Skip to content

Instantly share code, notes, and snippets.

@dmozgovoi
Created October 19, 2022 08:00
Show Gist options
  • Save dmozgovoi/af1ab4ebba72bb0228df04498b23c490 to your computer and use it in GitHub Desktop.
Save dmozgovoi/af1ab4ebba72bb0228df04498b23c490 to your computer and use it in GitHub Desktop.
HttpClient variation with flexible output format parsing
import * as http from 'http';
import * as https from 'https';
import got, { Got, ExtendOptions, Headers, CancelableRequest, Response } from 'got';
import CacheableLookup from 'cacheable-lookup';
import { decodeData, TypeOf, TSchema } from '../decoder';
export const DefaultHttpClientOptions = {
keepAlive: true,
maxSockets: 10,
// rough guess: 10 open sockets for each agent is enough, keeping more
// than a ten can become dangerous when http client amount increase
};
export const gotDefaultOptions = {
urlPrefix: '',
dnsCache: new CacheableLookup({
maxTtl: 60 * 30, // 30 minutes
}),
context: { someContext: 'here' },
handlers: [
(options: any, next: Function) => {
Error.captureStackTrace(options.context);
return next(options);
},
],
hooks: {
beforeError: [
(error: any) => {
error.source = error.options.context.stack.split('\n');
return error;
},
],
},
agent: {
http: new http.Agent(DefaultHttpClientOptions),
https: new https.Agent(DefaultHttpClientOptions),
},
};
type GetOptions = {
headers?: Headers;
};
type PostOptions = {
headers?: Headers;
body?: string | Buffer | undefined;
json?: object;
};
/**
* Class-wrapper for HttpClient (now it's got) responses and checking it`s schema
* In case you need to implement new data serialization format, add methods for it`s processing here
*/
class HttpResponseWrapper {
private _gotResponse: CancelableRequest<Response<string>>;
constructor(gotResponse: CancelableRequest<Response<string>>) {
this._gotResponse = gotResponse;
}
async json<S extends TSchema>(schema?: S): Promise<TypeOf<S>> {
const data = await this._gotResponse.json();
if (!schema) {
return data;
}
return decodeData<S>(schema, data, 'httpClient');
}
}
export class HttpClient {
got: Got;
constructor(options: Got | ExtendOptions) {
this.got = got.extend({
...gotDefaultOptions,
...options,
});
}
get(path: string, options?: GetOptions): HttpResponseWrapper {
return new HttpResponseWrapper(this.got.get(path, options));
}
post(path: string, options?: PostOptions): HttpResponseWrapper {
return new HttpResponseWrapper(this.got.post(path, options));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment