mirror of
				https://codeberg.org/ashley/poke
				synced 2025-07-17 16:52:11 +00:00 
			
		
		
		
	Create node-superfetch.js
This commit is contained in:
		
							parent
							
								
									0256b96674
								
							
						
					
					
						commit
						d2cb3337e1
					
				
							
								
								
									
										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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Ashley
						Ashley