ネットワーク
はじめに
Playwrightは、HTTPとHTTPSの両方のブラウザネットワークトラフィックを監視および変更するためのAPIを提供します。XHRやfetchリクエストを含む、ページが行うあらゆるリクエストは、追跡、変更、および処理することができます。
APIモック
APIモックガイドを参照して、以下の方法について詳細を確認してください。
- APIリクエストをモックし、APIを呼び出さない
- APIリクエストを実行し、レスポンスを変更する
- HARファイルを使用してネットワークリクエストをモックする。
HTTP認証
HTTP認証を実行します。
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setHttpCredentials("bill", "pa55w0rd"));
Page page = context.newPage();
page.navigate("https://example.com");
HTTPプロキシ
ページをHTTP(S)プロキシまたはSOCKSv5経由で読み込むように設定できます。プロキシは、ブラウザ全体にグローバルに設定することも、各ブラウザコンテキストに個別に設定することもできます。
HTTP(S)プロキシのユーザー名とパスワードをオプションで指定でき、また、setProxyをバイパスするホストを指定することもできます。
グローバルプロキシの例を次に示します
Browser browser = chromium.launch(new BrowserType.LaunchOptions()
.setProxy(new Proxy("http://myproxy.com:3128")
.setUsername("usr")
.setPassword("pwd")));
コンテキストごとに指定することも可能です
Browser browser = chromium.launch();
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setProxy(new Proxy("http://myproxy.com:3128")));
ネットワークイベント
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType chromium = playwright.chromium();
Browser browser = chromium.launch();
Page page = browser.newPage();
page.onRequest(request -> System.out.println(">> " + request.method() + " " + request.url()));
page.onResponse(response -> System.out.println("<<" + response.status() + " " + response.url()));
page.navigate("https://example.com");
browser.close();
}
}
}
またはPage.waitForResponse()を使用してボタンクリック後にネットワークレスポンスを待つこともできます
// Use a glob URL pattern
Response response = page.waitForResponse("**/api/fetch_data", () -> {
page.getByText("Update").click();
});
バリエーション
レスポンスをPage.waitForResponse()で待機
// Use a RegExp
Response response = page.waitForResponse(Pattern.compile("\\.jpeg$"), () -> {
page.getByText("Update").click();
});
// Use a predicate taking a Response object
Response response = page.waitForResponse(r -> r.url().contains(token), () -> {
page.getByText("Update").click();
});
リクエストの処理
page.route("**/api/fetch_data", route -> route.fulfill(new Route.FulfillOptions()
.setStatus(200)
.setBody(testData)));
page.navigate("https://example.com");
Playwrightスクリプトでネットワークリクエストを処理することにより、APIエンドポイントをモックできます。
バリエーション
ブラウザコンテキスト全体でBrowserContext.route()、またはページでPage.route()を使用してルートを設定します。これはポップアップウィンドウや開かれたリンクにも適用されます。
browserContext.route("**/api/login", route -> route.fulfill(new Route.FulfillOptions()
.setStatus(200)
.setBody("accept")));
page.navigate("https://example.com");
リクエストの変更
// Delete header
page.route("**/*", route -> {
Map<String, String> headers = new HashMap<>(route.request().headers());
headers.remove("X-Secret");
route.resume(new Route.ResumeOptions().setHeaders(headers));
});
// Continue requests as POST.
page.route("**/*", route -> route.resume(new Route.ResumeOptions().setMethod("POST")));
変更を加えてリクエストを続行できます。上記の例では、送信リクエストからHTTPヘッダーを削除しています。
リクエストの中止
Page.route()とRoute.abort()を使用してリクエストを中止できます。
page.route("**/*.{png,jpg,jpeg}", route -> route.abort());
// Abort based on the request type
page.route("**/*", route -> {
if ("image".equals(route.request().resourceType()))
route.abort();
else
route.resume();
});
レスポンスの変更
レスポンスを変更するには、APIRequestContextを使用して元のレスポンスを取得し、そのレスポンスをRoute.fulfill()に渡します。オプションを通じてレスポンスの個々のフィールドを上書きできます
page.route("**/title.html", route -> {
// Fetch original response.
APIResponse response = route.fetch();
// Add a prefix to the title.
String body = response.text();
body = body.replace("<title>", "<title>My prefix:");
Map<String, String> headers = response.headers();
headers.put("content-type", "text/html");
route.fulfill(new Route.FulfillOptions()
// Pass all fields from the response.
.setResponse(response)
// Override response body.
.setBody(body)
// Force content type to be html.
.setHeaders(headers));
});
Glob URLパターン
Playwrightは、Page.route()やPage.waitForResponse()などのネットワークインターセプションメソッドにおけるURLマッチングに簡略化されたGlobパターンを使用します。これらのパターンは基本的なワイルドカードをサポートしています
- アスタリスク
- 単一の
*
は、/
を除く任意の文字に一致します - 二重の
**
は、/
を含む任意の文字に一致します
- 単一の
- 疑問符
?
は疑問符?
のみに一致します。任意の文字に一致させたい場合は、代わりに*
を使用してください。 - 波括弧
{}
は、コンマ,
で区切られたオプションのリストに一致させるために使用できます - バックスラッシュ
\
は、特殊文字をエスケープするために使用できます (バックスラッシュ自体は\\
としてエスケープすることに注意)
例
https://example.com/*.js
はhttps://example.com/file.js
に一致しますが、https://example.com/path/file.js
には一致しませんhttps://example.com/?page=1
はhttps://example.com/?page=1
に一致しますが、https://example.com
には一致しません**/*.js
はhttps://example.com/file.js
とhttps://example.com/path/file.js
の両方に一致します**/*.{png,jpg,jpeg}
はすべての画像リクエストに一致します
重要な注意事項
- Globパターンは、URLの一部だけでなく、URL全体に一致する必要があります。
- URLマッチングにGlobを使用する場合、プロトコルとパスセパレータを含む完全なURL構造を考慮してください。
- より複雑なマッチング要件には、Globパターンの代わりに[RegExp]の使用を検討してください。
WebSockets
Playwrightは、WebSocketsの検査、モック、変更をそのままサポートしています。WebSocketsをモックする方法については、APIモックガイドを参照してください。
WebSocketが作成されるたびに、Page.onWebSocket(handler)イベントが発火します。このイベントには、さらなるWebSocketフレーム検査のためのWebSocketインスタンスが含まれます
page.onWebSocket(ws -> {
log("WebSocket opened: " + ws.url());
ws.onFrameSent(frameData -> log(frameData.text()));
ws.onFrameReceived(frameData -> log(frameData.text()));
ws.onClose(ws1 -> log("WebSocket closed"));
});
欠落しているネットワークイベントとサービスワーカー
Playwrightの内蔵機能であるBrowserContext.route()とPage.route()を使用すると、テストでリクエストをネイティブにルーティングし、モックとインターセプションを実行できます。
- Playwrightのネイティブ機能であるBrowserContext.route()とPage.route()を使用しており、ネットワークイベントが欠落しているように見える場合は、setServiceWorkersを
'block'
に設定してService Workersを無効にしてください。 - Mock Service Worker (MSW)のようなモックツールを使用している可能性があります。このツールはレスポンスのモックにはすぐに利用できますが、独自のService Workerを追加し、ネットワークリクエストを横取りするため、BrowserContext.route()とPage.route()から見えなくなってしまいます。ネットワークテストとモックの両方に興味がある場合は、組み込みのBrowserContext.route()とPage.route()をレスポンスモックに使用することを検討してください。
- Service Workersをテストやネットワークモックのためだけでなく、Service Workers自体が行うリクエストのルーティングやリッスンにも興味がある場合は、この実験的な機能を参照してください。