简体   繁体   English

Python 3请求或urllib-如何始终添加标头?

[英]Python 3 Requests or urllib - how to always add a header?

Title says it all: is there a 'best' way to always add a header to every request? 标题说明了一切:是否有一种“最佳”方式始终向每个请求添加标头? I've got an internal tool that wants to send request ids to other internal tools; 我有一个内部工具,希望将请求ID发送给其他内部工具。 I'm looking for a blessed solution. 我正在寻找一种有福的解决方案。 I've skimmed the docs of both and it seems that this isn't a popular thing to ask for as I can't find a cookbook example. 我已经浏览了两者的文档,并且由于我找不到菜谱示例,所以这似乎不是一件很受欢迎的事情。

I'm thinking of a couple solutions: 我在考虑几个解决方案:

  1. Wrap requests in my own thin wrapper and use that. 用我自己的薄包装器包装请求并使用它。 Need to teach codevelopers to remember to not import requests but import myrequestswrapper as requests . 需要教导合作开发者记住不要import requests而是import myrequestswrapper as requests
  2. Monkey-patch requests. 猴子补丁请求。 I don't like monkey patching, but maybe just this once...? 我不喜欢猴子打补丁,但也许只是一次...? I dread the time when there comes a need to not send a header to this one particular system. 我害怕的时候,有那么需要一个头发送这一个特定的系统。

edit: Why I'm not considering a requests.Session: it stores cookies and needs to be disposed of as it keeps its connection open. 编辑:为什么我不考虑request.Session:它存储cookie,并需要保持连接打开状态进行处理。

Create a session object , which is the 1st thing shown under advanced usage : 创建一个会话对象 ,这是高级用法下显示的第一件事:

s = requests.Session()
s.headers.update({'x-some-header': 'the value'})
s.get('http://httpbin.org/headers')

and use the session to perform requests. 并使用会话执行请求。 As you've stated that you do not wish to persist cookies between requests, you could subclass the Session : 如前所述,您不想在请求之间保留cookie,可以将Session子类化:

In [64]: from requests.adapters import HTTPAdapter

In [65]: from requests.cookies import cookiejar_from_dict

In [66]: class CookieMonsterSession(Session):
    ...:     
    ...:     def __init__(self, *args, **kwgs):
    ...:         super(CookieMonsterSession, self).__init__(*args, **kwgs)
    ...:         # Override default adapters with 0-pooling adapters
    ...:         self.mount('https://', HTTPAdapter(pool_connections=1,
    ...:                                            pool_maxsize=0))
    ...:         self.mount('http://', HTTPAdapter(pool_connections=1,
    ...:                                           pool_maxsize=0))
    ...:     @property
    ...:     def cookies(self):
    ...:         """ Freshly baked cookies, always!"""
    ...:         return cookiejar_from_dict({})
    ...:     @cookies.setter
    ...:     def cookies(self, newcookies):
    ...:         """ OM NOM NOM NOM..."""
    ...:         pass
    ...:     

In [67]: s = CookieMonsterSession()

In [69]: real_s = Session()

In [70]: s.get('http://www.google.fi')
Out[70]: <Response [200]>

In [71]: s.cookies
Out[71]: <RequestsCookieJar[]>

In [72]: real_s.get('http://www.google.fi')
Out[72]: <Response [200]>

In [73]: real_s.cookies
Out[73]: <RequestsCookieJar[Cookie(version=0, name='NID', value='86=14qy...Rurx', port=None, port_specified=False, domain='.google.fi', domain_specified=True, domain_initial_dot=True, path='/', path_specified=True, secure=False, expires=1489744358, discard=False, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False)]>

It is unfortunate that the Session is by design difficult to extend and configure, so "disabling" cookies, and modifying pooling like this is a hack and prone to break, if and when Session is updated the slightest. 不幸的是, Session在设计上很难扩展和配置,因此“禁用” cookie并修改池这样的做法是很容易破解的,而且如果Session进行最细微的更新也很容易中断。 Also we've disabled the 2 main features of Session just for persistent headers. 另外,我们仅针对持久标头禁用了Session的2个主要功能。

Wrapping the basic API methods is probably the cleaner and safer approach: 包装基本的API方法可能是一种更清洁,更安全的方法:

# customrequests.py
from functools import wraps
from requests import api as requests_api

custom_headers = {}


def _header_wrapper(f):
    @wraps(f)
    def wrapper(*args, **kwgs):
        headers = kwgs.pop('headers', None) or {}
        headers.update(custom_headers)
        return f(*args, headers=headers, **kwgs)

    return wrapper

request = _header_wrapper(requests_api.request)
get = _header_wrapper(requests_api.get)
options = _header_wrapper(requests_api.options)
head = _header_wrapper(requests_api.head)
post = _header_wrapper(requests_api.post)
put = _header_wrapper(requests_api.put)
patch = _header_wrapper(requests_api.patch)
delete = _header_wrapper(requests_api.delete)

In action: 实际上:

In [1]: import customrequests as requests

In [2]: print(requests.get('http://httpbin.org/headers').text)
{
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.11.1"
  }
}


In [3]: requests.custom_headers['X-Test'] = "I'm always here"

In [4]: print(requests.get('http://httpbin.org/headers').text)
{
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.11.1", 
    "X-Test": "I'm always here"
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM