[Bug]: route.fulfill({ json }) replaces a Content-Type set in headers and sets none for null, false, 0 and ''

オープン 初心者向け
#44,109 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
82/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
javascript, typescript
領域
api, testing

調査の方向性

バグは packages/playwright-core/src/client/network.ts の _innerFulfill にある json 分岐にあり、既存のヘッダーを確認せずに Content-Type を設定し、options.json の truthiness をテストしています。そのすぐ上にある、options.json !== undefined で本文を構築するブロックを読み、2つの条件を比較してください。完了条件は、json に Content-Type があらかじめ設定されている場合はその値を保持し、null、false、0、'' の場合は application/json を送信することです。Chromium、Firefox、WebKit で再現用 spec テスト tests/fulfill-json.spec.ts を使って確認してください。

索引モデルが issue の本文から書いたものです。

説明

Version

1.65.1

Steps to reproduce
  1. Clone https://github.com/ondraulehla/playwright-repro-fulfill-json-content-type
  2. npm install
  3. npx playwright install
  4. npx playwright test

The repro is one spec file, tests/fulfill-json.spec.ts. Every request is routed, so it needs no server. Each test does this with a different set of options:

await page.route('http://repro.test/data', route => route.fulfill(options));
const result = await page.evaluate(async () => {
  const response = await fetch('/data');
  return { contentType: response.headers.get('content-type'), body: await response.text() };
});
Expected behavior

The docs for the json option say: "JSON response. This method will set the content type to application/json if not set."

So I'd expect two things:

  1. route.fulfill({ json: { a: 1 }, headers: { 'Content-Type': 'application/problem+json' } }) keeps application/problem+json, because the content type is already set.
  2. route.fulfill({ json: null }) responds with application/json, and so do false, 0 and '', the same way json: 1 does. Playwright already serializes the body for them (null, false, 0, "").
Actual behavior

18 of the 30 tests fail, the same 6 in Chromium, Firefox and WebKit. The 4 control tests pass in all three.

fulfill options Expected Chromium Firefox WebKit
json: { a: 1 }, headers: { 'content-type': 'application/problem+json' } application/problem+json application/json application/json application/json
json: { a: 1 }, headers: { 'Content-Type': 'application/problem+json' } application/problem+json application/json application/json application/json
json: null application/json no header no header text/plain
json: false application/json no header no header text/plain
json: 0 application/json no header no header text/plain
json: '' application/json no header no header text/plain

"no header" means response.headers.get('content-type') is null in the page.

I get the same table on macOS and on Linux (Ubuntu 24.04 in Docker).

Additional context

I found this while looking at how the clients pick the content type after #43205, which was the Python side of the second case (json=[] and json={}).

Both cases come from the same block in _innerFulfill in packages/playwright-core/src/client/network.ts:

if (options.contentType)
  headers['content-type'] = String(options.contentType);
else if (options.json)
  headers['content-type'] = 'application/json';

The json branch doesn't check whether headers already has a content type, and it tests options.json for truthiness. A few lines above, the body is built with options.json !== undefined, which is why the falsy values get a serialized body but no header.

I tried this change against the installed 1.65.1 bundle and all 30 tests pass with it:

else if (options.json !== undefined && !('content-type' in headers))

I'd like to send a PR with the fix and tests if this is approved for a community contribution.

Environment
System:
  OS: macOS 26.6.2
  CPU: (8) arm64 Apple M1 Pro
Binaries:
  Node: 26.5.0 - /opt/homebrew/bin/node
  npm: 11.17.0 - /opt/homebrew/bin/npm
npmPackages:
  @playwright/test: 1.65.1 => 1.65.1
主要言語
TypeScript
スター
99.7k
フォーク
6.8k
平均マージ
16時間 10分
マージ済み PR(30日)
301

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

microsoft/playwright のほかの issue

microsoft/playwright の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。