Closed6

PlaywrightでAcceptヘッダをapplication/jsonに変更する方法

idumistidumist

実現したいこと

  1. PlaywrightでJSONを取得したい。
  2. APIサーバに対してAccept: application/jsonでアクセスする必要がある。

つまり、

$ curl -H "Accept: application/json" http://127.0.0.1/api/

と同じことを行いたい。

idumistidumist

前提条件

  • Playwright for .NET 1.49.0
  • インストール済みのGoogle Chrome(Playwrightではブラウザをインストールしない)
  • 通常表示とヘッドレスのどちらも利用
  • puppeteer/pyppeteerやPower Automateの代替としてブラウザ操作の自動化のみが目的(テスト自動化等の本来の用途は全くわかっていない)
idumistidumist

結論

1.(Chrome上で実行したい場合)NetworkのModify requestsでacceptヘッダ[1]を上書きする。
2.(単にJSONを取得したい場合)API Testingを利用する

脚注
  1. 上書きするヘッダは小文字のacceptだが、上書きせずに先頭大文字のAcceptヘッダを新規追加しても動作した。 ↩︎

idumistidumist

1.(Chrome上で実行したい場合)NetworkのModify requestsでacceptヘッダを上書きする

using Microsoft.Playwright;

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync(new()
{
    Channel = "chrome",  // インストール済みのChromeを起動
    Headless = false  // trueならヘッドレス
});
var context = await browser.NewContextAsync();
var page = await context.NewPageAsync();

// Modify requests
await page.RouteAsync("**/*", async route =>
{
    Dictionary<string, string> headers = new(route.Request.Headers.ToDictionary(x => x.Key, x => x.Value));
    // acceptヘッダを上書きする
    if (headers.ContainsKey("accept"))
        headers["accept"] = "application/json";
    await route.ContinueAsync(new() { Headers = headers });
});

// http://127.0.0.1/api/ にGETリクエスト
var response = await page.GotoAsync("http://127.0.0.1/api/");

// JSONを取得
if (response is not null)
{
    var json = await response.JsonAsync();  // JsonElementが取得できる
    Debug.WriteLine(json.ToString());
}

await context.CloseAsync();
await browser.CloseAsync();

https://playwright.dev/dotnet/docs/network#modify-requests

idumistidumist

NG例

最初、BrowserContextやPageのSetExtraHTTPHeadersAsync()で良いのかと思い

await page.SetExtraHTTPHeadersAsync(new Dictionary<string, string>()
{
    { "Accept", "application/json" }
});

としたが期待した動作にならなかった。全く同じことをやっていた方を見つけて解決した。
https://github.com/microsoft/playwright/issues/20439

idumistidumist

2.(単にJSONを取得したい場合)API Testingを利用する

単にAPIを叩くだけならAPI Testingを使えばよさそう。(HttpClientでできることをPlaywrightでやってみる)

using Microsoft.Playwright;

using var playwright = await Playwright.CreateAsync();
await using var apiRequest = await playwright.APIRequest.NewContextAsync(new()
{
    BaseURL = "http://127.0.0.1/api/"
});

// Acceptヘッダをapplication/jsonに変更
Dictionary<string, string> headers = new()
{
    { "Accept", "application/json" }
};

// http://127.0.0.1/api/ にGETリクエスト
await using var apiResponse = await apiRequest.GetAsync("./", new() { Headers = headers });

// JSONを取得
var json = await apiResponse.JsonAsync();  // JsonElementが取得できる
Debug.WriteLine(json.ToString());

//await apiResponse.DisposeAsync();  // await using ステートメント利用時は不要
//await apiRequest.DisposeAsync();  // await using ステートメント利用時は不要(利用時に実行すると例外が発生する)

https://playwright.dev/dotnet/docs/api-testing

このスクラップは2025/02/05にクローズされました