/ node_modules / parseurl / index.js
index.js
  1  /*!
  2   * parseurl
  3   * Copyright(c) 2014 Jonathan Ong
  4   * Copyright(c) 2014-2017 Douglas Christopher Wilson
  5   * MIT Licensed
  6   */
  7  
  8  'use strict'
  9  
 10  /**
 11   * Module dependencies.
 12   * @private
 13   */
 14  
 15  var url = require('url')
 16  var parse = url.parse
 17  var Url = url.Url
 18  
 19  /**
 20   * Module exports.
 21   * @public
 22   */
 23  
 24  module.exports = parseurl
 25  module.exports.original = originalurl
 26  
 27  /**
 28   * Parse the `req` url with memoization.
 29   *
 30   * @param {ServerRequest} req
 31   * @return {Object}
 32   * @public
 33   */
 34  
 35  function parseurl (req) {
 36    var url = req.url
 37  
 38    if (url === undefined) {
 39      // URL is undefined
 40      return undefined
 41    }
 42  
 43    var parsed = req._parsedUrl
 44  
 45    if (fresh(url, parsed)) {
 46      // Return cached URL parse
 47      return parsed
 48    }
 49  
 50    // Parse the URL
 51    parsed = fastparse(url)
 52    parsed._raw = url
 53  
 54    return (req._parsedUrl = parsed)
 55  };
 56  
 57  /**
 58   * Parse the `req` original url with fallback and memoization.
 59   *
 60   * @param {ServerRequest} req
 61   * @return {Object}
 62   * @public
 63   */
 64  
 65  function originalurl (req) {
 66    var url = req.originalUrl
 67  
 68    if (typeof url !== 'string') {
 69      // Fallback
 70      return parseurl(req)
 71    }
 72  
 73    var parsed = req._parsedOriginalUrl
 74  
 75    if (fresh(url, parsed)) {
 76      // Return cached URL parse
 77      return parsed
 78    }
 79  
 80    // Parse the URL
 81    parsed = fastparse(url)
 82    parsed._raw = url
 83  
 84    return (req._parsedOriginalUrl = parsed)
 85  };
 86  
 87  /**
 88   * Parse the `str` url with fast-path short-cut.
 89   *
 90   * @param {string} str
 91   * @return {Object}
 92   * @private
 93   */
 94  
 95  function fastparse (str) {
 96    if (typeof str !== 'string' || str.charCodeAt(0) !== 0x2f /* / */) {
 97      return parse(str)
 98    }
 99  
100    var pathname = str
101    var query = null
102    var search = null
103  
104    // This takes the regexp from https://github.com/joyent/node/pull/7878
105    // Which is /^(\/[^?#\s]*)(\?[^#\s]*)?$/
106    // And unrolls it into a for loop
107    for (var i = 1; i < str.length; i++) {
108      switch (str.charCodeAt(i)) {
109        case 0x3f: /* ?  */
110          if (search === null) {
111            pathname = str.substring(0, i)
112            query = str.substring(i + 1)
113            search = str.substring(i)
114          }
115          break
116        case 0x09: /* \t */
117        case 0x0a: /* \n */
118        case 0x0c: /* \f */
119        case 0x0d: /* \r */
120        case 0x20: /*    */
121        case 0x23: /* #  */
122        case 0xa0:
123        case 0xfeff:
124          return parse(str)
125      }
126    }
127  
128    var url = Url !== undefined
129      ? new Url()
130      : {}
131  
132    url.path = str
133    url.href = str
134    url.pathname = pathname
135  
136    if (search !== null) {
137      url.query = query
138      url.search = search
139    }
140  
141    return url
142  }
143  
144  /**
145   * Determine if parsed is still fresh for url.
146   *
147   * @param {string} url
148   * @param {object} parsedUrl
149   * @return {boolean}
150   * @private
151   */
152  
153  function fresh (url, parsedUrl) {
154    return typeof parsedUrl === 'object' &&
155      parsedUrl !== null &&
156      (Url === undefined || parsedUrl instanceof Url) &&
157      parsedUrl._raw === url
158  }