83 votes

Python urllib2, authentification HTTP de base, et tr.im

Je suis en train de jouer autour, essayer d'écrire un peu de code pour utiliser le http://tr.im Api (http://tr.im/api/) pour raccourcir une URL.

Après la lecture de http://docs.python.org/library/urllib2.html, j'ai essayé:

   TRIM_API_URL = 'http://api.tr.im/api'
   auth_handler = urllib2.HTTPBasicAuthHandler()
   auth_handler.add_password(realm='tr.im',
                             uri=TRIM_API_URL,
                             user=USERNAME,
                             passwd=PASSWORD)
   opener = urllib2.build_opener(auth_handler)
   urllib2.install_opener(opener)
   response = urllib2.urlopen('%s/trim_simple?url=%s'
                              % (TRIM_API_URL, url_to_trim))
   url = response.read().strip()

réponse.code 200 (je pense qu'il devrait être 202). l'url est valide, mais l'authentification HTTP de base ne semble pas avoir fonctionné, parce que le URL raccourcie n'est pas dans ma liste d'Url (à http://tr.im/?page=1).

Après la lecture de http://www.voidspace.org.uk/python/articles/authentication.shtml#doing-it-properly J'ai aussi essayé:

   TRIM_API_URL = 'api.tr.im/api'
   password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
   password_mgr.add_password(None, TRIM_API_URL, USERNAME, PASSWORD)
   auth_handler = urllib2.HTTPBasicAuthHandler(password_mgr)
   opener = urllib2.build_opener(auth_handler)
   urllib2.install_opener(opener)
   response = urllib2.urlopen('http://%s/trim_simple?url=%s'
                              % (TRIM_API_URL, url_to_trim))
   url = response.read().strip()

Mais j'obtiens les mêmes résultats. (la réponse.le code est 200 et l'url est valide, mais pas enregistré dans mon compte à l' http://tr.im/.)

Si j'utilise des paramètres de chaîne de requête à la place de l'authentification HTTP de base, comme ceci:

   TRIM_API_URL = 'http://api.tr.im/api'
   response = urllib2.urlopen('%s/trim_simple?url=%s&username=%s&password=%s'
                              % (TRIM_API_URL,
                                 url_to_trim,
                                 USERNAME,
                                 PASSWORD))
   url = response.read().strip()

...alors, non seulement est une url valide, mais c'est inscrit dans mes tr.compte de messagerie instantanée. (Si réponse.le code est toujours de 200.)

Il doit y avoir quelque chose de mal avec mon code si (et pas tr.im API), parce que

$ curl -u yacitus:xxxx http://api.tr.im/api/trim_url.json?url=http://www.google.co.uk

...retourne:

{"trimpath":"hfhb","reference":"nH45bftZDWOX0QpVojeDbOvPDnaRaJ","trimmed":"11\/03\/2009","destination":"http:\/\/www.google.co.uk\/","trim_path":"hfhb","domain":"google.co.uk","url":"http:\/\/tr.im\/hfhb","visits":0,"status":{"result":"OK","code":"200","message":"tr.im URL Added."},"date_time":"2009-03-11T10:15:35-04:00"}

...et l'URL n'apparaît pas dans ma liste d'Url sur http://tr.im/?page=1.

Et si je lance:

$ curl -u yacitus:xxxx http://api.tr.im/api/trim_url.json?url=http://www.google.co.uk

...encore une fois, j'obtiens:

{"trimpath":"hfhb","reference":"nH45bftZDWOX0QpVojeDbOvPDnaRaJ","trimmed":"11\/03\/2009","destination":"http:\/\/www.google.co.uk\/","trim_path":"hfhb","domain":"google.co.uk","url":"http:\/\/tr.im\/hfhb","visits":0,"status":{"result":"OK","code":"201","message":"tr.im URL Already Created [yacitus]."},"date_time":"2009-03-11T10:15:35-04:00"}

Remarque le code est 201, et le message est "tr.im URL Déjà Créé [yacitus]."

Je ne dois pas être en train de faire l'authentification HTTP de base correctement (à essayer). Pouvez-vous repérer mon problème? Peut-être que je devrais regarder et de voir ce qui est envoyé sur le fil? Je n'ai jamais fait ça avant. Sont là Python Api que je peux utiliser (peut-être dans apb)? Ou est-il un autre outil (de préférence pour Mac OS X) je peux utiliser?

243voto

Flowpoke Points 2544

Cela semble fonctionner vraiment bien (prises à partir d'un autre thread)

import urllib2, base64

request = urllib2.Request("http://api.foursquare.com/v1/user")
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
request.add_header("Authorization", "Basic %s" % base64string)   
result = urllib2.urlopen(request)

20voto

Ali Afshar Points 22836

Vraiment pas cher solution:

urllib2.urlopen('http://user:xxxx@api.tr.im/api')

(que vous pouvez décider n'est pas adapté pour un certain nombre de raisons, comme la sécurité de l'url)

13voto

Mark Mikofski Points 2503

Jetez un oeil à cette SORTE de post de réponse et aussi regarder ce authentification de base tutoriel de la urllib2 manuel.

Pour urllib2 l'authentification de base pour le travail, l'adresse http de la réponse doit contenir le code HTTP 401 non autorisé et une touche "WWW-Authenticate" avec la valeur "Basic" sinon, Python ne transmettrons pas vos informations de connexion, et vous aurez besoin d'utiliser soit des Demandes, ou urllib.urlopen(url) avec votre identifiant dans l'url, ou ajouter l'en-tête comme dans @Flowpoke de réponse.

Vous pouvez afficher votre erreur en mettant votre urlopen dans un bloc try:

try:
    urllib2.urlopen(urllib2.Request(url))
except urllib2.HTTPError, e:
    print e.headers
    print e.headers.has_key('WWW-Authenticate')

3voto

dnozay Points 3672

Mêmes solutions que Python urllib2 Basic Auth Problème s'appliquent.

voir http://stackoverflow.com/a/24048852/1733117; vous pouvez sous-classe urllib2.HTTPBasicAuthHandler ajouter l' Authorization d'en-tête pour chaque demande correspond à l'url connue.

class PreemptiveBasicAuthHandler(urllib2.HTTPBasicAuthHandler):
    '''Preemptive basic auth.

    Instead of waiting for a 403 to then retry with the credentials,
    send the credentials if the url is handled by the password manager.
    Note: please use realm=None when calling add_password.'''
    def http_request(self, req):
        url = req.get_full_url()
        realm = None
        # this is very similar to the code from retry_http_basic_auth()
        # but returns a request object.
        user, pw = self.passwd.find_user_password(realm, url)
        if pw:
            raw = "%s:%s" % (user, pw)
            auth = 'Basic %s' % base64.b64encode(raw).strip()
            req.add_unredirected_header(self.auth_header, auth)
        return req

    https_request = http_request

0voto

Andrew G Points 241

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X