получить бинарный файл из запроса POST с BaseHTTPRequestHandler - PullRequest
0 голосов
/ 10 декабря 2018

Я экспериментировал с кодом из этого форума .До сих пор все работало нормально, чтобы получить кусочки json, доставленные в curl POST-запросах, но сейчас я пытаюсь отправить ему небольшой файл .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

Если кто-нибудь знает, как исправить этот код, чтобы он получал двоичный файл, пожалуйста, опубликуйте его, в противном случае, как ему удается перейти на неправильный elifвариант?Есть ли что-то в заголовках или в поведении curl, которое мне не хватает?

1 Ответ

0 голосов
/ 10 декабря 2018

Ваше состояние всегда вернет True.Непустая строка оценивается как True:

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

Это должно быть:

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

или

elif ctype in ('application/x-www-form-urlencoded', 'application/json'):
...