/*jshint laxcomma: true, smarttabs: true, node:true, esnext:true*/ 'use strict'; /** * Simple wrapper around the http request object to avoid deopts * @module skyring/lib/server/request * @author Eric Satterwhite * @since 1.0.0 * @requires url * @requires querystring */ const {Url} = require('url') , qs = require('querystring') , cache = new WeakMap() , pathexp = /^(\/\/?(?!\/)[^\?#\s]*)(\?[^#\s]*)?$/ ; /** * @constructor * @alias skyring/lib/server/request * @param {IncommingMessage} req An {@link https://nodejs.org/api/http.html#http_class_http_incomingmessage|IncomingMessage} * from the node http module */ function Request(req) { this.query = Object.create(null); this.path = null; this._body = false; this.body = null; this.timers = null; this.res = null; this.headers = req.headers; const parsed = parseurl(req); if (parsed) { this.query = parsed.query; this.path = parsed.pathname; } } /** * Returns the value of a header, if it exists * @param {String} header The name of the header to lookup * @returns {String} The request header, if set */ Request.prototype.get = function get( key ) { const _key = key.toLowerCase(); const headers = this.headers || {}; switch (_key) { case 'referrer': case 'referer': return headers.referrer || headers.referer; default: return headers[_key]; } }; function parseurl( req ) { const url = req.url; if (!url) return url; if ( cache.has(req) ) return cache.get(req); const parsed = fastparse(url); cache.set(req, parsed); return parsed; } function fastparse( str ) { const simple = typeof str === 'string' && pathexp.exec( str ); if ( simple ) { const pathname = simple[1]; const search = simple[2] || null; const url = new Url(); url.path = str; url.href = str; url.pathname = pathname; url.search = search; url.query = url.search ? qs.parse( search.substr( 1 ) ) : Object.create(null); return url; } return parseurl( str, true ); } module.exports = Request;