Отправка http-запросов с определенным / несуществующим протоколом http-версии в Python
Существует некоторый способ отправлять http-запросы в python с определенным протоколом http-версии. Я думаю, что с httplib или urllib это невозможно.
Например: GET / HTTP/6.9
Заранее спасибо.
3 ответа
Простой ответ на ваш вопрос: вы правы, ни httplib
ни urllib
имеет общедоступную встроенную функциональность для этого. (Кроме того, вы действительно не должны использовать urllib
для большинства вещей, в частности, для urlopen
.)
Конечно, вы всегда можете положиться на детали реализации этих модулей, как в ответе Лукаса Графа.
Или, в качестве альтернативы, вы можете разветвить один из этих модулей и изменить его, что гарантирует, что ваш код будет работать на других реализациях Python 2.x.*. Обратите внимание, что httplib
это один из тех модулей, который имеет ссылку на источник вверху, что означает, что он предназначен для сервера в качестве примера кода, а не просто для библиотеки черного ящика.
Или вы можете просто переопределить функцию самого низкого уровня, которую нужно подключить, но это публично задокументировано. За httplib
Я верю, что это httplib.HTTPConnection.putrequest
, что составляет несколько сотен строк.
Или вы можете выбрать другую библиотеку, в которой больше хуков, поэтому у вас меньше хуков.
Но на самом деле, если вы пытаетесь создать собственный запрос, чтобы вручную снять отпечатки пальцев, почему вы вообще используете HTTP-библиотеку? Почему бы просто не сделать это?
msg = 'GET / HTTP/6.9\r\n\r\n'
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.stackru.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