Skip to content

Commit

Permalink
fix(core): always sends the 'host' (http/1) or ':authority' (http/2) …
Browse files Browse the repository at this point in the history
…header

fix #110
  • Loading branch information
grantila committed Aug 20, 2020
1 parent a93a54a commit bec7c32
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
7 changes: 6 additions & 1 deletion lib/fetch-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const {
HTTP2_HEADER_METHOD,
HTTP2_HEADER_SCHEME,
HTTP2_HEADER_PATH,
HTTP2_HEADER_AUTHORITY,

// Methods
HTTP2_METHOD_GET,
Expand Down Expand Up @@ -124,6 +125,7 @@ export async function setupFetch(
const {
origin,
protocol,
host,
pathname, search, hash,
} = new URL( url );
const path = pathname + search + hash;
Expand All @@ -143,6 +145,9 @@ export async function setupFetch(
if ( headers.has( HTTP2_HEADER_COOKIE ) )
cookies.push( ...arrayify( headers.get( HTTP2_HEADER_COOKIE ) ) );

if ( !headers.has( "host" ) )
headers.set( "host", host );

const headersToSend: RawHeaders = {
// Set required headers
...( session.protocol === "http1" ? { } : {
Expand All @@ -165,7 +170,7 @@ export async function setupFetch(
if ( key === "host" && session.protocol === "http2" )
// Convert to :authority like curl does:
// https://github.com/grantila/fetch-h2/issues/9
headersToSend[ ":authority" ] = val;
headersToSend[ HTTP2_HEADER_AUTHORITY ] = val;
else if ( key !== HTTP2_HEADER_COOKIE )
headersToSend[ key ] = val;
}
Expand Down
80 changes: 79 additions & 1 deletion test/fetch-h2/context.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { map } from "already";
import { TestData } from "../lib/server-common";
import { makeMakeServer } from "../lib/server-helpers";

Expand Down Expand Up @@ -270,7 +271,7 @@ describe( `context (${version} over ${proto.replace( ":", "" )})`, ( ) =>
{
const { server } = await makeServer( );

const { disconnectAll, fetch } = context( );
const { disconnectAll, fetch } = context( { ...cycleOpts } );

const awaitFetch = fetch( "${proto}//localhost:0" );

Expand Down Expand Up @@ -305,5 +306,82 @@ describe( `context (${version} over ${proto.replace( ":", "" )})`, ( ) =>
await server.shutdown( );
} );
} );

describe( "session sharing", ( ) =>
{
jest.setTimeout( 2500 );

it( "should re-use session for same host", async ( ) =>
{
const { disconnectAll, fetch } = context( { ...cycleOpts } );

const urls = [
[ "https://en.wikipedia.org/wiki/33", "33" ],
[ "https://en.wikipedia.org/wiki/44", "44" ],
[ "https://en.wikipedia.org/wiki/42", "42" ],
];

const resps = await map(
urls,
{ concurrency: Infinity },
async ( [ url, title ] ) =>
{
const resp = await fetch( url );
const text = await resp.text( );
const m = text.match( /<h1[^>]*>(.*)<\/h1>/ );
return { expected: title, got: m?.[ 1 ] };
}
);

resps.forEach( ( { expected, got } ) =>
{
expect( expected ).toBe( got );
} );

await disconnectAll( );
} );

it( "should re-use session for same SAN but different host",
async ( ) =>
{
const { disconnectAll, fetch } = context( { ...cycleOpts } );

const urls = [
{ lang: "en", title: "33" },
{ lang: "en", title: "44" },
{ lang: "sv", title: "33" },
{ lang: "sv", title: "44" },
] as const;

const resps = await map(
urls,
{ concurrency: Infinity },
async ( { lang, title } ) =>
{
const url = `https://${lang}.wikipedia.org/wiki/${title}`;
const resp = await fetch( url );
const text = await resp.text( );
const mLang = text.match( /<html[^>]* lang="([^"]+)"/ );
const mTitle = text.match( /<h1[^>]*>([^<]+)<\/h1>/ );
return {
expectedLang: lang,
gotLang: mLang?.[ 1 ],
expectedTitle: title,
gotTitle: mTitle?.[ 1 ],
};
}
);

resps.forEach(
( { expectedLang, gotLang, expectedTitle, gotTitle } ) =>
{
expect( expectedLang ).toBe( gotLang );
expect( expectedTitle ).toBe( gotTitle );
}
);

await disconnectAll( );
} );
} );
} );
} );

0 comments on commit bec7c32

Please sign in to comment.