「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战」
本文为 koa 依赖系列文章,前几篇也可以在站内查看:
- koa 中依赖的库 parseurl
- Koa 依赖的库 type-is 和 content-disposition
- Koa 依赖的库 accepts、content-type 和 cache-content-type
这次看两个字符串相关的库,在 Koa 中都只在 response 中的 redirect 函数内使用到。
encodeurl 用于 redirect 中 Location 的设置,当重定向时,response header 中有 Location 属性,值是一个 Url,在 koa 中此 url 使用 encodeurl 库进行编码,encodeurl 源码如下:
var ENCODE_CHARS_REGEXP = /(?:[^\x21\x25\x26-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]|%(?:[^0-9A-Fa-f]|[0-9A-Fa-f][^0-9A-Fa-f]|$))+/g
var UNMATCHED_SURROGATE_PAIR_REGEXP = /(^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF]([^\uDC00-\uDFFF]|$)/g
var UNMATCHED_SURROGATE_PAIR_REPLACE = '$1\uFFFD$2'
function encodeUrl (url) {
return String(url)
.replace(UNMATCHED_SURROGATE_PAIR_REGEXP, UNMATCHED_SURROGATE_PAIR_REPLACE)
.replace(ENCODE_CHARS_REGEXP, encodeURI)
}
可以看到 encodeurl 全部代码很少,最终调用的还是 encodeURI,不过在调用之前做了一些处理,这样已经被编码过的数据不会被重复编码,举个例子:
原始 url http://localhost:3001/te st
包含一个空格,此时需要进行编码,encode 之后的 url 变为 http://localhost:3001/te%20st
,此时空格被编码为 %20,如果将新的 url 再进行一次编码,百分号会被编码成 %25,此时编码结果为 http://localhost:3001/te%2520st
,原生的 encodeURI 方法只会对传入的字符串各个字符一一做编码转换,不会去判断是否已经经过了一次编码。作为一个通用的方法 encodeURI 这个逻辑是合理的,但是在 koa 中这个应用场景下已经编码过的 Url 不应该被再次编码,因此此处使用了 encodeurl 中的逻辑。
接下来看 escape-html 库,从名字可以看出这是一个过滤 html 字符串的工具,在浏览器中为了防止 XSS,对于从用户侧接收到的数据都要进行 escape 处理,这里 koa 中也是这个用途。在 redirect 逻辑中有这样一段代码:
if (this.ctx.accepts('html')) {
url = escape(url)
this.type = 'text/html; charset=utf-8'
this.body = `Redirecting to <a href="${url}">${url}</a>.`
return
}
这里如果浏览器可以接收 html,koa 会在 body 添加一个 a 标签,这里会把 url 中的信息通过 a 标签渲染到页面上,由于 url 信息可能会包含特殊的 html 字符串,因此此处经过了一次 escape-html 处理,源码如下:
var matchHtmlRegExp = /["'&<>]/
function escapeHtml (string) {
var str = '' + string
var match = matchHtmlRegExp.exec(str)
if (!match) {
return str
}
var escape
var html = ''
var index = 0
var lastIndex = 0
for (index = match.index; index < str.length; index++) {
switch (str.charCodeAt(index)) {
case 34: // "
escape = '"'
break
case 38: // &
escape = '&'
break
case 39: // '
escape = '''
break
case 60: // <
escape = '<'
break
case 62: // >
escape = '>'
break
default:
continue
}
if (lastIndex !== index) {
html += str.substring(lastIndex, index)
}
lastIndex = index + 1
html += escape
}
return lastIndex !== index
? html + str.substring(lastIndex, index)
: html
}
代码逻辑本身不复杂,这里的匹配表达式为 /["'&<>]/
,把对应的五个特殊字符替换为安全的字符编码即可。
以上是两个字符串相关库的源码,这次内容很少,可以看出字符串处理离不开正则表达式的灵活应用,在前面 header 相关的库中也能看到很多相关的实践。
今天的文章Koa 依赖的库 encodeurl 和 escape-html分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21753.html