UNPKG

@vercel/node

Version:
906 lines (766 loc) 22.3 kB
module.exports = /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ 534: /***/ ((__unused_webpack_module, exports) => { /*! * content-type * Copyright(c) 2015 Douglas Christopher Wilson * MIT Licensed */ /** * RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1 * * parameter = token "=" ( token / quoted-string ) * token = 1*tchar * tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" * / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" * / DIGIT / ALPHA * ; any VCHAR, except delimiters * quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE * qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text * obs-text = %x80-FF * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) */ var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/ var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ /** * RegExp to match quoted-pair in RFC 7230 sec 3.2.6 * * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) * obs-text = %x80-FF */ var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g /** * RegExp to match chars that must be quoted-pair in RFC 7230 sec 3.2.6 */ var QUOTE_REGEXP = /([\\"])/g /** * RegExp to match type in RFC 7231 sec 3.1.1.1 * * media-type = type "/" subtype * type = token * subtype = token */ var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ /** * Module exports. * @public */ exports.format = format exports.parse = parse /** * Format object to media type. * * @param {object} obj * @return {string} * @public */ function format (obj) { if (!obj || typeof obj !== 'object') { throw new TypeError('argument obj is required') } var parameters = obj.parameters var type = obj.type if (!type || !TYPE_REGEXP.test(type)) { throw new TypeError('invalid type') } var string = type // append parameters if (parameters && typeof parameters === 'object') { var param var params = Object.keys(parameters).sort() for (var i = 0; i < params.length; i++) { param = params[i] if (!TOKEN_REGEXP.test(param)) { throw new TypeError('invalid parameter name') } string += '; ' + param + '=' + qstring(parameters[param]) } } return string } /** * Parse media type to object. * * @param {string|object} string * @return {Object} * @public */ function parse (string) { if (!string) { throw new TypeError('argument string is required') } // support req/res-like objects as argument var header = typeof string === 'object' ? getcontenttype(string) : string if (typeof header !== 'string') { throw new TypeError('argument string is required to be a string') } var index = header.indexOf(';') var type = index !== -1 ? header.substr(0, index).trim() : header.trim() if (!TYPE_REGEXP.test(type)) { throw new TypeError('invalid media type') } var obj = new ContentType(type.toLowerCase()) // parse parameters if (index !== -1) { var key var match var value PARAM_REGEXP.lastIndex = index while ((match = PARAM_REGEXP.exec(header))) { if (match.index !== index) { throw new TypeError('invalid parameter format') } index += match[0].length key = match[1].toLowerCase() value = match[2] if (value[0] === '"') { // remove quotes and escapes value = value .substr(1, value.length - 2) .replace(QESC_REGEXP, '$1') } obj.parameters[key] = value } if (index !== header.length) { throw new TypeError('invalid parameter format') } } return obj } /** * Get content-type from req/res objects. * * @param {object} * @return {Object} * @private */ function getcontenttype (obj) { var header if (typeof obj.getHeader === 'function') { // res-like header = obj.getHeader('content-type') } else if (typeof obj.headers === 'object') { // req-like header = obj.headers && obj.headers['content-type'] } if (typeof header !== 'string') { throw new TypeError('content-type header is missing from object') } return header } /** * Quote a string if necessary. * * @param {string} val * @return {string} * @private */ function qstring (val) { var str = String(val) // no need to quote tokens if (TOKEN_REGEXP.test(str)) { return str } if (str.length > 0 && !TEXT_REGEXP.test(str)) { throw new TypeError('invalid parameter value') } return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"' } /** * Class to represent a content type. * @private */ function ContentType (type) { this.parameters = Object.create(null) this.type = type } /***/ }), /***/ 891: /***/ ((__unused_webpack_module, exports) => { /*! * cookie * Copyright(c) 2012-2014 Roman Shtylman * Copyright(c) 2015 Douglas Christopher Wilson * MIT Licensed */ /** * Module exports. * @public */ exports.parse = parse; exports.serialize = serialize; /** * Module variables. * @private */ var decode = decodeURIComponent; var encode = encodeURIComponent; var pairSplitRegExp = /; */; /** * RegExp to match field-content in RFC 7230 sec 3.2 * * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] * field-vchar = VCHAR / obs-text * obs-text = %x80-FF */ var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; /** * Parse a cookie header. * * Parse the given cookie header string into an object * The object has the various cookies as keys(names) => values * * @param {string} str * @param {object} [options] * @return {object} * @public */ function parse(str, options) { if (typeof str !== 'string') { throw new TypeError('argument str must be a string'); } var obj = {} var opt = options || {}; var pairs = str.split(pairSplitRegExp); var dec = opt.decode || decode; for (var i = 0; i < pairs.length; i++) { var pair = pairs[i]; var eq_idx = pair.indexOf('='); // skip things that don't look like key=value if (eq_idx < 0) { continue; } var key = pair.substr(0, eq_idx).trim() var val = pair.substr(++eq_idx, pair.length).trim(); // quoted values if ('"' == val[0]) { val = val.slice(1, -1); } // only assign once if (undefined == obj[key]) { obj[key] = tryDecode(val, dec); } } return obj; } /** * Serialize data into a cookie header. * * Serialize the a name value pair into a cookie string suitable for * http headers. An optional options object specified cookie parameters. * * serialize('foo', 'bar', { httpOnly: true }) * => "foo=bar; httpOnly" * * @param {string} name * @param {string} val * @param {object} [options] * @return {string} * @public */ function serialize(name, val, options) { var opt = options || {}; var enc = opt.encode || encode; if (typeof enc !== 'function') { throw new TypeError('option encode is invalid'); } if (!fieldContentRegExp.test(name)) { throw new TypeError('argument name is invalid'); } var value = enc(val); if (value && !fieldContentRegExp.test(value)) { throw new TypeError('argument val is invalid'); } var str = name + '=' + value; if (null != opt.maxAge) { var maxAge = opt.maxAge - 0; if (isNaN(maxAge)) throw new Error('maxAge should be a Number'); str += '; Max-Age=' + Math.floor(maxAge); } if (opt.domain) { if (!fieldContentRegExp.test(opt.domain)) { throw new TypeError('option domain is invalid'); } str += '; Domain=' + opt.domain; } if (opt.path) { if (!fieldContentRegExp.test(opt.path)) { throw new TypeError('option path is invalid'); } str += '; Path=' + opt.path; } if (opt.expires) { if (typeof opt.expires.toUTCString !== 'function') { throw new TypeError('option expires is invalid'); } str += '; Expires=' + opt.expires.toUTCString(); } if (opt.httpOnly) { str += '; HttpOnly'; } if (opt.secure) { str += '; Secure'; } if (opt.sameSite) { var sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite; switch (sameSite) { case true: str += '; SameSite=Strict'; break; case 'lax': str += '; SameSite=Lax'; break; case 'strict': str += '; SameSite=Strict'; break; case 'none': str += '; SameSite=None'; break; default: throw new TypeError('option sameSite is invalid'); } } return str; } /** * Try decoding a string using a decoding function. * * @param {string} str * @param {function} decode * @private */ function tryDecode(str, decode) { try { return decode(str); } catch (e) { return str; } } /***/ }), /***/ 474: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { /*! * etag * Copyright(c) 2014-2016 Douglas Christopher Wilson * MIT Licensed */ /** * Module exports. * @public */ module.exports = etag /** * Module dependencies. * @private */ var crypto = __webpack_require__(417) var Stats = __webpack_require__(747).Stats /** * Module variables. * @private */ var toString = Object.prototype.toString /** * Generate an entity tag. * * @param {Buffer|string} entity * @return {string} * @private */ function entitytag (entity) { if (entity.length === 0) { // fast-path empty return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"' } // compute hash of entity var hash = crypto .createHash('sha1') .update(entity, 'utf8') .digest('base64') .substring(0, 27) // compute length of entity var len = typeof entity === 'string' ? Buffer.byteLength(entity, 'utf8') : entity.length return '"' + len.toString(16) + '-' + hash + '"' } /** * Create a simple ETag. * * @param {string|Buffer|Stats} entity * @param {object} [options] * @param {boolean} [options.weak] * @return {String} * @public */ function etag (entity, options) { if (entity == null) { throw new TypeError('argument entity is required') } // support fs.Stats object var isStats = isstats(entity) var weak = options && typeof options.weak === 'boolean' ? options.weak : isStats // validate argument if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) { throw new TypeError('argument entity must be string, Buffer, or fs.Stats') } // generate entity tag var tag = isStats ? stattag(entity) : entitytag(entity) return weak ? 'W/' + tag : tag } /** * Determine if object is a Stats object. * * @param {object} obj * @return {boolean} * @api private */ function isstats (obj) { // genuine fs.Stats if (typeof Stats === 'function' && obj instanceof Stats) { return true } // quack quack return obj && typeof obj === 'object' && 'ctime' in obj && toString.call(obj.ctime) === '[object Date]' && 'mtime' in obj && toString.call(obj.mtime) === '[object Date]' && 'ino' in obj && typeof obj.ino === 'number' && 'size' in obj && typeof obj.size === 'number' } /** * Generate a tag for a stat. * * @param {object} stat * @return {string} * @private */ function stattag (stat) { var mtime = stat.mtime.getTime().toString(16) var size = stat.size.toString(16) return '"' + size + '-' + mtime + '"' } /***/ }), /***/ 508: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { Object.defineProperty(exports, "__esModule", ({ value: true })); exports.createServerWithHelpers = exports.sendError = exports.ApiError = void 0; const http_1 = __webpack_require__(605); function getBodyParser(req, body) { return function parseBody() { if (!req.headers['content-type']) { return undefined; } // eslint-disable-next-line @typescript-eslint/no-var-requires const { parse: parseContentType } = __webpack_require__(534); const { type } = parseContentType(req.headers['content-type']); if (type === 'application/json') { try { const str = body.toString(); return str ? JSON.parse(str) : {}; } catch (error) { throw new ApiError(400, 'Invalid JSON'); } } if (type === 'application/octet-stream') { return body; } if (type === 'application/x-www-form-urlencoded') { // eslint-disable-next-line @typescript-eslint/no-var-requires const { parse: parseQS } = __webpack_require__(191); // note: querystring.parse does not produce an iterable object // https://nodejs.org/api/querystring.html#querystring_querystring_parse_str_sep_eq_options return parseQS(body.toString()); } if (type === 'text/plain') { return body.toString(); } return undefined; }; } function getQueryParser({ url = '/' }) { return function parseQuery() { // eslint-disable-next-line @typescript-eslint/no-var-requires const { parse: parseURL } = __webpack_require__(835); return parseURL(url, true).query; }; } function getCookieParser(req) { return function parseCookie() { const header = req.headers.cookie; if (!header) { return {}; } // eslint-disable-next-line @typescript-eslint/no-var-requires const { parse } = __webpack_require__(891); return parse(Array.isArray(header) ? header.join(';') : header); }; } function status(res, statusCode) { res.statusCode = statusCode; return res; } function redirect(res, statusOrUrl, url) { if (typeof statusOrUrl === 'string') { url = statusOrUrl; statusOrUrl = 307; } if (typeof statusOrUrl !== 'number' || typeof url !== 'string') { throw new Error(`Invalid redirect arguments. Please use a single argument URL, e.g. res.redirect('/destination') or use a status code and URL, e.g. res.redirect(307, '/destination').`); } res.writeHead(statusOrUrl, { Location: url }).end(); return res; } function setCharset(type, charset) { // eslint-disable-next-line @typescript-eslint/no-var-requires const { parse, format } = __webpack_require__(534); const parsed = parse(type); parsed.parameters.charset = charset; return format(parsed); } // eslint-disable-next-line @typescript-eslint/no-explicit-any function createETag(body, encoding) { // eslint-disable-next-line @typescript-eslint/no-var-requires const etag = __webpack_require__(474); const buf = !Buffer.isBuffer(body) ? Buffer.from(body, encoding) : body; return etag(buf, { weak: true }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any function send(req, res, body) { let chunk = body; let encoding; switch (typeof chunk) { // string defaulting to html case 'string': if (!res.getHeader('content-type')) { res.setHeader('content-type', 'text/html'); } break; case 'boolean': case 'number': case 'object': if (chunk === null) { chunk = ''; } else if (Buffer.isBuffer(chunk)) { if (!res.getHeader('content-type')) { res.setHeader('content-type', 'application/octet-stream'); } } else { return json(req, res, chunk); } break; } // write strings in utf-8 if (typeof chunk === 'string') { encoding = 'utf8'; // reflect this in content-type const type = res.getHeader('content-type'); if (typeof type === 'string') { res.setHeader('content-type', setCharset(type, 'utf-8')); } } // populate Content-Length let len; if (chunk !== undefined) { if (Buffer.isBuffer(chunk)) { // get length of Buffer len = chunk.length; } else if (typeof chunk === 'string') { if (chunk.length < 1000) { // just calculate length small chunk len = Buffer.byteLength(chunk, encoding); } else { // convert chunk to Buffer and calculate const buf = Buffer.from(chunk, encoding); len = buf.length; chunk = buf; encoding = undefined; } } else { throw new Error('`body` is not a valid string, object, boolean, number, Stream, or Buffer'); } if (len !== undefined) { res.setHeader('content-length', len); } } // populate ETag let etag; if (!res.getHeader('etag') && len !== undefined && (etag = createETag(chunk, encoding))) { res.setHeader('etag', etag); } // strip irrelevant headers if (204 === res.statusCode || 304 === res.statusCode) { res.removeHeader('Content-Type'); res.removeHeader('Content-Length'); res.removeHeader('Transfer-Encoding'); chunk = ''; } if (req.method === 'HEAD') { // skip body for HEAD res.end(); } else if (encoding) { // respond with encoding res.end(chunk, encoding); } else { // respond without encoding res.end(chunk); } return res; } // eslint-disable-next-line @typescript-eslint/no-explicit-any function json(req, res, jsonBody) { const body = JSON.stringify(jsonBody); // content-type if (!res.getHeader('content-type')) { res.setHeader('content-type', 'application/json; charset=utf-8'); } return send(req, res, body); } class ApiError extends Error { constructor(statusCode, message) { super(message); this.statusCode = statusCode; } } exports.ApiError = ApiError; function sendError(res, statusCode, message) { res.statusCode = statusCode; res.statusMessage = message; res.end(); } exports.sendError = sendError; function setLazyProp(req, prop, getter) { const opts = { configurable: true, enumerable: true }; const optsReset = { ...opts, writable: true }; Object.defineProperty(req, prop, { ...opts, get: () => { const value = getter(); // we set the property on the object to avoid recalculating it Object.defineProperty(req, prop, { ...optsReset, value }); return value; }, set: value => { Object.defineProperty(req, prop, { ...optsReset, value }); }, }); } function createServerWithHelpers(handler, bridge) { const server = new http_1.Server(async (_req, _res) => { const req = _req; const res = _res; try { const reqId = req.headers['x-now-bridge-request-id']; // don't expose this header to the client delete req.headers['x-now-bridge-request-id']; if (typeof reqId !== 'string') { throw new ApiError(500, 'Internal Server Error'); } const event = bridge.consumeEvent(reqId); setLazyProp(req, 'cookies', getCookieParser(req)); setLazyProp(req, 'query', getQueryParser(req)); setLazyProp(req, 'body', getBodyParser(req, event.body)); res.status = statusCode => status(res, statusCode); res.redirect = (statusOrUrl, url) => redirect(res, statusOrUrl, url); res.send = body => send(req, res, body); res.json = jsonBody => json(req, res, jsonBody); await handler(req, res); } catch (err) { if (err instanceof ApiError) { sendError(res, err.statusCode, err.message); } else { throw err; } } }); return server; } exports.createServerWithHelpers = createServerWithHelpers; /***/ }), /***/ 417: /***/ ((module) => { module.exports = require("crypto"); /***/ }), /***/ 747: /***/ ((module) => { module.exports = require("fs"); /***/ }), /***/ 605: /***/ ((module) => { module.exports = require("http"); /***/ }), /***/ 191: /***/ ((module) => { module.exports = require("querystring"); /***/ }), /***/ 835: /***/ ((module) => { module.exports = require("url"); /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(__webpack_module_cache__[moduleId]) { /******/ return __webpack_module_cache__[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ var threw = true; /******/ try { /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ threw = false; /******/ } finally { /******/ if(threw) delete __webpack_module_cache__[moduleId]; /******/ } /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/compat */ /******/ /******/ __webpack_require__.ab = __dirname + "/";/************************************************************************/ /******/ // module exports must be returned from runtime so entry inlining is disabled /******/ // startup /******/ // Load entry module and return exports /******/ return __webpack_require__(508); /******/ })() ;