Url 编码以及在 Nginx 中的实现
最近在看编码方面的东西, 这里对url编码(Percent-encoding)做一个简单的总结. 然后再看一下nginx中的url编码的实现方式.
url 编码
好吧, 有关url编码, 貌似这个东西被题了N+1遍了, 但是我比较关心的问题有三个:
- 为什么要进行url编码
- 怎么编码
- 有哪些细节需要注意
url编码是一种传输url的机制, 个人认为最主要的作用是区分字符是否有特殊意义. 我们都知道有许多字符在url中是有特殊含义的, 比如?
作为参数开始的标志, 又比如&
作为参数切分标志. 因此如果想要让这些
字符保留字符原本含义就需要对它们进行url编码. 另外一个作用是用来传递非可视字符. url编码的主要内容是: 0-9A-Za-z
以及-
, ~
, .
, ~
无需通过编码即可传输(普通字符), 而以下字符(保留字符):
! | * | ‘ | ( | ) | ; | : | @ | & | = | + | $ | , | / | ? | # | [ | ] |
如果要当作字符常量对待则需要经过编码. 另外其他的字符都需要进过url编码来进行传输. 编码形式是%
后跟对应的十六进制形式.
这里需要注意的有两点:
- 编码并非是强制性, 即使是普通字符我们也可以进行编码然后进行传输
- 在参数部分, 空格会被编码成
+
而非%25
, 参见这里的The application/x-www-form-urlencoded type一节, 所以会造成经过base64编码的内容直接传输时, 加号在经过解码之后变为空格. 针对这个问题衍生出了其他的base64方式(主要是替换了/
,+
)
这里再推荐一下阮一峰大哥的这篇文章, 写的挺好的~
nginx 的实现
从原理上讲url编码还是蛮容易的, 编码就是遇到非普通字符就开始转换, 解码就是遇到百分号就开始转换(这里可能还需要考虑到各种情况, 诸如上面提到的+号的情况).
如果现在让我来实现, 我可能就直接按字符的asc码比较来进行转换了. 学编程的进步方法之一就是看优秀的代码, 那我们不妨来看看nginx中是如何实现url编码的(因为nginx考虑的url编码情况比较多, 甚至涵盖了memcached的情况, 这里就对最普通的url编码进行解析):
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 |
|
代码很精简, 同时也很高效. 这里利用bitmap法来判断字符是否需要进行url编码(赞). 最关键的一句是:
1 2 3 4 |
|
如果我利用位图法我会将字符先分组(除以32), 然后再与上取其偏移量(模32)来取得bitmap的值. 上面就是在用位运算做这个事情, 真心学习了. 而转十六进制的时候同样使用了这个方法. 强大的位运算~
PPPPSSSS
《屌丝男士》第二季结束了, 还是非常有意思的. 友情出演的同学(邓超, 汤唯, 李晨, 波多野结衣, 温兆伦等)也都很给力~ 希望能出第三季~