3

我一直在试验这个论坛的一些代码。到目前为止,它可以接收在 curl POST 请求中传递的 json 片段,但现在我正在尝试向它发送一个小的 .jpg 文件。它同时以多种方式失败,但我对如何出现这些问题中的第一个感到困惑。

我的代码如下所示:

from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
from cgi import parse_header, parse_multipart

class ReportHandler(BaseHTTPRequestHandler):
    def do_HEAD(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def parse_POST(self):
        print(self.headers)
        ctype, pdict = parse_header(self.headers['content-type'])
        print("ctype", ctype, ctype == 'application/octet-stream')
        print(pdict)
        if ctype == 'multipart/form-data':
            postvars = parse_multipart(self.rfile, pdict)
        elif ctype == 'application/x-www-form-urlencoded' or 'application/json':   
            print("here!")
            length = int(self.headers['content-length'])
            postvars = parse_qs(
                self.rfile.read(length).decode('utf8'),
                keep_blank_values=1)
            print(postvars)
        elif ctype == 'application/octet-stream':
            print("octet stream header")

        else:
            print("nothing")
            postvars = {}
            a = self.rfile
            print(dir(a))
            print(a.peek())
        return postvars

    def do_POST(self):
        postvars = self.parse_POST()
        print(postvars)
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()



def main():
    server = HTTPServer(('', 8088), ReportHandler)
    try:
        print('Started http server')
        server.serve_forever()
    except KeyboardInterrupt:
        print('^C received, shutting down server')
        server.socket.close()

if __name__ == "__main__":
    main()

然后我在另一个终端中输入 curl 命令,如下所示:

curl --request POST -H "Content-Type:application/octet-stream"  --data-binary "@test.jpg"  http://127.0.0.1:8088

它返回以下输出和错误跟踪:

python receive_requests.py 
Started http server
Host: 127.0.0.1:8088
User-Agent: curl/7.52.1
Accept: */*
Content-Type: application/octet-stream
Content-Length: 16687
Expect: 100-continue


ctype application/octet-stream True
{}
here!
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 52056)
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/socketserver.py", line 317, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/local/lib/python3.6/socketserver.py", line 348, in process_request
    self.finish_request(request, client_address)
  File "/usr/local/lib/python3.6/socketserver.py", line 361, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/local/lib/python3.6/socketserver.py", line 721, in __init__
    self.handle()
  File "/usr/local/lib/python3.6/http/server.py", line 418, in handle
    self.handle_one_request()
  File "/usr/local/lib/python3.6/http/server.py", line 406, in handle_one_request
    method()
  File "receive_requests.py", line 42, in do_POST
    postvars = self.parse_POST()
  File "receive_requests.py", line 27, in parse_POST
    self.rfile.read(length).decode('utf8'),
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
----------------------------------------

所以编码有一个错误,但我真正想知道的是它是如何结束的:

elif ctype == 'application/x-www-form-urlencoded' or 'application/json':

..尽管

print("ctype", ctype, ctype == 'application/octet-stream')

给予

>>> ctype application/octet-stream True

If anyone knows how to fix this code so it receives the binary file please post it, otherwise how does it manage to go to the wrong elif option? Is there something about headers or the behaviour of curl which I am missing?

4

1 回答 1

4

Your condition will always return True. A non-empty string evaluates to True:

elif ctype == 'application/x-www-form-urlencoded' or 'application/json':

It should be:

elif ctype == 'application/x-www-form-urlencoded' or ctype == 'application/json':

or

elif ctype in ('application/x-www-form-urlencoded', 'application/json'):
于 2018-12-10T17:06:18.553 回答