Closed4

Playwright 1.15のHeadersの仕様議論まとめ

Yusuke IwakiYusuke Iwaki

playwright-ruby-clientを何度も対応し直すはめになった。

Playwright 1.15のHeadersまわりの仕様の変遷をメモ

発端となったissue

https://github.com/microsoft/playwright/issues/8587

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の仕様と現実(各種ブラウザの実装)の乖離がみられるところのようだ

https://stackoverflow.com/questions/3096888/standard-for-adding-multiple-values-of-a-single-http-header-to-a-request-or-resp

Yusuke IwakiYusuke Iwaki

RawHeaders爆誕

https://github.com/microsoft/playwright/pull/8638

従来のように headersを onRequestFinishedイベントに乗せていたのをやめて、専用のメソッドコールに変更した。

この変更により、Headerというデータ構造をそのまま返して、あとは使う側がコンマ区切りを取得したいのか、Arrayで取得したいのか、というのを変えられるようにする。

ということがやりたかったのだろう。

rawHeadersはallHeadersへ

単純なリネーム

https://github.com/microsoft/playwright/pull/8659

Playwrightサーバー→クライアント間の構造の統一

https://github.com/microsoft/playwright/pull/8665

Accept-Languages: ja
Accept-Languages: en

Accept-Languages: ja, en

とを正規化して、Playwrightクライアント側へ

[
  {name: Accept-Languages, value: "ja"},
  {name: Accept-Languages, value: "en"},
]

の形に統一して返すようになった。

クライアント側でそれをArrayにするなり、ハッシュにするなり、をするように変更された。

Yusuke IwakiYusuke Iwaki

RawHeadersクラス消滅

https://github.com/microsoft/playwright/pull/8749

Headersクラスを介してget() やgetAll() するのではなく、RequestやResponseに対して直接 .headers() (Deprecated) や .headersArray().allHeaders() するインターフェースに変更された。

裏の仕組みはあまり変わっていなくて、表面的なインターフェースの変更。

「型がへんだ!」とフィードバックが

「結局ソース読まないとわからない!」
「もうすこし型定義を厳密にしようよ」

(かなり意訳w)

Yusuke IwakiYusuke Iwaki

もう一回だけ修正!

https://github.com/microsoft/playwright/pull/8854

headersArray() の返り値の型定義が. Array<Array<string>> から Array<{name: string, value: string}> に変わっている。

RawHeadersクラスが内部クラスとして復活しているのだが、ここでSet-Cookieだけ特別扱いする処理が追加されている。(おそらくExpireの中のコンマと区別がつかないから、その救済措置だろう)

ドキュメントにもその旨は明記された。

結局どうなったか

とても複雑な仕様になった気がする。

.headers()

Deprecated. もう使わないでね

.headersArray()

生のヘッダーに近い Array<{name: string, value: string}> が返ってくる。

set-cookieSet-Cookie も統一されたりせず、そのまま返される。

.headerValue(name)

Set-Cookieに関しては \n 区切りで、それ以外については , 区切りで、string値が返される。
nameに対するvalueがない場合にはnullが返ってくる。

set-cookieSet-Cookie も統一されてマージされる(case-insensitive)

.headerValue(name)

Array<string> が返ってくる。

set-cookieSet-Cookie も統一されてマージされる(case-insensitive)

このスクラップは2021/09/13にクローズされました