ねののお庭。

かりかりもふもふ。

【C#】JsonContent と Request Header。

JsonContent と Request Header

JsonContent を使う事は多いでしょう。 直接 JsonContent を使わない場合でも、PostAsJsonAsync 等の拡張メソッドは内部的に当然 JsonContent を用いるので、めちゃくちゃ多用されている HttpContent です。

で、JsonContent を用いた場合、特に何もしなければ chunked request として送信されます。 つまり request header には transfer-encoding: chunked が付与されます。 そのため当然ながら content-length は不要なので、付与されません。

transfer-encoding: chunked ではなく、content-length を付与してリクエストを飛ばしたい場合は LoadIntoBufferAsync() を呼び出せば OK です。

var content = JsonContent.Create(...);

// この一行を入れる事によって、header に `transfer-encoding: chunked` ではなく `content-length` が付与されるようになる。
await content.LoadIntoBufferAsync(cancellationToken);

Cloud Run と Request Header

さてなんでこんな記事を書いているかというと、Cloud Run 使っている時にハマったからです...。

json を DELETE で飛ばしていたのですが、なぜか Cloud Run にホストされているところに対して送ると「body がねぇぞ!」という怒られが発生してしまいました。 ローカルとか CI では特に問題なかったのに...。

で、原因を調査していたところ Cloud Run (というか Cloud Run の前段にあるであろう内部の LB) が DELETE に関しては chunked request に対応していなかったのです...! POST の場合は chunked request に対応しているのに、なぜか DELETE に関してのみ対応していないのです...!

というか Cloud Run でホストされているサーバに対して chunked request で送っても、ホストされているコンテナには transfer-encoding: chunked が削除され、その代わりに content-length が付与された状態で届きます。 しかしDELETE method のリクエストに関しては transfer-encoding: chunked が削除され、content-length も付与されません。 何故...。

ということで Cloud Run でホストされているサーバに対して DELETE で json を投げる時は chunked request ではなく、content-length が付与された形式でリクエストは投げるようにしましょう。