Created
November 3, 2020 16:21
-
-
Save maletor/1028d89c5016d19facd51711637f1700 to your computer and use it in GitHub Desktop.
Generic HTTP methods
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { IncomingMessage } from "http"; | |
import { Agent, request, RequestOptions } from "https"; | |
const agent = new Agent({ keepAlive: true, timeout: 10000 }); | |
class MissingStatusCodeError extends Error { | |
constructor(public url: string) { | |
super("Missing a status code"); | |
this.name = "MissingStatusCodeError"; | |
this.url = url; | |
} | |
} | |
class TimeoutError extends Error { | |
constructor(public url: string) { | |
super("Timeout error"); | |
this.name = "TimeoutError"; | |
this.url = url; | |
} | |
} | |
export class ClientError extends Error { | |
constructor( | |
public url: RequestInfo, | |
public status: number, | |
public response?: unknown | |
) { | |
super("Client error"); | |
this.name = "ClientError"; | |
this.url = url; | |
this.status = status; | |
this.response = response; | |
} | |
} | |
class ServerError extends Error { | |
constructor( | |
public url: RequestInfo, | |
public status: number, | |
public response?: unknown | |
) { | |
super("Server error"); | |
this.name = "ServerError"; | |
this.url = url; | |
this.status = status; | |
this.response = response; | |
} | |
} | |
const parseIncoming = (incoming: IncomingMessage): Promise<unknown> => | |
new Promise((resolve, reject) => { | |
const data: Buffer[] = []; | |
incoming.on("data", (chunk) => data.push(chunk)); | |
incoming.on("end", () => { | |
try { | |
const response = Buffer.concat(data).toString(); | |
const json: unknown = JSON.parse(response); | |
resolve(json); | |
} catch (error) { | |
reject(error); | |
} | |
}); | |
}); | |
const makeRequest = ( | |
url: string, | |
options: RequestOptions, | |
method: "GET" | "POST", | |
data?: string | |
): Promise<IncomingMessage> => | |
new Promise((resolve, reject) => { | |
const req = request(url, { ...options, method, agent }, (incoming) => { | |
const statusCode = incoming.statusCode; | |
if (!statusCode) return reject(new MissingStatusCodeError(url)); | |
if (statusCode >= 400 && statusCode < 500) { | |
parseIncoming(incoming) | |
.then((json) => reject(new ClientError(url, statusCode, json))) | |
.catch(() => reject(new ClientError(url, statusCode))); | |
return; | |
} | |
if (statusCode >= 500 && statusCode < 600) { | |
parseIncoming(incoming) | |
.then((json) => reject(new ServerError(url, statusCode, json))) | |
.catch(() => reject(new ServerError(url, statusCode))); | |
return; | |
} | |
resolve(incoming); | |
}); | |
req.on("error", (error) => reject(error)); | |
req.on("timeout", () => req.destroy(new TimeoutError(url))); | |
if (data) req.write(data); | |
req.end(); | |
}); | |
const getStream = ( | |
url: string, | |
options: RequestOptions | |
): Promise<IncomingMessage> => makeRequest(url, options, "GET"); | |
export const get = (url: string, options: RequestOptions): Promise<unknown> => | |
getStream(url, options).then(parseIncoming); | |
const postStream = ( | |
url: string, | |
options: RequestOptions, | |
data?: string | |
): Promise<IncomingMessage> => makeRequest(url, options, "POST", data); | |
export const post = ( | |
url: string, | |
options: RequestOptions, | |
data?: string | |
): Promise<unknown> => postStream(url, options, data).then(parseIncoming); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment