url查询字符串中的转义,众所周知,url中的转义是百分号转义。很多人都只知道一个大概,很少有人能精确说出哪个字符转义,哪个字符不转义。这篇文章从新版edge浏览器发射的请求,url查询字符串中,字符的转义情况。
发射的客户端,查询字符串代码为:
`?${char}=${printcode}`
char是未转义的字符,printcode是整数,表达为十六进制。例如!感叹号发送请求,将会是:
"?!=21"
服务器端,我们测试ASP.NET的接收情况,其代码是:
_logger.LogInformation("{0}{1}",
this.Request.QueryString.Value,
stringify(this.Request.Query)
)
输出的第一部分是服务器端接收到请求的escaped字符串。第二部分是Query解析后的键值对。stringify是将其序列化的函数,细节忽略。
很明显,不可打印的非控制字符将会百分号转义。非ascii字符也会被百分号转义。我们测试可打印ascii字符(32~127)的转义情况。
和我们预想的一样,数字和字母,不转义:
?0=30["0","30"]
...
?9=39["9","39"]
?A=41["A","41"]
...
?Z=5A["Z","5A"]
?a=61["a","61"]
...
?z=7A["z","7A"]
其他不转义的符号有:
?!=21["!","21"]
?$=24["#34;,"24"]
?(=28["(","28"]
?)=29[")","29"]
?*=2A["*","2A"]
?,=2C[",","2C"]
?-=2D["-","2D"]
?.=2E[".","2E"]
?/=2F["/","2F"]
?:=3A[":","3A"]
?;=3B[";","3B"]
??=3F["?","3F"]
?@=40["@","40"]
?[=5B["[","5B"]
?\=5C["\\","5C"]
?]=5D["]","5D"]
?^=5E["^","5E"]
?_=5F["_","5F"]
?`=60["`","60"]
?{=7B["{","7B"]
?|=7C["|","7C"]
?}=7D["}","7D"]
?~=7E["~","7E"]
下面这些是字符有特定的用途,浏览器不会自动转义,如表示原义需要手工转义,避免服务器解释错误:
?[]//#23:#表示查询字符串的结束,所以查询字符串只有一个问号
?%=25["%","25"] //表示百分号编码的关键字
?&=26["","26"] //键值对的分隔符
?+=2B[" ","2B"] //被Query解析为空格
?==3D["","=3D"] //键与值的分隔符
下面这些是可以自动被浏览器百分号转义的字符:
?%20=20[" ","20"]
?%22=22["\"","22"]
?%27=27["'","27"]
?%3C=3C["<","3C"]
?%3E=3E[">","3E"]
?%7F=7F["\u007F","7F"]
后记
URL转义规则一直在不断变化,对于新版本升级,我们需要不断地进行回归测试。