Как я могу отправлять и получать запросы HTTP POST в Python?
У меня есть два скрипта Python, которые я использую, чтобы попытаться выяснить, как отправлять и получать запросы POST в Python:
Клиент:
import httplib
conn = httplib.HTTPConnection("localhost:8000")
conn.request("POST", "/testurl")
conn.send("clientdata")
response = conn.getresponse()
conn.close()
print(response.read())
Сервер:
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
ADDR = "localhost"
PORT = 8000
class RequestHandler(BaseHTTPRequestHandler):
def do_POST(self):
print(self.path)
print(self.rfile.read())
self.send_response(200, "OK")
self.end_headers()
self.wfile.write("serverdata")
httpd = HTTPServer((ADDR, PORT), RequestHandler)
httpd.serve_forever()
Проблема заключается в том, что сервер зависает на self.rfile.read() до тех пор, пока conn.close() не будет вызван на клиенте, но если на клиенте вызывается conn.close(), клиент не может получить ответ от сервера. Это создает ситуацию, когда можно либо получить ответ от сервера, либо прочитать данные POST, но не оба одновременно. Я предполагаю, что есть кое-что, что я пропускаю здесь, чтобы решить эту проблему
Дополнительная информация:
conn.getresponse () заставляет клиента зависать до тех пор, пока ответ не будет получен с сервера. Ответ не будет получен до тех пор, пока функция на сервере не завершит выполнение.
2 ответа
Есть несколько проблем с вашим оригинальным примером. Во-первых, если вы используете request
метод, вы должны включить тело сообщения, которое вы хотите отправить в этот вызов, а не вызов send
по отдельности. Примечания к документации send() могут использоваться как альтернатива request
:
В качестве альтернативы использованию метода request(), описанного выше, вы также можете пошагово отправлять запрос, используя четыре функции ниже.
Ты просто хочешь conn.request("POST", "/testurl", "clientdata")
,
Вторая проблема заключается в том, как вы пытаетесь прочитать то, что отправлено на сервер. self.rfile.read()
пытается прочитать весь входной поток, поступающий от клиента, что означает, что он будет блокироваться, пока поток не будет закрыт. Поток не будет закрыт, пока не будет закрыто соединение. Что вы хотите сделать, это прочитать точно, сколько байтов было отправлено с клиента, и все. Откуда ты знаешь, сколько это байтов? Заголовки, конечно:
length = int(self.headers['Content-length'])
print(self.rfile.read(length))
Я очень рекомендую библиотеку Python-запросов, если вы собираетесь делать больше, чем самые простые тесты. Я также рекомендую использовать лучший HTTP-фреймворк / сервер, чем BaseHTTPServer, для более простых тестов (фляжка, бутылка, торнадо и т. Д.).
Давно отвечал, но пришел во время обыска, поэтому я привожу еще один ответ. Чтобы сервер не оставил поток открытым (в результате чего ответ никогда не отправлялся), вы должны использовать
self.rfile.read1()
вместо
self.rfile.read()