UNPKG

koa-even-better-http-proxy

Version:
116 lines (96 loc) 3.12 kB
/* eslint no-param-reassign: ["error", { "props": false }] */ import _ from 'lodash'; import * as http from 'http'; import * as https from 'https'; import getRawBody from 'raw-body'; import isUnset from './isUnset'; const ensureHttpURL = (value) => /^http(s)?:\/\//.test(value) ? value : `http://${value}`; const shouldSkipHeader = (header, headersToSkip) => { if (!Array.isArray(headersToSkip)) return false; return headersToSkip.indexOf(header) > -1; }; const getHostFromContainer = (container) => { let { host } = container.params; const { ctx } = container.user; host = typeof host === 'function' ? host(ctx) : host.toString(); return !host ? null : ensureHttpURL(host); }; const shouldParseReqBody = (options) => isUnset(options.parseReqBody) ? true : options.parseReqBody; const extend = (obj, source, headersToSkip) => { if (!source) { return obj; } const extObj = _.cloneDeep(obj); Object.keys(source).forEach((header) => { if (shouldSkipHeader(header, headersToSkip)) return; extObj[header] = source[header]; }); return extObj; }; const parseUrl = (url) => { try { return new URL(url); } catch (err) { return null; } }; const reqHeaders = (ctx, options) => { const headers = options.headers || {}; const skipHdrs = ['connection', 'content-length']; if (!options.preserveHostHdr) { skipHdrs.push('host'); } return extend(headers, ctx.headers, skipHdrs); }; const maybeParseBody = (ctx, limit) => { if (ctx.request.body) { return Promise.resolve(ctx.request.body); } // Returns a promise if no callback specified and global Promise exists. return getRawBody(ctx.req, { length: ctx.headers['content-length'], limit, }); }; const isHttps = (options, parsed) => options.https || parsed.protocol === 'https:'; const getPort = (port, ishttps) => port || (ishttps ? 443 : 80); const getHttpModule = (ishttps) => (ishttps ? https : http); export const parseHost = (Container) => { const { options } = Container; const host = getHostFromContainer(Container); const parsed = parseUrl(host); if (!parsed) { return new Error(`Failed to parse hostname.`); } const ishttps = isHttps(options, parsed); return { host: parsed.hostname, port: getPort(parsed.port, ishttps), isSecure: ishttps, module: getHttpModule(ishttps), }; }; export const createRequestOptions = (ctx, options) => { // prepare proxyRequest const reqOpt = { headers: reqHeaders(ctx, options), method: ctx.method, path: ctx.path, // params: req.params, }; if (options.preserveReqSession) { reqOpt.session = ctx.session; } if (options.agent) { reqOpt.agent = options.agent; } return Promise.resolve(reqOpt); }; // extract to bodyContent object export const bodyContent = (ctx, options) => { if (!shouldParseReqBody(options)) return null; return maybeParseBody(ctx, options.limit || '50mb'); };