feat(fetch): support ignoreHTTPSErrors (#8795)

This commit is contained in:
Yury Semikhatsky 2021-09-08 20:32:52 -07:00 committed by GitHub
parent 5550f58284
commit 81ae790288
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 4 deletions

View File

@ -54,14 +54,19 @@ export async function playwrightFetch(context: BrowserContext, params: types.Fet
const timeout = context._timeoutSettings.timeout(params);
const deadline = monotonicTime() + timeout;
const fetchResponse = await sendRequest(context, new URL(params.url, context._options.baseURL), {
const options: https.RequestOptions & { maxRedirects: number, deadline: number } = {
method,
headers,
agent,
maxRedirects: 20,
timeout,
deadline
}, params.postData);
};
// rejectUnauthorized = undefined is treated as true in node 12.
if (context._options.ignoreHTTPSErrors)
options.rejectUnauthorized = false;
const fetchResponse = await sendRequest(context, new URL(params.url, context._options.baseURL), options, params.postData);
const fetchUid = context.storeFetchResponseBody(fetchResponse.body);
return { fetchResponse: { ...fetchResponse, fetchUid } };
} catch (e) {
@ -102,7 +107,7 @@ async function updateRequestCookieHeader(context: BrowserContext, url: URL, opti
}
}
async function sendRequest(context: BrowserContext, url: URL, options: http.RequestOptions & { maxRedirects: number, deadline: number }, postData?: Buffer): Promise<types.FetchResponse>{
async function sendRequest(context: BrowserContext, url: URL, options: https.RequestOptions & { maxRedirects: number, deadline: number }, postData?: Buffer): Promise<types.FetchResponse>{
await updateRequestCookieHeader(context, url, options);
return new Promise<types.FetchResponse>((fulfill, reject) => {
const requestConstructor: ((url: URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void) => http.ClientRequest)

View File

@ -19,6 +19,7 @@ import zlib from 'zlib';
import { pipeline } from 'stream';
import { contextTest as it, expect } from './config/browserTest';
import type { Response } from '..';
import { suppressCertificateWarning } from './config/utils';
it.skip(({ mode }) => mode !== 'default');
@ -459,6 +460,7 @@ it('should support https', async ({context, httpsServer}) => {
const oldValue = process.env['NODE_TLS_REJECT_UNAUTHORIZED'];
// https://stackoverflow.com/a/21961005/552185
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
suppressCertificateWarning();
try {
// @ts-expect-error
const response = await context._fetch(httpsServer.EMPTY_PAGE);
@ -468,7 +470,14 @@ it('should support https', async ({context, httpsServer}) => {
}
});
it('should resolve url relative to baseURL', async function({browser, server, contextFactory, contextOptions}) {
it('should support ignoreHTTPSErrors', async ({contextFactory, contextOptions, httpsServer}) => {
const context = await contextFactory({ ...contextOptions, ignoreHTTPSErrors: true });
// @ts-expect-error
const response = await context._fetch(httpsServer.EMPTY_PAGE);
expect(response.status()).toBe(200);
});
it('should resolve url relative to baseURL', async function({server, contextFactory, contextOptions}) {
const context = await contextFactory({
...contextOptions,
baseURL: server.PREFIX,

View File

@ -20,6 +20,7 @@ import fs from 'fs';
import * as path from 'path';
import { getUserAgent } from '../lib/utils/utils';
import WebSocket from 'ws';
import { suppressCertificateWarning } from './config/utils';
test.slow(true, 'All connect tests are slow');
@ -30,6 +31,7 @@ test('should connect over wss', async ({browserType , startRemoteServer, httpsSe
const oldValue = process.env['NODE_TLS_REJECT_UNAUTHORIZED'];
// https://stackoverflow.com/a/21961005/552185
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
suppressCertificateWarning();
try {
httpsServer.onceWebSocketConnection((ws, request) => {
const remote = new WebSocket(remoteServer.wsEndpoint(), [], {

View File

@ -19,6 +19,7 @@ import { contextTest as test, expect } from '../config/browserTest';
import { playwrightTest } from '../config/browserTest';
import http from 'http';
import { getUserAgent } from '../../lib/utils/utils';
import { suppressCertificateWarning } from '../config/utils';
test('should create a worker from a service worker', async ({page, server}) => {
const [worker] = await Promise.all([
@ -307,6 +308,7 @@ playwrightTest('should connect via https', async ({ browserType, browserOptions,
const oldValue = process.env['NODE_TLS_REJECT_UNAUTHORIZED'];
// https://stackoverflow.com/a/21961005/552185
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
suppressCertificateWarning();
try {
const cdpBrowser = await browserType.connectOverCDP(`https://localhost:${httpsServer.PORT}/`);
const contexts = cdpBrowser.contexts();

View File

@ -69,4 +69,22 @@ export function chromiumVersionLessThan(a: string, b: string) {
return true;
}
return false;
}
let didSuppressUnverifiedCertificateWarning = false;
let originalEmitWarning: (warning: string | Error, ...args: any[]) => void;
export function suppressCertificateWarning() {
if (didSuppressUnverifiedCertificateWarning)
return;
didSuppressUnverifiedCertificateWarning = true;
// Supress one-time warning:
// https://github.com/nodejs/node/blob/1bbe66f432591aea83555d27dd76c55fea040a0d/lib/internal/options.js#L37-L49
originalEmitWarning = process.emitWarning;
process.emitWarning = (warning, ...args) => {
if (typeof warning === 'string' && warning.includes('NODE_TLS_REJECT_UNAUTHORIZED')) {
process.emitWarning = originalEmitWarning;
return;
}
return originalEmitWarning.call(process, warning, ...args);
};
}