requestでPOSTした送信内容(data)を確認したい！

## 背景
PythonでコーディングしていくうえでRequestsモジュールを利用し、Webコンテンツを取得したりWebAPIを叩いたりするケースがあります。
これまではその時の実際のrequestの内容までは、あまり確認したいというケースはありませんでした。
そりゃぁそうです。自分でHeaderやBodyのデータを自分でセットしているんですから、それを確認すれば良いんです。
そしてWebブラウザ上でJavaScriptとかから送信している場合は、Chromeのデベロッパーツールを使えばPOST通信時に送信したパラメータは簡単に確認できます。

今回、訳あってRequestsモジュールで実際に送っているデータを確認する方法を探したのですが、無いのです！ 有ってもおかしくはない機能かと思うのですが、見つかりません！！
本当に無いの？？ 私が探し当てられなかっただけなの？？

`Requests.session.get('body')` こんな感じで、取得できたら良かったのですが…
できなかった…
（だれか、知っている人がいらっしゃいましたら…　おせーてくださいませ）

## そんなわけで…
まぁ、無いなら自分のWebサーバーに向けてrequestして、そのデータを見れば良いでしょう…
と、思ったのですが、なんだかわざわざFlaskを使ってアプリを書くのも面倒で、世の中の人はどう実現しているのか探ってみたところ、
もう…　これでしょ！ という事例が見つかりましたぁ。

　『[curlのGET,POSTのデータを確認](https://qiita.com/tkj/items/210a66213667bc038110)』https://qiita.com/tkj/items/210a66213667bc038110

を参考にさせてもらいました。ありがとうございます。

この方法であれば、わざわざサーバーを使う必要なく、手元（ローカル）の環境で確認ができます。簡単簡単！！

## やってみましょう。
なぜそこまでして、requestの内容を確認したかったかというと…
業務の自動化を図るために、社内のWebシステムにファイルをアップロードする仕組みを作っています。この仕組みは、WebAPIとして稼働していて、ビジネスロジックを担当するアプリケーションが、BLOBでファイルをこのWebAPIに渡してくれると、このWebAPIが社内のWebシステムにファイルをアップロードするというものです。

社内のWebシステムにはいろいろ＂仕来り＂がありますので、その辺をWebAPIが担当し、アプリケーションは簡単に社内のWebシステムにアップロードできるようなカラクリにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726928/d1e3e04b-3b9e-269d-a140-634348b86b4a.png)



この時、社内のWebシステムは＂multipart/form-data＂で受けるようになっています。
なので、ローカルのファイルであれば、こんな感じでアップロードできることは確認しています。
```python
import Requests
URL      = 'https://社内のWebシステム.com/アプリ/アップロード/'
FILES 　　　　　　= {'{{FORM_NAME}}': open('アップロードするファイルのPATH', 'rb')}
response = requests.post(URL, files=FILES)
```

しかし、WebAPIはビジネスロジック（アプリケーション）から受けたBLOBを、テンポラリファイルとして保存はしたくはないのです。
せっかくWebAPIはBLOBとして受けているのですから、そのまま io.BytesIO(ファイルの内容) でファイルとして扱いたいじゃないですか？？
```python
import Requests
URL      = 'https://社内のWebシステム.com/アプリ/アップロード/'
FILES 　　　　　　= {'{{FORM_NAME}}': io.BytesIO(ファイルの内容)}
response = requests.post(URL, files=FILES)
```
`open('アップロードするファイルのPATH', 'rb')`でファイルオブジェクトを指定しているんだから、`io.BytesIO(ファイルの内容)`も同じでしょ！ と思ったんですがね。
でも、これだと…　なんだか上手くいかないんですよぉ…

なので表題の件である、「requestの内容」を確認し、`open('アップロードするファイルのPATH', 'rb')`と`io.BytesIO(ファイルの内容)`での、requestの違いを確認したかったのです！

参考にさせていただいた『[curlのGET,POSTのデータを確認](https://qiita.com/tkj/items/210a66213667bc038110)』では、ファイルのようなバイナリデータをrequestするとちょっと都合が悪かったので、その辺なんかに手を加えています。

```python:echoRequestsHttpServer.py
import http.server
from urllib.parse import urlparse, parse_qs

class MyHandler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        self.make_data()
    def do_GET(self):
        self.make_data()
    def make_data(self):
        req_method    = self.command
        req_parsed    = urlparse(self.path)
        req_params    = '{}'.format(parse_qs(req_parsed.query))
        req_head      = '\n{}'.format(self.headers)
        length        = self.headers.get("content-length")
        content_len   = int(length) if length else 0
        _req_body     = self.rfile.read(content_len)
        req_body      = '{}'.format(_req_body)
        # レスポンスデータ生成
        body  = '＝＝　リクエストデータ　＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝\n'
        body += 'method: ' + req_method + '\n'
        body += 'header: ' + req_head   + '\n'
        body += 'params: ' + req_params + '\n'
        body += 'body  : ' + req_body   + '\n'
        body += '＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝\n'
        # サーバーの標準出力
        print('＝＝　リクエストデータ　＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝')
        print('【METHOD 】', req_method)
        print('【HEADERS】', req_head)
        print('【PARAMS 】', req_params)
        print('【 BODY  】', req_body)
        print('＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝')
        # レスポンス
        self.send_response(200)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.send_header('Content-length', len(body.encode()))
        self.end_headers()
        self.wfile.write(body.encode())
host = '0.0.0.0'
port = 5001
httpd = http.server.HTTPServer((host, port), MyHandler)
print('ポート:%s' % port)
httpd.serve_forever()
```


このサーバーを起動すると…
```python
% python echoRequestsHttpServer.py
ポート:5001
```


そして、上手くアップロードできない、対象のrequestをこのサーバーに向けてrequestすると…
```csvs
＝＝　リクエストデータ　＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
【METHOD 】 POST
【HEADERS】
user-agent: Takky_API
Accept-Encoding: gzip, deflate
Accept: application/json, text/javascript, */*; q=0.01
Connection: keep-alive
Content-Length: 1163
Content-Type: multipart/form-data; boundary=0c0acc9c1affeddfa38401805492e8f5

【PARAMS 】 {}
【 BODY  】 b'--0c0acc9c1affeddfa38401805492e8f5\r\n        ※みやすくするため改行してます
　　　　　　　　　　　　　　　　　　　Content-Disposition: form-data; name="{{FORM_NAME}}";
　　　※ココ →　　　　　filename="{{FORM_NAME}}"\r\n\r\n
#                  ＾＾＾＾＾＾＾＾
　　　　　　　　　　　　　　　　　　　"ファイルの内容"\r\n\r\n
　　　　　　　　　　　　　　　　　　　--0c0acc9c1affeddfa38401805492e8f5--\r\n'
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
192.168.40.136 - - [15/Aug/2022 18:14:23] "POST / HTTP/1.1" 200 -
```

問題なくアップロードできる、ローカルファイルをアップロードするrequestだと…
```csvs
＝＝　リクエストデータ　＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
【METHOD 】 POST
【HEADERS】
user-agent: Takky_API
Accept-Encoding: gzip, deflate
Accept: application/json, text/javascript, */*; q=0.01
Connection: keep-alive
Content-Length: 1145
Content-Type: multipart/form-data; boundary=c53e52730b147a1a87e3452b37f5dc27

【PARAMS 】 {}
【 BODY  】 b'--c53e52730b147a1a87e3452b37f5dc27\r\n        ※みやすくするため改行してます
　　　　　　　　　　　　　　　　　　　Content-Disposition: form-data; name="{{FORM_NAME}}";
　　　　※ココ →　　　　filename="{{アップロードするファイルのファイル名}}"\r\n\r\n
#                  ＾＾＾＾＾＾＾＾＾＾＾＾＾＾＾＾＾＾
　　　　　　　　　　　　　　　　　　　"ファイルの内容"\r\n\r\n
　　　　　　　　　　　　　　　　　　　--c53e52730b147a1a87e3452b37f5dc27--\r\n'
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
192.168.40.136 - - [15/Aug/2022 18:13:21] "POST / HTTP/1.1" 200 -
```

###### わかりましたぁ！！！！！！
ちゃんと、確認できれば簡単にわかることでした。


＂※ココ →＂で示されているように、`open('アップロードするファイルのPATH', 'rb')`でファイルを渡している場合は、bodyの「filename」に open() したファイル名がセットされていますが、`io.BytesIO(ファイルの内容)`で渡している場合には「filename」に "FORM_NAME" と同じ値が渡されています。

そうですねぇ…　「filename」は渡さなきゃイカンですよね！？
なので、「filename」も渡してあげるように修正します。
```python
URL      = 'https://社内のWebシステム.com/アプリ/アップロード/'
FILES 　　　　　　= {'{{FORM_NAME}}': ('アップロードするファイルのファイル名',io.BytesIO(ファイルの内容))}
#　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　     　＾＾＾＾＾＾＾＾＾＾＾＾＾＾＾＾＾＾　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　＾
response = requests.post(URL, files=FILES)
```


**これで、WebAPIは社内のWebシステムに、テンポラリファイルを介すことなくファイルをアップロードすることができました。**

やはり、「百聞は一見にしかず」です。
横着をせずにちゃんと状況を＂正確に＂把握することが、いろいろ近道につながります。


### めでたしめでたし…