通过特定网络接口发送http请求

时间:2018-02-26 20:22:29

标签: python python-requests

我有两个网络接口(wifi和以太网)都可以上网。假设我的接口是eth(以太网)和wlp2(wifi)。我需要通过eth通过wpl2界面和其他人请求具体请求。

类似的东西:

// Through "eth"
request.post(url="http://myapi.com/store_ip", iface="eth")
// Through "wlp2" 
request.post(url="http://myapi.com/log", iface="wlp2")

我正在使用requests,但如果pycurl没有任何办法,我可以使用urllibrequests

How to specify source interface in python requests module?引用Requests, bind to an ip,但不起作用。

3 个答案:

答案 0 :(得分:6)

这是没有猴子修补任何内容的Requests库的解决方案。

此功能将创建一个绑定到给定IP地址的会话。由您决定所需网络接口的IP地址。

经过测试可与requests==2.23.0一起使用。

import requests


def session_for_src_addr(addr: str) -> requests.Session:
    """
    Create `Session` which will bind to the specified local address
    rather than auto-selecting it.
    """
    session = requests.Session()
    for prefix in ('http://', 'https://'):
        session.get_adapter(prefix).init_poolmanager(
            # those are default values from HTTPAdapter's constructor
            connections=requests.adapters.DEFAULT_POOLSIZE,
            maxsize=requests.adapters.DEFAULT_POOLSIZE,
            # This should be a tuple of (address, port). Port 0 means auto-selection.
            source_address=(addr, 0),
        )

    return session


# usage example:
s = session_for_src_addr('192.168.1.12')
s.get('https://httpbin.org/ip')

请注意,尽管这种方法与curl的{​​{1}}选项相同,但在某些情况下无济于事。根据您的路由配置,即使您绑定到特定的IP地址,请求也可能会通过其他接口发生。因此,如果此答案对您不起作用,请首先检查--interface是否可以按预期工作。

答案 1 :(得分:3)

我找到了使用pycurl的方法。这就像一个魅力。

import pycurl
from io import BytesIO
import json


def curl_post(url, data, iface=None):
    c = pycurl.Curl()
    buffer = BytesIO()
    c.setopt(pycurl.URL, url)
    c.setopt(pycurl.POST, True)
    c.setopt(pycurl.HTTPHEADER, ['Content-Type: application/json'])
    c.setopt(pycurl.TIMEOUT, 10)
    c.setopt(pycurl.WRITEFUNCTION, buffer.write)
    c.setopt(pycurl.POSTFIELDS, data)
    if iface:
        c.setopt(pycurl.INTERFACE, iface)
    c.perform()

    # Json response
    resp = buffer.getvalue().decode('UTF-8')

    #  Check response is a JSON if not there was an error
    try:
        resp = json.loads(resp)
    except json.decoder.JSONDecodeError:
        pass

    buffer.close()
    c.close()
    return resp


if __name__ == '__main__':
    dat = {"id": 52, "configuration": [{"eno1": {"address": "192.168.1.1"}}]}
    res = curl_post("http://127.0.0.1:5000/network_configuration/", json.dumps(dat), "wlp2")
    print(res)

我离开问题时,有人可以使用requests给出答案。

答案 2 :(得分:-1)

尝试在下面的代码中将内部IP(192.168.0.200)更改为相应的iface。

import requests
from requests_toolbelt.adapters import source

def check_ip(inet_addr):
    s = requests.Session()
    iface = source.SourceAddressAdapter(inet_addr)
    s.mount('http://', iface)
    s.mount('https://', iface)
    url = 'https://emapp.cc/get_my_ip'
    resp = s.get(url)
    print(resp.text)

if __name__ == '__main__':
    check_ip('192.168.0.200')