Playwright 1.15のHeadersの仕様議論まとめ
playwright-ruby-clientを何度も対応し直すはめになった。
Playwright 1.15のHeadersまわりの仕様の変遷をメモ
発端となったissue
Playwright 1.14までは、 Request.headers()
Response.headers()
があり、これらは単純なKey => valueハッシュを返すものだった。
そこで問題になるのが
Set-Cookie: aaa=bbb
Set-Cookie: ccc=ddd
こういうケース。おなじSet-Cookieという名前で複数ヘッダーが指定されることがあるのだ。このときに、Playwright 1.14の挙動だと、
[set-cookie] => "aaa=bbb\nccc-ddd"
というKey-Valueが生成されていたらしく、
- 「え?自前で
\n
区切りの文字列をパースしないといけないの??」 - 「これ実装依存だよね。仕様化してくれないと将来変更されたら嫌なんだけど」
(かなり意訳w)
補足
ちなみに、HTTPヘッダによっては、以下のように ,
区切りでまとめて値を返すものもあるようで、
Accept-Languages: ja, en
勝手に \n
区切りで返すやつと、もともと ,
区切りのものとが混在していると確かに発狂したくなる。
このあたりは、RFCの仕様と現実(各種ブラウザの実装)の乖離がみられるところのようだ
RawHeaders爆誕
従来のように headersを onRequestFinishedイベントに乗せていたのをやめて、専用のメソッドコールに変更した。
この変更により、Headerというデータ構造をそのまま返して、あとは使う側がコンマ区切りを取得したいのか、Arrayで取得したいのか、というのを変えられるようにする。
ということがやりたかったのだろう。
rawHeadersはallHeadersへ
単純なリネーム
Playwrightサーバー→クライアント間の構造の統一
Accept-Languages: ja
Accept-Languages: en
と
Accept-Languages: ja, en
とを正規化して、Playwrightクライアント側へ
[
{name: Accept-Languages, value: "ja"},
{name: Accept-Languages, value: "en"},
]
の形に統一して返すようになった。
クライアント側でそれをArrayにするなり、ハッシュにするなり、をするように変更された。
RawHeadersクラス消滅
Headersクラスを介してget() やgetAll() するのではなく、RequestやResponseに対して直接 .headers()
(Deprecated) や .headersArray()
や .allHeaders()
するインターフェースに変更された。
裏の仕組みはあまり変わっていなくて、表面的なインターフェースの変更。
「型がへんだ!」とフィードバックが
「結局ソース読まないとわからない!」
「もうすこし型定義を厳密にしようよ」
(かなり意訳w)
もう一回だけ修正!
headersArray() の返り値の型定義が. Array<Array<string>>
から Array<{name: string, value: string}>
に変わっている。
RawHeadersクラスが内部クラスとして復活しているのだが、ここでSet-Cookieだけ特別扱いする処理が追加されている。(おそらくExpireの中のコンマと区別がつかないから、その救済措置だろう)
ドキュメントにもその旨は明記された。
結局どうなったか
とても複雑な仕様になった気がする。
.headers()
Deprecated. もう使わないでね
.headersArray()
生のヘッダーに近い Array<{name: string, value: string}>
が返ってくる。
set-cookie
も Set-Cookie
も統一されたりせず、そのまま返される。
.headerValue(name)
Set-Cookieに関しては \n
区切りで、それ以外については ,
区切りで、string値が返される。
nameに対するvalueがない場合にはnullが返ってくる。
set-cookie
も Set-Cookie
も統一されてマージされる(case-insensitive)
.headerValue(name)
Array<string>
が返ってくる。
set-cookie
も Set-Cookie
も統一されてマージされる(case-insensitive)