Python:带有自定义标头的请求失败

时间:2018-06-28 01:15:04

标签: python python-3.x

我在使用自定义标头进行发布请求时遇到一些问题。 我正在使用Requests库,并作为端点jsonplaceholder,在这里您可以通过POST请求获得伪造的JSON。

我用

调用脚本
py request.py

// request.py

import requests
import json
from pprint import pprint

def postReqCustom( url, headers, data):
    print('Making request to: ', url)
    r = requests.post(url, headers=headers, data=data)

    print('status code: ' + str(r.status_code))

    response = r.json()
    pprint(response)

def postReq( url, data):
    print('Making request to: ', url)
    r = requests.post(url, data=data)

    print('status code: ' + str(r.status_code))

    response = r.json()
    pprint(response)

headers = {'content-type': 'application/json'}

data = {
            "title": "foo",
            "body": "bar",
            "userId": 1
            }
post_url = "https://jsonplaceholder.typicode.com/posts"

#postReq(post_url, data) #ok
postReqCustom(post_url, headers, data) #error

对于postReq,我没有收到任何错误(状态码201),但是当我尝试使用自定义标头进行postReqCustom时,却遇到了以下错误:

Making request to:  https://jsonplaceholder.typicode.com/posts
status code: 500
Traceback (most recent call last):
  File "request.py", line 55, in <module>
    postReqCustom(post_url, headers, payload)
  File "request.py", line 24, in postReqCustom
    response = r.json()
  File "C:\Users\Samy\AppData\Local\Programs\Python\Python36-32\lib\site-packages\requests\models.py", line 892, in json
    return complexjson.loads(self.text, **kwargs)
  File "C:\Users\Samy\AppData\Local\Programs\Python\Python36-32\lib\json\__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "C:\Users\Samy\AppData\Local\Programs\Python\Python36-32\lib\json\decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Users\Samy\AppData\Local\Programs\Python\Python36-32\lib\json\decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

2 个答案:

答案 0 :(得分:2)

问题是您正在使用data=data。与the docs explain一样,如果您使用此参数并传递除字符串以外的任何内容, 1 它将对数据进行形式编码,如下所示:

title=foo&body=bar&userId=1

默认情况下,它还将Content-Type标头设置为application/x-www-form-urlencoded,因此一切正常。

但是,如果您使用application/json覆盖该标头,那么现在将服务器主体title=foo&body=bar&userId=1传递给服务器,并告诉服务器将其解码为JSON。当然哪个会失败,所以服务器给您一个错误也就不足为奇了。 2


如果您希望您的值采用JSON编码而不是形式编码,请使用json参数,而不要使用data参数:

r = requests.post(url, headers=headers, json=data)

此JSON编码数据,如下所示:

{"title": "foo", "body": "bar", "userId": 1}

它还将默认将Content-Type设置为application/json,因此一切正常。当然,如果您用相同的值覆盖相同的标头,它将仍然具有相同的作用。


如果要手动进行编码并发送任何编码的字符串,可以使用data,但随后必须发送一个字符串。例如(直接从同一“文档”部分中删除):

r = requests.post(url, headers=headers, data=json.dumps(data))

1。此处将Unicode str以及类似编码的bytesbytes的类型都视为字符串,但这在快速入门教程中没有说明。

2。当然,真正的服务器应该并且可能会返回一个400 Bad Request,而不是尝试执行没有意义的操作,遇到意外错误并仅仅使用500 Internal Server Error。 sub>

答案 1 :(得分:-1)

细读代码后;我可以说您正确实现了自定义标头。看完用于模拟REST端点的服务后,似乎它不接受application / json MIME类型。这是您的端点接受的内容:

text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

在将标头字典更改为“ Content-Type”:“ text / xml”后,一切运行良好(得到201):

import requests
import json
from pprint import pprint

def postReqCustom( url, headers, data):
    print('Making request to: ', url)
    r = requests.post(url, headers=headers, data=data)

    print('status code: ' + str(r.status_code))

    response = r.raise_for_status()
    pprint(response)

def postReq( url, data):
    print('Making request to: ', url)
    r = requests.post(url, data=data)

    print('status code: ' + str(r.status_code))

    response = r.json()
    pprint(response)

headers = {'content-type': 'application/xml'}

data = {
            "title": "foo",
            "body": "bar",
            "userId": 1
            }
post_url = "https://jsonplaceholder.typicode.com/posts"
postReqCustom(post_url, headers, data)