mirror of
https://codeberg.org/ashley/poke.git
synced 2024-11-26 01:58:56 +01:00
Create node-superfetch.js
This commit is contained in:
parent
97c075a014
commit
439d344b21
1 changed files with 168 additions and 0 deletions
168
src/modules/node-superfetch.js
Normal file
168
src/modules/node-superfetch.js
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
Internet Systems Consortium license
|
||||
===================================
|
||||
|
||||
Copyright (c) 2017-2018, dragonfire535
|
||||
|
||||
https://github.com/dragonfire535/node-superfetch
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted, provided that the above copyright notice
|
||||
and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
const fetch = require('node-fetch');
|
||||
const FormData = require('form-data');
|
||||
const { URL } = require('url');
|
||||
const { METHODS } = require('http');
|
||||
|
||||
class Request {
|
||||
constructor(options) {
|
||||
if (!options.url) throw new Error('The "url" option is required.');
|
||||
this.url = new URL(options.url);
|
||||
this.method = options.method ? options.method.toUpperCase() : 'GET';
|
||||
if (!METHODS.includes(this.method)) throw new Error(`The method "${this.method}" is not supported.`);
|
||||
this.headers = options.headers || {};
|
||||
this.body = options.body || null;
|
||||
this.redirectCount = typeof options.redirects === 'undefined' ? 20 : options.redirects;
|
||||
this.agent = options.agent || null;
|
||||
this.noResultData = options.noResultData || false;
|
||||
}
|
||||
|
||||
async _request() {
|
||||
const response = await fetch(this.url.toString(), {
|
||||
method: this.method,
|
||||
headers: this.headers,
|
||||
follow: this.redirectCount,
|
||||
body: this.body,
|
||||
agent: this.agent
|
||||
});
|
||||
let raw = null;
|
||||
if (!this.noResultData) raw = await response.buffer();
|
||||
const headers = {};
|
||||
for (const [header, value] of response.headers.entries()) headers[header] = value;
|
||||
const res = {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headers,
|
||||
url: response.url,
|
||||
redirected: response.redirected,
|
||||
ok: response.ok,
|
||||
raw,
|
||||
get text() {
|
||||
if (this.noResultData) return null;
|
||||
return raw.toString();
|
||||
},
|
||||
get body() {
|
||||
if (this.noResultData) return null;
|
||||
if (/application\/json/gi.test(headers['content-type'])) {
|
||||
try {
|
||||
return JSON.parse(raw.toString());
|
||||
} catch (err) {
|
||||
return raw.toString();
|
||||
}
|
||||
} else {
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!response.ok) {
|
||||
const err = new Error(`${res.status} ${res.statusText}`);
|
||||
Object.assign(err, res);
|
||||
throw err;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
then(resolver, rejector) {
|
||||
return this._request().then(resolver, rejector);
|
||||
}
|
||||
|
||||
catch(rejector) {
|
||||
return this.then(null, rejector);
|
||||
}
|
||||
|
||||
end(cb) {
|
||||
return this.then(
|
||||
response => cb ? cb(null, response) : response,
|
||||
err => cb ? cb(err, err.status ? err : null) : err
|
||||
);
|
||||
}
|
||||
|
||||
query(queryOrName, value) {
|
||||
if (typeof queryOrName === 'object') {
|
||||
for (const [param, val] of Object.entries(queryOrName)) this.url.searchParams.append(param, val);
|
||||
} else if (typeof queryOrName === 'string' && value) {
|
||||
this.url.searchParams.append(queryOrName, value);
|
||||
} else {
|
||||
throw new TypeError('The "query" parameter must be either an object or a query field.');
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
set(headersOrName, value) {
|
||||
if (typeof headersOrName === 'object') {
|
||||
for (const [header, val] of Object.entries(headersOrName)) this.headers[header] = val;
|
||||
} else if (typeof headersOrName === 'string' && value) {
|
||||
this.headers[headersOrName] = value;
|
||||
} else {
|
||||
throw new TypeError('The "headers" parameter must be either an object or a header field.');
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
attach(...args) {
|
||||
if (!this.body || !(this.body instanceof FormData)) this.body = new FormData();
|
||||
if (typeof args[0] === 'object') {
|
||||
for (const [key, val] of Object.entries(args[0])) this.attach(key, val);
|
||||
} else {
|
||||
this.body.append(...args);
|
||||
}
|
||||
this.set(this.body.getHeaders());
|
||||
this.set('content-length', this.body.getLengthSync());
|
||||
return this;
|
||||
}
|
||||
|
||||
send(body, raw = false) {
|
||||
if (body instanceof FormData) raw = true;
|
||||
if (!raw && body !== null && typeof body === 'object') {
|
||||
const header = this.headers['content-type'];
|
||||
if (header) {
|
||||
if (/application\/json/gi.test(header)) body = JSON.stringify(body);
|
||||
} else {
|
||||
this.set('content-type', 'application/json');
|
||||
body = JSON.stringify(body);
|
||||
}
|
||||
}
|
||||
this.body = body;
|
||||
return this;
|
||||
}
|
||||
|
||||
redirects(amount) {
|
||||
if (typeof amount !== 'number') throw new TypeError('The "amount" parameter must be a number.');
|
||||
this.redirectCount = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
agent(agent) {
|
||||
this.agent = agent;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
for (const method of METHODS) {
|
||||
if (!/^[A-Z$_]+$/gi.test(method)) continue;
|
||||
Request[method.toLowerCase()] = (url, options) => new Request({ url, method, ...options });
|
||||
}
|
||||
|
||||
Request.version = "1.0.0";
|
||||
|
||||
module.exports = Request;
|
Loading…
Reference in a new issue