15

I have a script that makes some requests with urllib2.

I use the trick suggested elsewhere on Stack Overflow to bind another ip to the application, where my my computer has two ip addresses (IP A and IP B).

I would like to switch to using the requests library. Does anyone knows how I can achieve the same functionality with that library?

Community
  • 1
  • 1
Giorgos Komnino
  • 433
  • 1
  • 7
  • 20
  • Have you tried the monkey patching method mentioned in the link you provided? Did it not work? I've never looked into the `requests` lib, but somewhere in there a socket must be getting created. – tMC Sep 25 '12 at 14:50
  • Requests uses urllib3 and it seems like the feature you're after belongs to the latter. – Piotr Dobrogost Oct 06 '12 at 08:49

3 Answers3

22

Looking into the requests module, it looks like it uses httplib to send the http requests. httplib uses socket.create_connection() to connect to the www host.

Knowing that and following the monkey patching method in the link you provided:

import socket

real_create_conn = socket.create_connection

def set_src_addr(*args):
    address, timeout = args[0], args[1]
    source_address = ('IP_ADDR_TO_BIND_TO', 0)
    return real_create_conn(address, timeout, source_address)

socket.create_connection = set_src_addr

import requests
r = requests.get('http://www.google.com')

It looks like httplib passes all the arguments (to create_connection()) as args (vs keywords) as trying to extend the kwargs dict inside set_src_addr was failing. I believe the above is what you want, but I don't have a dual homed machine to test on.

tMC
  • 18,105
  • 14
  • 62
  • 98
  • Yeah, just tested this too. Using `nc -nlvp 8080` I get the output of my default IP and not my bind IP. – Allison Sep 21 '17 at 03:07
1

actually, you should bind IP to requests like this :

import urllib3
real_create_conn = urllib3.util.connection.create_connection

def set_src_addr(address, timeout, *args, **kw):
    source_address = ('YOUR_BIND_IP', 0)
    return real_create_conn(address, timeout=timeout, source_address=source_address)

urllib3.util.connection.create_connection = set_src_addr

import requests
r = requests.get('http://ipecho.net/plain')
print( r.text)
Hossin Asaadi
  • 367
  • 6
  • 13
1

Reposting my answer from a duplicate question, as I believe it is a cleaner solution:

You can use a SourceAddressAdapter from requests-toolbelt:

import requests
from requests_toolbelt.adapters import source

source = source.SourceAddressAdapter('127.0.0.1')

with requests.Session() as session:
    session.mount('http://', source)
    r = session.get("http://example.com/foo/bar")
Pelle
  • 1,222
  • 13
  • 18