Выполнение запроса POST с использованием urllib с несколькими заголовками дает ошибку 400 Bad Request - PullRequest
0 голосов
/ 27 ноября 2018

Я использовал библиотеку requests и знаю, как с ней работать, но мне нужно работать только со стандартной библиотекой, поэтому я был бы признателен, если бы вы не рекомендовали мне использовать requests.

Я создал сервер-колбу, который обрабатывает запросы POST, а затем из другого сценария я вызываю urllib , чтобы выполнять вызовы POST на сервере-колбе. Мне нужно отправить сырой json в теле, как мы делаем в Почтальоне.

Flask Server

from flask import Flask, request

app = Flask(__name__)
@app.route('/random', methods=['POST'])
def random():
    if request.method == 'POST':
        if request.headers.get('Authorization') and request.headers.get('Content-Type') == 'application/json':
            print(request.get_json())
            return "Success"
        else:
            print(request.get_json())
            return "Bad request"

app.run(host='0.0.0.0', port=5000, debug=True)

Urllib Client (сохранено как test.py) -

import urllib.request
import urllib.parse
d = {"spam": 1, "eggs": 2, "bacon": 0}
data = urllib.parse.urlencode(d)
data = data.encode()
req = urllib.request.Request("http://localhost:5000/random", data)
req.add_header('Content-Type', 'application/json')
req.add_header('Authorization', 12345)
with urllib.request.urlopen(req) as f:
    print(f.read().decode('utf-8'))

Только с заголовком Авторизация Я получаю Bad Request в качестве вывода, а json равен None на стороне сервера фляги как и ожидалось .

С ТОЛЬКО заголовком Content-Type ИЛИ обоими заголовками я получаю эту ошибку -

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    with urllib.request.urlopen(req) as f:
  File "C:\ProgramData\Anaconda3\lib\urllib\request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "C:\ProgramData\Anaconda3\lib\urllib\request.py", line 532, in open
    response = meth(req, response)
  File "C:\ProgramData\Anaconda3\lib\urllib\request.py", line 642, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\ProgramData\Anaconda3\lib\urllib\request.py", line 570, in error
    return self._call_chain(*args)
  File "C:\ProgramData\Anaconda3\lib\urllib\request.py", line 504, in _call_chain
    result = func(*args)
  File "C:\ProgramData\Anaconda3\lib\urllib\request.py", line 650, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 400: BAD REQUEST

Все достаточно просто, но я не могу понять, почему это происходит, исообщение об ошибке тоже мало помогает.

1 Ответ

0 голосов
/ 27 ноября 2018

Сбой сервера в request.get_json().Это происходит только тогда, когда клиент отправляет оба заголовка, потому что именно тогда он достигает этой строки.

Чтобы исправить это, измените клиент так, чтобы он отправлял данные в формате JSON:

import json            # <-- Import json
import urllib.request
import urllib.parse

d = {"spam": 1, "eggs": 2, "bacon": 0}
data = json.dumps(d)   # <-- Dump the dictionary as JSON
data = data.encode()
req = urllib.request.Request("http://localhost:5000/random", data)
req.add_header('Content-Type', 'application/json')
req.add_header('Authorization', 12345)
with urllib.request.urlopen(req) as f:
    print(f.read().decode('utf-8'))

Надеюсь, это поможет

...