16

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 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?

2
  • 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. Commented Sep 25, 2012 at 14:50
  • Requests uses urllib3 and it seems like the feature you're after belongs to the latter. Commented Oct 6, 2012 at 8:49

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, just tested this too. Using nc -nlvp 8080 I get the output of my default IP and not my bind IP.
2

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)

Comments

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")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.