From 1e49526ced26bcc756c5d3435721706ae09ba6e3 Mon Sep 17 00:00:00 2001 From: James Diefenderfer Date: Thu, 11 Nov 2021 10:52:43 -0800 Subject: [PATCH] chore: add request proxy tests --- test/proxy.spec.ts | 205 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 test/proxy.spec.ts diff --git a/test/proxy.spec.ts b/test/proxy.spec.ts new file mode 100644 index 0000000000000..c0c438942a5d3 --- /dev/null +++ b/test/proxy.spec.ts @@ -0,0 +1,205 @@ +/** + * Copyright 2021 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import expect from 'expect'; +import http from 'http'; +import os from 'os'; +import { getTestState } from './mocha-utils'; // eslint-disable-line import/extensions +import type { Server, IncomingMessage, ServerResponse } from 'http'; +import type { Browser } from '../lib/cjs/puppeteer/common/Browser.js'; +import type { AddressInfo } from 'net'; + +/** + * Requests to localhost do not get proxied by default. Create a URL using the hostname + * instead. + */ +function getEmptyPageUrl(server: { PORT: number; EMPTY_PAGE: string }): string { + const emptyPagePath = new URL(server.EMPTY_PAGE).pathname; + + return `http://${os.hostname()}:${server.PORT}${emptyPagePath}`; +} + +describe('request proxy', () => { + let browser: Browser; + let proxiedRequestUrls: string[]; + let proxyServer: Server; + let proxyServerUrl: string; + + beforeEach(() => { + proxiedRequestUrls = []; + + proxyServer = http + .createServer( + ( + originalRequest: IncomingMessage, + originalResponse: ServerResponse + ) => { + proxiedRequestUrls.push(originalRequest.url as string); + + const proxyRequest = http.request( + originalRequest.url as string, + { + method: originalRequest.method, + headers: originalRequest.headers, + }, + (proxyResponse) => { + originalResponse.writeHead( + proxyResponse.statusCode as number, + proxyResponse.headers + ); + proxyResponse.pipe(originalResponse, { end: true }); + } + ); + + originalRequest.pipe(proxyRequest, { end: true }); + } + ) + .listen(); + + proxyServerUrl = `http://${os.hostname()}:${ + (proxyServer.address() as AddressInfo).port + }`; + }); + + afterEach(async () => { + await browser.close(); + + await new Promise((resolve, reject) => { + proxyServer.close((error) => { + if (error) { + reject(error); + } else { + resolve(undefined); + } + }); + }); + }); + + it('should proxy requests when configured', async () => { + const { puppeteer, defaultBrowserOptions, server } = getTestState(); + const emptyPageUrl = getEmptyPageUrl(server); + + browser = await puppeteer.launch({ + ...defaultBrowserOptions, + args: [`--proxy-server=${proxyServerUrl}`], + }); + + const page = await browser.newPage(); + const response = await page.goto(emptyPageUrl); + + expect(response.ok()).toBe(true); + + expect(proxiedRequestUrls).toEqual([emptyPageUrl]); + }); + + it('should respect proxy bypass list', async () => { + const { puppeteer, defaultBrowserOptions, server } = getTestState(); + const emptyPageUrl = getEmptyPageUrl(server); + + browser = await puppeteer.launch({ + ...defaultBrowserOptions, + args: [ + `--proxy-server=${proxyServerUrl}`, + `--proxy-bypass-list=${new URL(emptyPageUrl).host}`, + ], + }); + + const page = await browser.newPage(); + const response = await page.goto(emptyPageUrl); + + expect(response.ok()).toBe(true); + + expect(proxiedRequestUrls).toEqual([]); + }); + + describe('in incognito browser context', () => { + it('should proxy requests when configured at browser level', async () => { + const { puppeteer, defaultBrowserOptions, server } = getTestState(); + const emptyPageUrl = getEmptyPageUrl(server); + + browser = await puppeteer.launch({ + ...defaultBrowserOptions, + args: [`--proxy-server=${proxyServerUrl}`], + }); + + const context = await browser.createIncognitoBrowserContext(); + const page = await context.newPage(); + const response = await page.goto(emptyPageUrl); + + expect(response.ok()).toBe(true); + + expect(proxiedRequestUrls).toEqual([emptyPageUrl]); + }); + + it('should respect proxy bypass list when configured at context level', async () => { + const { puppeteer, defaultBrowserOptions, server } = getTestState(); + const emptyPageUrl = getEmptyPageUrl(server); + + browser = await puppeteer.launch({ + ...defaultBrowserOptions, + args: [ + `--proxy-server=${proxyServerUrl}`, + `--proxy-bypass-list=${new URL(emptyPageUrl).host}`, + ], + }); + + const context = await browser.createIncognitoBrowserContext(); + const page = await context.newPage(); + const response = await page.goto(emptyPageUrl); + + expect(response.ok()).toBe(true); + + expect(proxiedRequestUrls).toEqual([]); + }); + }); + + describe('in incognito browser context', () => { + it('should proxy requests when configured at context level', async () => { + const { puppeteer, defaultBrowserOptions, server } = getTestState(); + const emptyPageUrl = getEmptyPageUrl(server); + + browser = await puppeteer.launch(defaultBrowserOptions); + + const context = await browser.createIncognitoBrowserContext({ + proxyServer: proxyServerUrl, + }); + const page = await context.newPage(); + const response = await page.goto(emptyPageUrl); + + expect(response.ok()).toBe(true); + + expect(proxiedRequestUrls).toEqual([emptyPageUrl]); + }); + + it('should respect proxy bypass list when configured at browser level', async () => { + const { puppeteer, defaultBrowserOptions, server } = getTestState(); + const emptyPageUrl = getEmptyPageUrl(server); + + browser = await puppeteer.launch(defaultBrowserOptions); + + const context = await browser.createIncognitoBrowserContext({ + proxyServer: proxyServerUrl, + proxyBypassList: [new URL(emptyPageUrl).host], + }); + const page = await context.newPage(); + const response = await page.goto(emptyPageUrl); + + expect(response.ok()).toBe(true); + + expect(proxiedRequestUrls).toEqual([]); + }); + }); +});