无法从POST请求python获取响应体

时间:2013-12-19 19:20:30

标签: python post request response

我正在尝试在python中编写简单的应用程序,它将使用POST HTTP方法向服务器发送一些文本,然后获得包含一些文本的响应。

服务器:

from http.server import *
class MyServer(BaseHTTPRequestHandler):

    def do_POST(self):
        self.send_response(200)
        self.send_header("Content-type","text/plain")
        self.end_headers()
        print(self.rfile.read().decode("UTF-8"))
        self.wfile.write(bytes("TEST RESPONSE", "UTF-8"))

address = ("",8000)
httpd = HTTPServer(address, MyServer)
httpd.serve_forever()

客户端:

import http.client
class client:
    def __init__(self):
        h = self.request("127.0.0.1:8000", "POST", "OH YEA")
        resp = h.getresponse()
        print(resp.status)
        #data = resp.read()


    def request(self, host, metoda, strona):
        headers = { "Host" : host, "Accept": r"text/plain" }
        h = http.client.HTTPConnection(host)
        h.request(metoda,"",strona,headers)
        return h

a = client()

只要行数据= resp.read()仍然注释一切正常(服务器获取请求打印到它的控制台主体并发送响应)但当我尝试读取响应体服务器不打印请求体并且我没有得到,即使我得到响应状态200我也无法读取响应体(整个应用程序“挂断”)。我究竟做错了什么?我猜测服务器的行为与未完成的响应处理有关但我无法完成它因为我无法获得响应体。

1 个答案:

答案 0 :(得分:1)

您错过了HTTP响应中的Content-Length标头。 HTTP客户端不知道响应何时完成,因此它会继续等待更多。:

def do_POST(self):
    content = bytes("TEST RESPONSE", "UTF-8")
    self.send_response(200)
    self.send_header("Content-type","text/plain")
    self.send_header("Content-Length", len(content))
    self.end_headers()
    print(self.rfile.read().decode("UTF-8"))
    self.wfile.write(content)

这还不完全有效:服务器有同样的问题:它只是继续从rfile读取。

def do_POST(self):
    content = bytes("TEST RESPONSE", "UTF-8")
    self.send_response(200)
    self.send_header("Content-type","text/plain")
    self.send_header("Content-Length", len(content))
    self.end_headers()
    print(self.rfile.read(int(self.headers['Content-Length'])).decode("UTF-8"))
    self.wfile.write(content)

使用curl,这很好用:

$ curl -X POST http://localhost:8000 -d 'testrequest'
TEST RESPONSE

有一些方法可以在没有Content-Length标题的情况下执行此操作,但首先,这应该足够了。

编辑:这是编写HTTP客户端/服务器的一个很好的练习,但是对于生产用途,您可能需要考虑更多高级抽象,例如客户端的requests一边和WSGI或服务器端的完整网络框架(FlaskDjango都是受欢迎的选择,具体取决于您的要求)。