parseurl源码解析

介绍

Parse a URL with memoization.

意思是转化URL对象,使用缓存,基于node的url.parse的能力。

demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
parseurl({url:'http://www.baidu.com?q=ni&s=shuo&a=shenme'})

Url {
protocol: 'http:',
slashes: true,
auth: null,
host: 'www.baidu.com',
port: null,
hostname: 'www.baidu.com',
hash: null,
search: '?q=ni&s=shuo&a=shenme',
query: 'q=ni&s=shuo&a=shenme',
pathname: '/',
path: '/?q=ni&s=shuo&a=shenme',
href: 'http://www.baidu.com/?q=ni&s=shuo&a=shenme',
_raw: 'http://www.baidu.com?q=ni&s=shuo&a=shenme'
}

源码 parseurl 1.3.3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
'use strict'

var url = require('url')
var parse = url.parse
var Url = url.Url

module.exports = parseurl
module.exports.original = originalurl

/**
* parse转化 `req` 中的 url,同时使用缓存
* @param {ServerRequest} req
* @return {Object}
* @public
*/
function parseurl(req) {
var url = req.url

if (url === undefined) {
// URL 是 undefined 时直接返回
return undefined
}

var parsed = req._parsedUrl

if (fresh(url, parsed)) {
// 如果当前记录的为最新的 url,则直接返回之前parse过的结果
return parsed
}

// 转化 URL
// 转化前url存在_raw,转化后url存在_parsedUrl
// _parsedUrl即为缓存的内容
parsed = fastparse(url)
parsed._raw = url

return (req._parsedUrl = parsed)
};

/**
* 转化 `req`对象的 original url
*
* @param {ServerRequest} req
* @return {Object}
* @public
*/
function originalurl(req) {
var url = req.originalUrl

if (typeof url !== 'string') {
// Fallback
return parseurl(req)
}

var parsed = req._parsedOriginalUrl

if (fresh(url, parsed)) {
// Return cached URL parse
return parsed
}

// Parse the URL
parsed = fastparse(url)
parsed._raw = url

return (req._parsedOriginalUrl = parsed)
};

/**
* Parse the `str` url with fast-path short-cut.
*
* @param {string} str
* @return {Object}
* @private
*/
function fastparse(str) {
// 如果参数不为字符串则使用node中的url.parse去转换
if (typeof str !== 'string' || str.charCodeAt(0) !== 0x2f /* / */) {
return parse(str)
}

var pathname = str
var query = null
var search = null

// This takes the regexp from https://github.com/joyent/node/pull/7878
// Which is /^(\/[^?#\s]*)(\?[^#\s]*)?$/
// And unrolls it into a for loop
// 通过判断 ? 来截取后边的 query字串
for (var i = 1; i < str.length; i++) {
switch (str.charCodeAt(i)) {
case 0x3f: /* ? */
if (search === null) {
pathname = str.substring(0, i)
query = str.substring(i + 1)
search = str.substring(i)
}
break
case 0x09: /* \t */
case 0x0a: /* \n */
case 0x0c: /* \f */
case 0x0d: /* \r */
case 0x20: /* */
case 0x23: /* # */
case 0xa0:
case 0xfeff:
return parse(str)
}
}

var url = Url !== undefined
? new Url()
: {}

url.path = str
url.href = str
url.pathname = pathname

if (search !== null) {
url.query = query
url.search = search
}

return url
}

/**
* 判断之前转化过的 url 是否是最新的
* @param {string} url
* @param {object} parsedUrl
* @return {boolean}
* @private
*/
function fresh(url, parsedUrl) {
// 判断 parsedUrl 为不为空的对象,且为Url的实例,且raw记录的url为当前传入的url
return typeof parsedUrl === 'object' &&
parsedUrl !== null &&
(Url === undefined || parsedUrl instanceof Url) &&
parsedUrl._raw === url
}

参考链接:

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

给阿姨来一杯卡普基诺~

支付宝
微信