UNPKG

url-resolver-fs

Version:

resolves urls and provides fs like access

178 lines (159 loc) 4.29 kB
import { URLScheme } from "./url-scheme"; import { parseAuthenticate, ResponseError } from "./util"; import fetch from "node-fetch"; import btoa from "btoa"; import HttpProxyAgent from "http-proxy-agent"; import HttpsProxyAgent from "https-proxy-agent"; /** * URLScheme for http requests * @param {Object} options * @param {string} options.proxy * * @property {Object} options */ export class HTTPScheme extends URLScheme { /** * @return {string} 'http' */ static get name() { return "http"; } /** * @return {number} 80 the http default port */ static get defaultPort() { return 80; } /** * Extract options suitable for the constructor * form the given set of environment variables * @param {Object} env * @return {Object} undefined if no suitable environment variables have been found */ static optionsFromEnvironment(env) { if (env !== undefined) { if (env.HTTP_PROXY !== undefined) { return { proxy: env.HTTP_PROXY }; } if (env.HTTPS_PROXY !== undefined) { return { proxy: env.HTTPS_PROXY }; } } return undefined; } setOptions(options = {}) { Object.defineProperty(this, "httpOptions", { value: { headers: {} } }); if (options.proxy !== undefined) { this.httpOptions.agent = this.isSecure ? new HttpsProxyAgent(options.proxy) : new HttpProxyAgent(options.proxy); } super.setOptions(options); } /** * @param {Context} context execution context * @param {URL} url * @param {Object} options * @return {Promise} fetch result */ async fetch(context, url, options = {}) { options = Object.assign({}, options, this.httpOptions, { headers: Object.assign({}, this.httpOptions.headers, options.headers) }); let response; for (let n = 1; n <= 2; n++) { response = await fetch(url, options); if (response.status < 200 || response.status >= 300) { switch (response.status) { case 401: const credentials = await this.provideCredentials( context, parseAuthenticate(response.headers.get("WWW-Authenticate"), { url }) ); if (credentials !== undefined) { this.addAuthorizationHeader(options.headers, credentials); break; } default: throw new ResponseError(response); } } else { return response; } } return response; } /** * Execute a GET request * @param {Context} context execution context * @param {URL} url source * @param {Object} options * @return {Promise} body of the response */ async get(context, url, options) { const response = await this.fetch(context, url, options); return response.body; } /** * Execute a PUT request * @param {Context} context execution context * @param {URL} url destination * @param {Stream} stream content to be put to the url * @param {Object} options */ async put(context, url, stream, options) { return this.fetch( context, url, Object.assign( { method: "put", data: stream }, options ) ); } /** * Execute a HEAD request * @param {Context} context execution context * @param {URL} url * @param {Object} options * @param {string} options.method * @return {Object} response object */ async stat(context, url, options) { return this.fetch( context, url, Object.assign( { method: "head" }, options ) ); } /** * inserts the authorization data into the reguest header * @param {Object} headers http credentials will be inserted into * @param {Object} credentials * * @return {boolean} true if auth info has been written into headers */ addAuthorizationHeader(headers, credentials) { if (credentials !== undefined) { if ( credentials.user !== undefined && credentials.password !== undefined ) { headers.authorization = "Basic " + btoa(credentials.user + ":" + credentials.password); return true; } } return false; } }