Skip to content

Commit

Permalink
feat: handle invalid headers
Browse files Browse the repository at this point in the history
  • Loading branch information
gajus committed Feb 15, 2020
1 parent bc54b7e commit f9281b8
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 53 deletions.
28 changes: 0 additions & 28 deletions src/factories/createToughCookiePayloadFromPuppeteerCookies.js

This file was deleted.

3 changes: 0 additions & 3 deletions src/factories/index.js

This file was deleted.

42 changes: 34 additions & 8 deletions src/routines/proxyRequest.js
@@ -1,5 +1,8 @@
// @flow

import {
promisify,
} from 'util';
import type {
Request,
} from 'puppeteer';
Expand All @@ -13,8 +16,8 @@ import {
import HttpProxyAgent from 'http-proxy-agent';
import HttpsProxyAgent from 'https-proxy-agent';
import {
createToughCookiePayloadFromPuppeteerCookies,
} from '../factories';
formatPuppeteerCookieAsToughCookie,
} from '../utilities';
import type {
ProxyRequestConfigurationType,
} from '../types';
Expand Down Expand Up @@ -75,11 +78,34 @@ const proxyRequest = async (proxyRequestConfiguration: ProxyRequestConfiguration
url: request.url(),
}, 'making a request using HTTP proxy');

const cookieJar = CookieJar.deserializeSync(
createToughCookiePayloadFromPuppeteerCookies(
(await getAllCookies(page)).cookies,
),
);
const puppeteerCookies = (await getAllCookies(page)).cookies;

const cookieJar = CookieJar.deserializeSync({
cookies: puppeteerCookies.map((puppeteerCookie) => {
return formatPuppeteerCookieAsToughCookie(puppeteerCookie);
}),
rejectPublicSuffixes: true,
storeType: 'MemoryCookieStore',
version: 'tough-cookie@2.0.0',
});

const getCookieString = promisify(cookieJar.getCookieString.bind(cookieJar));
const setCookie = promisify(cookieJar.setCookie.bind(cookieJar));

const gotCookieJar = {
getCookieString: async (url) => {
return getCookieString(url);
},
setCookie: async (rawCookie: string, url: string) => {
return setCookie(
rawCookie,
url,
{
ignoreError: true,
},
);
},
};

let agent;

Expand All @@ -97,7 +123,7 @@ const proxyRequest = async (proxyRequestConfiguration: ProxyRequestConfiguration
response = await got(request.url(), {
agent,
body: request.postData(),
cookieJar,
cookieJar: gotCookieJar,
followRedirect: false,
headers,
method: request.method(),
Expand Down
15 changes: 1 addition & 14 deletions src/types.js
Expand Up @@ -49,7 +49,7 @@ export type PuppeteerCookieType = {|
+value: string,
|};

type ToughCookieCookiePayloadType = {|
export type ToughCookiePayloadType = {|
+creation: string,
+domain: string,
+expires: number | string,
Expand All @@ -61,16 +61,3 @@ type ToughCookieCookiePayloadType = {|
+secure: boolean,
+value: string,
|};

/**
* Serialized instance of a `tough-cookie` `CookieJar`.
*
* @see https://www.npmjs.com/package/tough-cookie#tojson
*/
export type ToughCookiePayloadType = {|
+cookies: $ReadOnlyArray<ToughCookieCookiePayloadType>,
+rejectPublicSuffixes: boolean,
+storeType: 'MemoryCookieStore',
+version: string,
|};

21 changes: 21 additions & 0 deletions src/utilities/formatPuppeteerCookieAsToughCookie.js
@@ -0,0 +1,21 @@
// @flow

import type {
PuppeteerCookieType,
ToughCookiePayloadType,
} from '../types';

export default (cookie: PuppeteerCookieType): ToughCookiePayloadType => {
return {
creation: new Date().toISOString(),
domain: cookie.domain.replace(/^\./, ''),
expires: cookie.expires === -1 ? Infinity : new Date(cookie.expires * 1000).toISOString(),
hostOnly: !cookie.domain.startsWith('.'),
httpOnly: cookie.httpOnly,
key: cookie.name,
lastAccessed: new Date().toISOString(),
path: cookie.path,
secure: cookie.secure,
value: cookie.value,
};
};
3 changes: 3 additions & 0 deletions src/utilities/index.js
@@ -0,0 +1,3 @@
// @flow

export {default as formatPuppeteerCookieAsToughCookie} from './formatPuppeteerCookieAsToughCookie';
55 changes: 55 additions & 0 deletions test/puppeteer-proxy/routines/proxyRequest.js
Expand Up @@ -180,6 +180,61 @@ test('sets cookies for the succeeding proxy requests', async (t) => {
t.is(requestHandler.callCount, 2);
});

test('sets cookies for the succeeding proxy requests (ignores invalid cookies)', async (t) => {
t.plan(4);

const requestHandler = sinon.stub()
.onCall(0)
.callsFake((incomingRequest, outgoingRequest) => {
outgoingRequest.setHeader('set-cookie', ['foo=bar;', '( ) < > @ , ; : \\ " / [ ] ? = { }bar=baz']);
outgoingRequest.end('foo');
})
.onCall(1)
.callsFake((incomingRequest, outgoingRequest) => {
t.is(incomingRequest.headers.cookie, 'foo=bar');

outgoingRequest.end('bar');
});

const httpServer = await createHttpServer(requestHandler);

const httpProxyServer = await createHttpProxyServer();

await createPage(async (page) => {
await page.setRequestInterception(true);

page.on('request', async (request) => {
await proxyRequest({
page,
proxyUrl: httpProxyServer.url,
request,
});
});

t.deepEqual(await page.cookies(), []);

await page.goto(httpServer.url);

t.deepEqual(await page.cookies(), [
{
domain: 'localhost',
expires: -1,
httpOnly: false,
name: 'foo',
path: '/',
secure: false,
session: true,
size: 6,
value: 'bar',
},
]);

await page.goto(httpServer.url);
});

t.is(requestHandler.callCount, 2);
});

test('sets cookies for the succeeding proxy requests (correctly handles cookie expiration)', async (t) => {
t.plan(4);

Expand Down

0 comments on commit f9281b8

Please sign in to comment.