index.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*!
  2. * parseurl
  3. * Copyright(c) 2014 Jonathan Ong
  4. * Copyright(c) 2014 Douglas Christopher Wilson
  5. * MIT Licensed
  6. */
  7. 'use strict'
  8. /**
  9. * Module dependencies.
  10. */
  11. var url = require('url')
  12. var parse = url.parse
  13. var Url = url.Url
  14. /**
  15. * Pattern for a simple path case.
  16. * See: https://github.com/joyent/node/pull/7878
  17. */
  18. var simplePathRegExp = /^(\/\/?(?!\/)[^\?#\s]*)(\?[^#\s]*)?$/
  19. /**
  20. * Exports.
  21. */
  22. module.exports = parseurl
  23. module.exports.original = originalurl
  24. /**
  25. * Parse the `req` url with memoization.
  26. *
  27. * @param {ServerRequest} req
  28. * @return {Object}
  29. * @api public
  30. */
  31. function parseurl(req) {
  32. var url = req.url
  33. if (url === undefined) {
  34. // URL is undefined
  35. return undefined
  36. }
  37. var parsed = req._parsedUrl
  38. if (fresh(url, parsed)) {
  39. // Return cached URL parse
  40. return parsed
  41. }
  42. // Parse the URL
  43. parsed = fastparse(url)
  44. parsed._raw = url
  45. return req._parsedUrl = parsed
  46. };
  47. /**
  48. * Parse the `req` original url with fallback and memoization.
  49. *
  50. * @param {ServerRequest} req
  51. * @return {Object}
  52. * @api public
  53. */
  54. function originalurl(req) {
  55. var url = req.originalUrl
  56. if (typeof url !== 'string') {
  57. // Fallback
  58. return parseurl(req)
  59. }
  60. var parsed = req._parsedOriginalUrl
  61. if (fresh(url, parsed)) {
  62. // Return cached URL parse
  63. return parsed
  64. }
  65. // Parse the URL
  66. parsed = fastparse(url)
  67. parsed._raw = url
  68. return req._parsedOriginalUrl = parsed
  69. };
  70. /**
  71. * Parse the `str` url with fast-path short-cut.
  72. *
  73. * @param {string} str
  74. * @return {Object}
  75. * @api private
  76. */
  77. function fastparse(str) {
  78. // Try fast path regexp
  79. // See: https://github.com/joyent/node/pull/7878
  80. var simplePath = typeof str === 'string' && simplePathRegExp.exec(str)
  81. // Construct simple URL
  82. if (simplePath) {
  83. var pathname = simplePath[1]
  84. var search = simplePath[2] || null
  85. var url = Url !== undefined
  86. ? new Url()
  87. : {}
  88. url.path = str
  89. url.href = str
  90. url.pathname = pathname
  91. url.search = search
  92. url.query = search && search.substr(1)
  93. return url
  94. }
  95. return parse(str)
  96. }
  97. /**
  98. * Determine if parsed is still fresh for url.
  99. *
  100. * @param {string} url
  101. * @param {object} parsedUrl
  102. * @return {boolean}
  103. * @api private
  104. */
  105. function fresh(url, parsedUrl) {
  106. return typeof parsedUrl === 'object'
  107. && parsedUrl !== null
  108. && (Url === undefined || parsedUrl instanceof Url)
  109. && parsedUrl._raw === url
  110. }