web-dev-qa-db-fra.com

Comment puis-je obtenir l'adresse IP d'une requête http en utilisant la bibliothèque de requêtes?

Je fais des requêtes HTTP en utilisant la bibliothèque de requêtes en python, mais j'ai besoin de l'adresse IP du serveur qui a répondu à la demande http et j'essaie d'éviter de faire deux appels (et possiblement d'avoir une adresse IP différente de celle qui a répondu) la demande.

Est-ce possible? Est-ce qu'une bibliothèque http python http me permet de le faire?

ps: J'ai également besoin de faire des requêtes HTTPS et d'utiliser un proxy authentifié.

Mise à jour 1:

Exemple:

import requests

proxies = {
  "http": "http://user:[email protected]:3128",
  "https": "http://user:[email protected]:1080",
}

response = requests.get("http://example.org", proxies=proxies)
response.ip # This doesn't exist, this is just an what I would like to do

ensuite, je voudrais savoir à quelles demandes d'adresse IP connectées à partir d'une méthode ou d'une propriété dans la réponse. Dans d'autres bibliothèques, j'ai pu le faire en trouvant l'objet sock et en utilisant la méthode getpeername ().

22
gawry

Il s'avère que c'est plutôt impliqué.

Voici un patch de singe lors de l'utilisation de requests version 1.2.3:

Enveloppant la méthode _make_request Sur HTTPConnectionPool pour stocker la réponse de socket.getpeername() sur l'instance HTTPResponse.

Pour moi sur python 2.7.3, cette instance était disponible sur response.raw._original_response.

from requests.packages.urllib3.connectionpool import HTTPConnectionPool

def _make_request(self,conn,method,url,**kwargs):
    response = self._old_make_request(conn,method,url,**kwargs)
    sock = getattr(conn,'sock',False)
    if sock:
        setattr(response,'peer',sock.getpeername())
    else:
        setattr(response,'peer',None)
    return response

HTTPConnectionPool._old_make_request = HTTPConnectionPool._make_request
HTTPConnectionPool._make_request = _make_request

import requests

r = requests.get('http://www.google.com')
print r.raw._original_response.peer

Rendements:

('2a00:1450:4009:809::1017', 80, 0, 0)

Ah, si un proxy est impliqué ou si la réponse est fragmentée, le HTTPConnectionPool._make_request N'est pas appelé.

Voici donc une nouvelle version corrigeant httplib.getresponse À la place:

import httplib

def getresponse(self,*args,**kwargs):
    response = self._old_getresponse(*args,**kwargs)
    if self.sock:
        response.peer = self.sock.getpeername()
    else:
        response.peer = None
    return response


httplib.HTTPConnection._old_getresponse = httplib.HTTPConnection.getresponse
httplib.HTTPConnection.getresponse = getresponse

import requests

def check_peer(resp):
    orig_resp = resp.raw._original_response
    if hasattr(orig_resp,'peer'):
        return getattr(orig_resp,'peer')

Fonctionnement:

>>> r1 = requests.get('http://www.google.com')
>>> check_peer(r1)
('2a00:1450:4009:808::101f', 80, 0, 0)
>>> r2 = requests.get('https://www.google.com')
>>> check_peer(r2)
('2a00:1450:4009:808::101f', 443, 0, 0)
>>> r3 = requests.get('http://wheezyweb.readthedocs.org/en/latest/tutorial.html#what-you-ll-build')
>>> check_peer(r3)
('162.209.99.68', 80)

Également vérifié le fonctionnement avec des proxys définis; l'adresse proxy est retournée.


Mise à jour 2016/01/19

est offre ne alternative qui n'a pas besoin du patch singe :

rsp = requests.get('http://google.com', stream=True)
# grab the IP while you can, before you consume the body!!!!!!!!
print rsp.raw._fp.fp._sock.getpeername()
# consume the body, which calls the read(), after that fileno is no longer available.
print rsp.content  

Mise à jour 2016/05/19

D'après les commentaires, en copiant ici pour la visibilité, Richard Kenneth Niescior offre ce qui suit qui est confirmé en travaillant avec les requêtes 2.10.0 et Python 3.

rsp=requests.get(..., stream=True)
rsp.raw._connection.sock.getpeername()

Mise à jour 22/02/2019

Python3 avec requêtes version 2.19.1.

resp=requests.get(..., stream=True)
resp.raw._connection.sock.socket.getsockname()

Mise à jour 2020/01/31

Python3.8 avec requêtes 2.22.0

resp = requests.get('https://www.google.com', stream=True)
resp.raw._connection.sock.getsockname()
37
MattH