Skip to content

Commit

Permalink
Mention h2c usage
Browse files Browse the repository at this point in the history
Fixes #1751
  • Loading branch information
szmarczak committed Jul 13, 2021
1 parent 59b9aed commit c601899
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 3 deletions.
3 changes: 3 additions & 0 deletions documentation/2-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,9 @@ If `true`, the `request` option will default to `http2wrapper.auto` and the enti
**Note:**
> - Setting the `request` option to `https.request` will disable HTTP/2 usage, even if the `http2` option is `true`. It is required to use `http2wrapper.auto`.
**Note:**
> - There is no direct [`h2c`](https://datatracker.ietf.org/doc/html/rfc7540#section-3.1) support. However, you can provide a `h2session` option in a `beforeRequest` hook. See [an example](examples/h2c.js).
```js
import got from 'got';

Expand Down
3 changes: 2 additions & 1 deletion documentation/examples/gh-got.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const getRateLimit = (headers) => ({
const instance = got.extend({
prefixUrl: 'https://api.github.com',
headers: {
accept: 'application/vnd.github.v3+json'
accept: 'application/vnd.github.v3+json',
'user-agent': `${packageJson.name}/${packageJson.version}`
},
responseType: 'json',
context: {
Expand Down
51 changes: 51 additions & 0 deletions documentation/examples/h2c.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import http2 from 'http2-wrapper';
import got from 'got';

let sessions = {};
const getSession = ({origin}) => {
if (sessions[origin] && !sessions[origin].destroyed) {
return sessions[origin];
}

const session = http2.connect(origin);
session.once('error', () => {
delete sessions[origin];
});

sessions[origin] = session;

return session;
};

const closeSessions = () => {
for (const key in sessions) {
sessions[key].close();
}

sessions = {};
};

const instance = got.extend({
hooks: {
beforeRequest: [
options => {
options.h2session = getSession(options.url);
options.http2 = true;
options.request = http2.request;
}
]
}
});

const server = http2.createServer((request, response) => {
response.end('{}');
});

server.listen(async () => {
const url = `http://localhost:${server.address().port}`;
const {body, headers} = await instance(url, {context: {h2c: true}});
console.log(headers, body);

closeSessions();
server.close();
});
6 changes: 6 additions & 0 deletions documentation/tips.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,12 @@ const fn = retryCount => {
fn(0);
```

### `h2c`

There is no direct [`h2c`](https://datatracker.ietf.org/doc/html/rfc7540#section-3.1) support.

However, you can provide a `h2session` option in a `beforeRequest` hook. See [an example](examples/h2c.js).

### Electron `net` module is not supported

Got doesn't support the `electron.net` module. It's missing crucial APIs that are available in Node.js.\
Expand Down
6 changes: 5 additions & 1 deletion source/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ export default class Request extends Duplex implements RequestEvents<Request> {
// Reset `prefixUrl`
options.prefixUrl = '';

let request = options.getRequestFunction();
let request: ReturnType<Options['getRequestFunction']> | undefined;

for (const hook of options.hooks.beforeRequest) {
// eslint-disable-next-line no-await-in-loop
Expand All @@ -1065,6 +1065,10 @@ export default class Request extends Duplex implements RequestEvents<Request> {
}
}

if (!request) {
request = options.getRequestFunction();
}

const url = options.url as URL;

this._requestOptions = options.createNativeRequestOptions() as NativeRequestOptions;
Expand Down
14 changes: 13 additions & 1 deletion source/core/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type {InspectOptions} from 'util';
import is, {assert} from '@sindresorhus/is';
import lowercaseKeys from 'lowercase-keys';
import CacheableLookup from 'cacheable-lookup';
import http2wrapper from 'http2-wrapper';
import http2wrapper, {ClientHttp2Session} from 'http2-wrapper';
import type CacheableRequest from 'cacheable-request';
import type ResponseLike from 'responselike';
import type {IncomingMessageWithTimings} from '@szmarczak/http-timer';
Expand Down Expand Up @@ -551,6 +551,7 @@ const defaultInternals: Options['_internals'] = {
https: undefined,
http2: undefined,
},
h2session: undefined,
decompress: true,
timeout: {
connect: undefined,
Expand Down Expand Up @@ -937,6 +938,14 @@ export default class Options {
}
}

get h2session(): ClientHttp2Session | undefined {
return this._internals.h2session;
}

set h2session(value: ClientHttp2Session | undefined) {
this._internals.h2session = value;
}

/**
Decompress the response automatically.
Expand Down Expand Up @@ -2165,6 +2174,9 @@ export default class Options {
headers: internals.headers,
createConnection: internals.createConnection,
timeout: internals.http2 ? getHttp2TimeoutOption(internals) : undefined,

// HTTP/2 options
h2session: internals.h2session,
};
}

Expand Down

0 comments on commit c601899

Please sign in to comment.