python requests post リクエスト送信時に、header を設定する


python requests を使って、
post 送信時に、header を付与しようとして、
少しうまくいかなかったので、うまくいかなかった話を記載します。


どう書けばよいのか

クイックスタート — requests-docs-ja 1.0.4 documentation
に記載がありますが、post 送信時に header を送信する場合は、以下のように記述します。

import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
headers = {'content-type': 'application/json'}
r = requests.post(url, data=json.dumps(payload), headers=headers)


headers に json を送るとどうなるか

以下のようにな実装で、headers に json 文字列を指定すると、

response = requests.post(BATCH_GET_API_URL,
                            data=json_data,
                            headers=json.dumps(headers))

以下のエラーを吐いて落ちます。

Traceback (most recent call last):
  File "batch_get_amp_url.py", line 36, in <module>
    execute()
  File "batch_get_amp_url.py", line 26, in execute
    headers=json.dumps(headers))
  File "/Library/Python/2.7/site-packages/requests/api.py", line 112, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/Library/Python/2.7/site-packages/requests/api.py", line 58, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Library/Python/2.7/site-packages/requests/sessions.py", line 504, in request
    prep = self.prepare_request(req)
  File "/Library/Python/2.7/site-packages/requests/sessions.py", line 436, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "/Library/Python/2.7/site-packages/requests/models.py", line 303, in prepare
    self.prepare_headers(headers)
  File "/Library/Python/2.7/site-packages/requests/models.py", line 441, in prepare_headers
    for header in headers.items():
AttributeError: 'str' object has no attribute 'items'

post するデータが json 文字列だからといって、header が json とは限らないということかと
思います。


application/x-www-form-urlencoded を Content-Type に設定する

JSON 形式ではない通常の Form のデータを POST する際の Content-Type ですが、 辞書形式の data を設定して POST すると、Content-Type に、application/x-www-form-urlencoded が設定されます。
requests/models.py at master · requests/requests あたりで、data として設定した形式により、自動的に Contents-type を判定するようです。

        json_data = request.data
        payload = {"v": "1", 
                   "t": "event", 
                   "tid": "UA-XXXXXXXX-X",
                   "cid": json_data.get("userId", ""),
                   "hl": "ja",
                   "ni": "1",
                   "ec": "Notification",
                   "ea": json_data.get("event", ""),
                   "el": json_data.get("heading", "")
                  }
        r = requests.post("https://www.google-analytics.com/collect", payload)
以下の記事が参考になりました。

以上です。

コメント