Java
HTTP
HTTPS

multipart/form-dataのリクエストで地味にハマったメモ

multipart/form-data

先日、JavaのHttpURLConnectionを用いて通信処理の実装をしてました。
その中で、multipart/form-data形式で汎用的に送信できる部品を作っていたのですが、何故か何度通信してもmultipart/form-dataのリクエストとして認識されず、解決にかなりの時間を費やしてしまいました。

原因はとてもしょうもない内容で、こんな事でハマるやつが他にいるのか?という感じだったのですが、備忘録的な意味合いも兼ねて書いておきたいと思います。

ちなみに最初に書いてしまうと、原因はこいつでした。
imageのコピー2.jpg

multipart/form-dataのリクエストボディ

一般的なのはこんな感じです。
以下のような形式で組み立てた内容をBodyに乗せて通信します。

multipart/form-dataのボディ
--[Boundary文字列]
Content-Disposition: form-data; name="[フォーム名]"

<<フォームの内容>>
--[Boundary文字列]
Content-Disposition: form-data; name="[フォーム名]"; filename="[ファイル名]"
Content-Type: text/plain

<<ファイルの内容>>
--[Boundary文字列]
・
・
・
送る分だけ続く
・
・
・
--[Boundary文字列]--

リクエストヘッダのContent-Typeはmultipart/form-data、Boundary文字列はContent-Typeの後ろに書いておきましょう。
改行コードは必ずCRLFで。

何故か認識されない・・・

送信したリクエストのリクエストボディを見るも、上記の形式と比べてパッと見間違っている気配がなく、リクエストヘッダのContent-TypeのBoundary指定も間違いない。
うーん?

原因

Postmanからformdata形式で通信し、正常に認識できているリクエストと比較したら、

multipart/form-dataのボディ
--[Boundary文字列]

の、最初の「--」がありませんでした。。
最初、あまりmultipart/form-dataの仕組みに詳しくなく、ネット上のサイトを参考に作っていたのですが、色々なサイトでBoundary文字列として「--------ランダムな文字列」みたいな指定だったので、それに習って最初に「--------」を付けた文字列を指定しており、最初に別途「--」が必要だという認識が欠けてた事と、実際抜けてるかどうかの確認がし辛かった事が原因でした。(RFCちゃんと読めと言う話ですが。)

ちなみに最後の区切りは後ろにも「--」が必要だゾ!(念押し)

教訓

思い込みは怖い。

同じような内容で詰まる人が出ないように書き記しておきます。(そんな人いないか)

ついでに

ちなみに、HTTP通信のテストを行うときは下記のサイトがおすすめです。
GETやPOSTで送ったリクエストの情報とかをJSONの形で返してくれるようなエンドポイントや、バイナリのレスポンスを返してくれたり、他にも色々なエンドポイントが用意されているので、簡単な通信内容の確認から結構しっかりした通信のテストも行えます。

ご存知でない方がいたら是非利用してみてください。捗ります。
httpBin: https://httpbin.org/