Skip to content

Instantly share code, notes, and snippets.

@joselcvarela
Created August 7, 2024 11:48
Show Gist options
  • Save joselcvarela/9a60eb6a3bd435181bb61e4b6e51d558 to your computer and use it in GitHub Desktop.
Save joselcvarela/9a60eb6a3bd435181bb61e4b6e51d558 to your computer and use it in GitHub Desktop.
Util class to make requests easily in Javascript
const { Request } = require('./request.js')
function start({token = "", body = null} = {}) {
const request = Request.get('http://ip.jsontest.com')
if (auth) request.header('Authorization', `Bearer ${token}`)
const response = await request.json(body)
if (!response.ok) throw response
console.log("My IP is:", response.json.ip)
}
const _fetch = require("node-fetch");
/**
* @typedef {'GET' | 'POST' | 'HEAD' | 'PATCH'} Method
* @typedef {string | [string,string]} Url
* @typedef {object} Headers
*/
class Request {
/**@type {URL} */
_url = null;
_headers = new _fetch.Headers();
_method = "";
_redirect = /**@type {_fetch.RequestRedirect}*/ ("follow");
_body = null;
/**
* @param {object} params
* @param {Url} params.url
* @param {Headers} [params.headers]
* @param {Method} [params.method]
*/
constructor({ url, headers, method }) {
this.url(url);
this.method(method ?? "GET");
if (headers) this.headers(headers);
}
/**@param {Url} url */
static post(url) {
return new Request({ url, method: "POST" });
}
/**@param {Url} url */
static get(url) {
return new Request({ url });
}
/**@param {Url} url */
static head(url) {
return new Request({ url, method: "HEAD" });
}
/**@param {Url} url */
static patch(url) {
return new Request({ url, method: "PATCH" });
}
/**@param {Url} url */
url(url) {
this._url = Array.isArray(url) ? new URL(...url) : new URL(url);
return this;
}
/**
* @param {string} client_id
* @param {string} secret
* */
basic(client_id, secret) {
const basic = Buffer.from(`${client_id}:${secret}`).toString("base64");
this.header("Authorization", `Basic ${basic}`);
return this;
}
/**@param {Headers} method */
method(method) {
this._method = method;
return this;
}
/**@param {object} headers */
headers(headers) {
for (const [key, value] of Object.entries(headers)) {
this.header(key, value);
}
return this;
}
/**
* @param {string} key
* @param {string} value
*/
header(key, value) {
this._headers.set(key, value);
return this;
}
/**@param {object} body */
body(body) {
this._body = body;
return this;
}
/**@param {_fetch.RequestRedirect} redirect */
redirect(redirect) {
this._redirect = redirect;
return this;
}
async fetch() {
let text = null;
let json = null;
let status = null;
let headers = null;
let ok = null;
let error = null;
let url = null;
try {
const response = await _fetch(this._url, {
method: this._method,
body: this._body || undefined,
headers: this._headers,
redirect: this._redirect,
});
url = response.url;
status = response.status;
headers = response.headers;
text = await response.text().catch(() => null);
json = await Promise.resolve(text)
.then(JSON.parse)
.catch(() => null);
ok = true;
if (response?.status < 200 || response?.status >= 400)
throw new Error("Status < 200 or >= 400");
} catch (err) {
error = err;
ok = false;
}
return { json, text, status, ok, error, headers, url };
}
/**@param {object} [body] */
async json(body) {
this.header("Accept", "application/json; charset=utf-8");
if (body) {
this.header("Content-Type", "application/json; charset=utf-8");
this.body(JSON.stringify(body));
}
return this.fetch();
}
}
module.exports = { Request };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment