简体   繁体   English

urllib.Request 删除 Content-Type 标头

[英]urllib.Request remove Content-Type header

I want to remove the content-type header from a POST request.我想从 POST 请求中删除内容类型标头。 I have tried setting the header to ''我试过将标题设置为''

try:
    from urllib.request import Request, urlopen
except ImportError:
    from urllib2 import Request, urlopen

url = 'https://httpbin.org/post'
test_data = 'test'

req = Request(url, test_data.encode(), headers={'Content-Type': ''})
req.get_method = lambda: 'POST'
print(urlopen(req).read().decode())

But this sends:但这会发送:

{
  // ...
  "headers": {
     "Content-Type": "", // ...
  }
  // ...
}

What I would like it to do is send no Content-Type at all, instead of a blank one.我希望它做的是根本不发送 Content-Type,而不是发送一个空白的。 By default, it is application/x-www-form-urlencoded .默认情况下,它是application/x-www-form-urlencoded

This can easily be acheived with requests :这可以通过requests轻松实现:

print(requests.post(url, test_data).text)

But this is a script I need to distribute, so cannot have dependencies.但这是我需要分发的脚本,因此不能有依赖项。 I need it to have no Content-Type at all, since the server is very picky, so I cannot use text/plain or application/octet-stream .我需要它根本没有 Content-Type ,因为服务器非常挑剔,所以我不能使用text/plainapplication/octet-stream

You can specify custom handler:您可以指定自定义处理程序:

try:
    from urllib.request import Request, urlopen, build_opener, BaseHandler
except ImportError:
    from urllib2 import Request, urlopen, build_opener, BaseHandler

url = 'https://httpbin.org/post'
test_data = 'test'

class ContentTypeRemover(BaseHandler):
    def http_request(self, req):
        if req.has_header('Content-type'):
            req.remove_header('Content-type')
        return req
    https_request = http_request

opener = build_opener(ContentTypeRemover())
req = Request(url, test_data.encode())
print(opener.open(req).read().decode())

Another (hacky) way: monkey-patching the request object to pretend there's Content-type header already there;另一种(hacky)方式:猴子修补请求对象以假装已经存在Content-type标头; prevents AbstractHTTPHandler to default Content-Type header.防止AbstractHTTPHandler使用默认的 Content-Type 标头。

req = Request(url, test_data.encode())
req.has_header = lambda header_name: (header_name == 'Content-type' or
                                      Request.has_header(req, header_name))
print(urlopen(req).read().decode())

Just to add ontop of @falsetru's answer,只是为了添加@falsetru的答案,

If you need to filter more headers than this, req.headers is not the thing you want, it's more like this:如果你需要过滤比这更多的标题, req.headers不是你想要的,它更像是这样的:

class ContentTypeRemover(BaseHandler):
    def __init__(self, headers_to_filter={'Content-type'}): # set or dict works
        self.headers_to_filter = headers_to_filter

    def http_request(self, req):
        for header, value in req.header_items():
            if header in self.headers_to_filter:
                req.remove_header(header)
        return req
    https_request = http_request

And if you need to modify a header, not remove it.. It gets a bit weird (at least this is the only method I've found to be working):如果你需要修改一个标题,而不是删除它......它变得有点奇怪(至少这是我发现唯一有效的方法):

req.remove_header(header)
req.add_header(header, self.modify_headers[header.lower()])

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

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