url encode问题总结

456 阅读1分钟

问题

1. url.searchParams默认对参数编码;

let p = '123abc!*();:@&=+$,/?#[]-_.~ <>#%{}|\^`~'
let url = new URL() 
url.searchParams.set('par',par)
url.search // p=123abc%21*%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D-_.%7E+%3C%3E%23%25%7B%7D%7C%5E%60%7E

2. vue-router也会默认对参数进行编码;

url = 'abc.com?a=123/456+!789'

fullPath = 'abc.com?a%3D123%2F456%2B!789'

export default context => {
   const { url } = context;
   const { fullPath } = router.resolve(url).route
}

3. url跳转query参数丢失;

module.exports = (ctx, url) => {
    let queryStr = '';
    const { query } = ctx;
    const queryList = [];
    Object.keys(query).forEach((item) => {
       queryList.push(`${item}=${query[item]}`);
    });
    queryStr = `?${queryList.join('&')}`
}

example.com?target=encodeURIComponent(https://target.com…

这样重定向之后就只会存在a=1的参数;

结论:URL编码方式不同

Percent-encoding, also known as URL encodingURL 和 URLSearchParams 基于最新的 URL 规范:RFC3986,而 encode* 函数是基于过时的 RFC2396。它们之间有一些区别,例如对 IPv6 地址的编码方式不同:

RFC3986规定Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符

保留字符: ! * ' ( ) ; : @ & = + $ , / ? # [ ]

英文字母(a-zA-Z)、数字(0-9)、-_.*~[]<>%{}^`空格#$&,+:;=?/@!()
URLSearchParams-%7E%5B%5D%3C%3E%25%7B%7D%7C%5E%60+%23%24%26%2C%2B%3A%3B%3D%3F%2F%40%21%28%29
escape-%7E%5B%5D%3C%3E%25%7B%7D%7C%5E%60%20%23%24%26%2C-%3A%3B%3D%3F--%21%28%29
encodeURIComponent-%7E%5B%5D%3C%3E%25%7B%7D%7C%5E%60%20%23%24%26%2C%2B---!()
encodeURI-%7E%5B%5D%3C%3E%25%7B%7D%7C%5E%60%20#$&,-%3A%3B%3D%3F%2F%40!()

URL常见使用Query的方式

  • URL 和 URLSearchParams类型 zh.javascript.info/url

  • JS的API:escape、encodeURIComponent 和 encodeURI

  • 浏览器发出https请求

  • vue router的编码方式,调用浏览器的encodeURIComponent和decodeURIComponent;

let par = '123abc!*();:@&=+$,/?#[]-_.~ <>#%{}|\^`~'

1. URLSearchParams

! () ; : @ & = + $ , / ? # [ ] ~ < > % { } | \ ^ ` ~ 被转码

*-_. 未被转码

let url = new URLSearchParams() 
url.set('par',par) 
url.toString(); 
// par=123abc%21*%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D-_.%7E+%3C%3E%23%25%7B%7D%7C%5E%60%7E 
url.get('par') 
// '123abc!*();:@&=+$,/?#[]-_.~ <>#%{}|^`~'

URLSearchParams的set/append都会进行编码,get其实会进行解码;

但是URL的search会返回当前toString()的内容

image.png

url.spec.whatwg.org/#urlsearchp… image.png

urlSearchParams的编码方式:

  • 编码字符串:escape [] <>%{}|^` #$&, !();: =?~~ 被转码

  • 编码URL的参数:encodeURIComponent [] <>%{}|^` #$&+, /:;=?@ 被转码

  • 编码整个URL:encodeURI [] <>%{}|^` 被转码。

escape(par) 
// '123abc%21*%28%29%3B%3A@%26%3D+%24%2C/%3F%23%5B%5D-_.%7E%20%3C%3E%23%25%7B%7D%7C%5E%60%7E' 
encodeURIComponent(par) 
// '123abc!*()%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D-_.~%20%3C%3E%23%25%7B%7D%7C%5E%60~' 
encodeURI(par) 
// '123abc!*();:@&=+$,/?#%5B%5D-_.~%20%3C%3E#%25%7B%7D%7C%5E%60~'

encodeURI和encodeURIComponent的区别:

zh.javascript.info/url

一个自然的问题:“encodeURIComponent 和 encodeURI 之间有什么区别?我们什么时候应该使用哪个?”如果我们看一个 URL,就容易理解了,它被分解为本文上面图中所示的组件形式:site.com:8080/path/page?p…正如我们所看到的,在 URL 中 :,?,=,&,# 这类字符是被允许的。……另一方面,对于 URL 的单个组件,例如一个搜索参数,则必须对这些字符进行编码,以免破坏 URL 的格式。encodeURI 仅编码 URL 中完全禁止的字符。encodeURIComponent 也编码这类字符,此外,还编码 #,$,&,+,,,/,:,;,=,? 和 @ 字符。所以,对于一个 URL 整体aa,我们可以使用 encodeURI:而对于 URL 参数,我们应该改用 encodeURIComponent:

浏览器发出请求:

window.location.href 自动encode: 空格、`、<>