使用Python中特定/不存在的http版本协议发送http请求



有一些方法可以通过特定的http版本协议在python中发送http请求。我认为,使用httplib或urllib是不可能的。

例如:GET/HTTP/6.9

提前谢谢。

问题的简单答案是:你是对的,httpliburllib都没有公共的内置功能。(此外,对于大多数事情,您真的不应该使用urllib,尤其是urlopen。)

当然,您可以始终依赖这些模块的实现细节,正如Lukas Graf的回答所示。

或者,您也可以派生其中一个模块并对其进行修改,这可以保证您的代码可以在其他Python 2.x实现上运行。*。请注意,httplib是其中一个在顶部有指向源代码链接的模块,这意味着它意味着要作为示例代码而不仅仅是一个黑盒库来服务器。

或者,您可以重新实现需要挂接但已公开文档的最低级别功能。对于httplib,我相信这是httplib.HTTPConnection.putrequest,它有几百行长。

或者,你可以选择一个不同的库,它有更多的钩子,所以你要钩子的更少。

但实际上,如果你试图创建一个自定义请求来手动对结果进行指纹识别,你为什么要使用HTTP库呢?为什么不这么做呢?

msg = 'GET / HTTP/6.9rnrn'
s = socket.create_connection((host, 80))
with closing(s):
    s.send(msg)
    buf = ''.join(iter(partial(s.recv, 4096), ''))

*这并没有多大好处,因为永远不会有2.8,所有现有的主要2.7实现都共享该模块的相同来源,而且任何新的2.x实现都不太可能有任何不同。如果你转到3.x,httplib已经被重新组织和重命名,而urllib已经被完全删除,所以你已经有更大的变化需要担心了

通过对httplib.HTTPConnection进行子类化并重新定义类属性_http_vsn_str:,可以很容易地做到这一点

from httplib import HTTPConnection

class MyHTTPConnection(HTTPConnection):
    _http_vsn_str = '6.9'

conn = MyHTTPConnection("www.stackoverflow.com")
conn.request("GET", "/")
response = conn.getresponse()
print "Status: {} {}".format(response.status, response.reason)
print "Headers: {}".format(response.getheaders())
print "Body: {}".format(response.read())

当然,这将导致大多数服务器的400 Bad Request

Status: 400 Bad Request
Headers: [('date', 'Tue, 11 Nov 2014 21:21:12 GMT'), ('connection', 'close'), ('content-type', 'text/html; charset=us-ascii'), ('content-length', '311')]
Body: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request</h2>
<hr><p>HTTP Error 400. The request is badly formed.</p>
</BODY></HTML>

使用这个选项使用pycurl是可能的

c.setopt(pycurl.HTTP_VERSION, pycurl.CURL_HTTP_VERSION_1_0)

但是,您需要使用linux或mac,因为pycurl在windows 上不受官方支持

最新更新