笔者遇到过这样一个需求,在http的拦截器中拦截url并添加一些额外的参数,代码如下:
// http request 拦截器
// instance: axios实例
this.instance.interceptors.request.use(
config => {
const authParams: any = LocalStorage.get(STORAGE_KEY.IFRAME_PARAMS)
// 替换url,替换参数
const {url, baseURL, params} = config
let [pathname, search] = url.split('?')
const temp = search ? this.parseParams(search) : {}
Object.assign(temp, authParams) // 覆盖原请求中的部分参数
const newParams = this.getQueryString(temp)
config.url = newParams ? `${pathname}?${newParams}` : pathname // 使用?拼接成新的url
return config
},
err => {
return Promise.reject(err)
})
/**
* @desc 解析跳转进来的路由参数,为对象
* '?type=1&iframe=true'
* =>
* {type: "1"
iframe: "true"
}
*/
parseParams(search) {
const ret = {},
seg = search.replace(/^\?/, '').split('&'),
len = seg.length
let i = 0, s
for (; i < len; i++) {
if (!seg[i]) {
continue
}
s = seg[i].split('=')
ret[s[0]] = s[1]
}
return ret
}
比如拦截http请求(1):
https://xxx.com/report/list?title=customer_number&endTime=2020-06-30%2023:59:59&startTime=2020-06-01%2000:00:00&pageSize=20¤tPageNo=1
添加参数后变成请求(2):
https://xxx.com/report/list?timestamp=1595314770&sign=9bc3fd371169e2b4fb6184ed081b0817¤tPageNo=1&pageSize=20&startTime=2020-06-01%252000:00:00&endTime=2020-06-30%252023:59:59&title=customer_number
对比可知添加了参数:
// B
{
timestamp: 1595314770,
sign:9bc3fd371169e2b4fb6184ed081b0817
}
我的做法是解析成元url中?后面的参数成object(A),然后把新的参数(B)拼接到A上,再更新新的url的参数,看似逻辑木得问题,但是!发请求的时候就是失败,并且报错:参数[startTime]格式错误,咦,笔者都没有操作startTime啊,怎么会参数错误呢?
笔者瞪大着高度近视的小眼睛,观察了半天才发现,原来两个url中的startTime参数真的不一样,
请求(1)中startTime:startTime=2020-06-01%2000:00:00
请求(2)中startTime:startTime=2020-06-01%252000:00:00
额,笔者当时上传的参数未:startTime=2020-06-01 00:00:00
,明明是空格(space),肿么变成了%20,又变成了%25呢?原来是特殊字符的锅。。。
由于url支持26个英文字母、数字和少数几个特殊字符,因此,对于url中包含非标准url的字符时,就需要对其进行编码。
较为特殊的字符例如:@&=+$,/?%!*’();:#[]
当客户端发请求时,浏览器会自动对含有这些字符的部分进行处理,根据的HTML URL 编码表
可以发现,笔者参数中的空格()被转义成了
%20
,在拦截器中拦截请求时,%
又是特殊字符,被转义成了%25
,因此请求(2)的startTime会变成2020-06-01%252000:00:00
,既然bug找到了,下面就是解决bug啦ღღღღღღ
既然请求(1)中2020-06-01 00:00:00
被转义成了2020-06-01%2000:00:00
,那么我们把2020-06-01%2000:00:00
反转义成真实的字符,那么请求(2)中再转义一次也还是正确的,就不会报错啦❀
因此笔者优化了的parseParams()
,如下,第二行中的decodeURIComponent(search)
可以对对编码后的search
进行解码,将诸如%20这样的字符解码成特殊字符空格()
parseParams(search) {
const ret = {}, seg = decodeURIComponent(search).replace(/^\?/, '').split('&'), len = seg.length
let i = 0, s
for (; i < len; i++) {
if (!seg[i]) {
continue
}
s = seg[i].split('=')
ret[s[0]] = s[1]
}
return ret
}
点击F12(或者Fn + F12)打开控制台,输入如下指令:
console.log(decodeURIComponent("%2b"))
把%2b替换为你想查询的16进制(+
)即可。
URL 编码 - 从 %00 到 %8f
ASCII Value | URL-encode | ASCII Value | URL-encode | ASCII Value | URL-encode |
---|---|---|---|---|---|
æ | %00 | 0 | %30 | ` | %60 |
%01 | 1 | %31 | a | %61 | |
%02 | 2 | %32 | b | %62 | |
%03 | 3 | %33 | c | %63 | |
%04 | 4 | %34 | d | %64 | |
%05 | 5 | %35 | e | %65 | |
%06 | 6 | %36 | f | %66 | |
%07 | 7 | %37 | g | %67 | |
backspace | %08 | 8 | %38 | h | %68 |
tab | %09 | 9 | %39 | i | %69 |
linefeed | %0a | : | %3a | j | %6a |
%0b | ; | %3b | k | %6b | |
%0c | < | %3c | l | %6c | |
c return | %0d | = | %3d | m | %6d |
%0e | > | %3e | n | %6e | |
%0f | ? | %3f | o | %6f | |
%10 | @ | %40 | p | %70 | |
%11 | A | %41 | q | %71 | |
%12 | B | %42 | r | %72 | |
%13 | C | %43 | s | %73 | |
%14 | D | %44 | t | %74 | |
%15 | E | %45 | u | %75 | |
%16 | F | %46 | v | %76 | |
%17 | G | %47 | w | %77 | |
%18 | H | %48 | x | %78 | |
%19 | I | %49 | y | %79 | |
%1a | J | %4a | z | %7a | |
%1b | K | %4b | { | %7b | |
%1c | L | %4c | | | %7c | |
%1d | M | %4d | } | %7d | |
%1e | N | %4e | ~ | %7e | |
%1f | O | %4f | %7f | ||
space(空格) | %20 | P | %50 | € | %80 |
! | %21 | Q | %51 | %81 | |
" | %22 | R | %52 | ‚ | %82 |
# | %23 | S | %53 | ƒ | %83 |
$ | %24 | T | %54 | „ | %84 |
% | %25 | U | %55 | … | %85 |
& | %26 | V | %56 | † | %86 |
' | %27 | W | %57 | ‡ | %87 |
( | %28 | X | %58 | ˆ | %88 |
) | %29 | Y | %59 | ‰ | %89 |
* | %2a | Z | %5a | Š | %8a |
+ | %2b | [ | %5b | ‹ | %8b |
, | %2c | \ | %5c | Œ | %8c |
- | %2d | ] | %5d | %8d | |
. | %2e | ^ | %5e | Ž | %8e |
/ | %2f | _ | %5f | %8f |
URL 编码 - 从 %90 到 %ff
ASCII Value | URL-encode | ASCII Value | URL-encode | ASCII Value | URL-encode |
---|---|---|---|---|---|
%90 | À | %c0 | ð | %f0 | |
‘ | %91 | Á | %c1 | ñ | %f1 |
’ | %92 | Â | %c2 | ò | %f2 |
“ | %93 | Ã | %c3 | ó | %f3 |
” | %94 | Ä | %c4 | ô | %f4 |
• | %95 | Å | %c5 | õ | %f5 |
– | %96 | Æ | %c6 | ö | %f6 |
— | %97 | Ç | %c7 | ÷ | %f7 |
˜ | %98 | È | %c8 | ø | %f8 |
™ | %99 | É | %c9 | ù | %f9 |
š | %9a | Ê | %ca | ú | %fa |
› | %9b | Ë | %cb | û | %fb |
œ | %9c | Ì | %cc | ü | %fc |
%9d | Í | %cd | ý | %fd | |
ž | %9e | Î | %ce | þ | %fe |
Ÿ | %9f | Ï | %cf | ÿ | %ff |
%a0 | Ð | %d0 | |||
¡ | %a1 | Ñ | %d1 | ||
¢ | %a2 | Ò | %d2 | ||
£ | %a3 | Ó | %d3 | ||
%a4 | Ô | %d4 | |||
¥ | %a5 | Õ | %d5 | ||
| | %a6 | Ö | %d6 | ||
§ | %a7 | %d7 | |||
¨ | %a8 | Ø | %d8 | ||
© | %a9 | Ù | %d9 | ||
ª | %aa | Ú | %da | ||
« | %ab | Û | %db | ||
¬ | %ac | Ü | %dc | ||
¯ | %ad | Ý | %dd | ||
® | %ae | Þ | %de | ||
¯ | %af | ß | %df | ||
° | %b0 | à | %e0 | ||
± | %b1 | á | %e1 | ||
² | %b2 | â | %e2 | ||
³ | %b3 | ã | %e3 | ||
´ | %b4 | ä | %e4 | ||
µ | %b5 | å | %e5 | ||
¶ | %b6 | æ | %e6 | ||
· | %b7 | ç | %e7 | ||
¸ | %b8 | è | %e8 | ||
¹ | %b9 | é | %e9 | ||
º | %ba | ê | %ea | ||
» | %bb | ë | %eb | ||
¼ | %bc | ì | %ec | ||
½ | %bd | í | %ed | ||
¾ | %be | î | %ee | ||
¿ | %bf | ï | %ef |