URL编码问题


URL为何需要编码

对于Url来说,之所以要进行编码,是因为Url中有些字符会引起歧义。

URL中采用何种编码

Url的编码格式采用的是ASCII码,而不是Unicode,这也就是说你不能在Url中包含任何非ASCII字符 
Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。

如何对URL编码

例如a在US-ASCII码中对应的字节是0x61,那么Url编码之后得到的就是%61,我们在地址栏上输入http://g.cn/search?q=%61%62%63,实际上就等同于在google上搜索abc了。对于非ASCII字符,需要使用ASCII字符集的超集进行编码得到相应的字节,然后对每个字节执行百分号编码。如”中文”使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,经过Url编码之后得到”%E4%B8%AD%E6%96%87”。

URL编码转换形式

URL 编码将字符转变成对 URL 解析无意义的无害形式。它将字符转化成为一种特定字符编码的字节序列,然后将字节转换为16进制形式,并将其前面加上”%”。问号的 URL 编码形式为”%3F”。我们可以将指向 “to_be_or_not_to_be?.jpg”图片的 URL 写成:”http://example.com/to_be_or_not_to_be%3F.jpg”,这样就没有人会认为这儿可能由一个查询部分了。

escape,encodeURI,encodeURIComponent

encodeURI被用作对一个完整的URI进行编码,而encodeURIComponent被用作对URI的一个组件进行编码。从上面提到的安全字符范围表格来看,我们会发现,encodeURIComponent编码的字符范围要比encodeURI的大。我们上面提到过,保留字符一般是用来分隔URI组件(一个URI可以被切割成多个组件,参考预备知识一节)或者子组件(如URI中查询参数的分隔符),如:号用于分隔scheme和主机,?号用于分隔主机和路径。由于encodeURI操纵的对象是一个完整的的URI,这些字符在URI中本来就有特殊用途,因此这些保留字符不会被encodeURI编码,否则意义就变了。 
  组件内部有自己的数据表示格式,但是这些数据内部不能包含有分隔组件的保留字符,否则就会导致整个URI中组件的分隔混乱。因此对于单个组件使用encodeURIComponent,需要编码的字符就更多了。

URL,URI

URI 是从虚拟根路径开始的 
URL是整个链接 
如URL http://zhidao.baidu.com/question/68016373.html 
URI 是/question/68016373.html 
在摆渡那边服务器上把http://zhidao.baidu.com/制作成了虚拟的路径的根 
URL是一种具体的URI,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI是一种语义上的抽象概念,可以是绝对的,也可以是相对的,而URL则必须提供足够的信息来定位,所以,是绝对的

表单提交

当Html的表单被提交时,每个表单域都会被Url编码之后才在被发送

解码后的URL不能被再编码为同样的形式

如果你解码”http://example.com/blue%2Fred%3Fand+green” 为”http://example.com/blue/red?and+green”,然后对它进行编码(哪怕使用一个对URL每一部分都很了解的编码器),你将会得到”http://example.com/blue/red?and+green”,这是因为它已经是一个有效的URL。它跟我们解码之前的URL非常的不同

其他

很多HTTP监视工具或者浏览器地址栏等在显示Url的时候会自动将Url进行一次解码(使用UTF-8字符集),这就是为什么当你在Firefox中访问Google搜索中文的时候,地址栏显示的Url包含中文的缘故。但实际上发送给服务端的原始Url还是经过编码的。你可以在地址栏上使用Javascript访问location.href就可以看出来了。在研究Url编解码的时候千万别被这些假象给迷惑了。

一个http请求经过的几个环节

浏览器(ie firefox)【get/post】————>Servlet服务器——————————->浏览器显示 
编码 解码成unicode,然后将显示的内容编码 解码 
(1) 浏览器把URL(以及post提交的内容)经过编码后发送给服务器。 
(2) 这里的Servlet服务器实际上指的是由Servlet服务器提供的servlet实现ServletRequestWrapper,不同应用服务器的servlet实现不同,这些servlet的实现把这些内容解码转换为unicode,处理完毕后,然后再把结果(即网页)编码返回给浏览器。 
(3) 浏览器按照指定的编码显示该网页。当对字符串进行编码和解码的时候都涉及到字符集,通常使用的字符集为ISO8859-1、GBK、UTF-8、UNICODE。 
(1) 对于中文IE,如果在高级选项中选中总以UTF-8发送(默认方式),则PathInfo是URL Encode是按照UTF-8编码,QueryString是按照GBK编码。 
http://localhost:8080/example/中国?name=中国 
实际上提交是: 
GET /example/%E4%B8%AD%E5%9B%BD?name=%D6%D0%B9%FA

(2) 对于中文IE,如果在高级选项中取消总以UTF-8发送,则PathInfo和QueryString是URL encode按照GBK编码。 
实际上提交是: 
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

网址路径的编码,用的是utf-8编码 
查询字符串的编码,用的是操作系统的默认编码(直接输入网址) 
GET和POST方法的编码,用的是网页的编码:< meta http-equiv=”Content-Type” content=”text/html;charset=xxxx”> 
在Ajax调用中,IE总是采用GB2312编码(操作系统的默认编码),而Firefox总是采用utf-8编码。这就是我们的结论4。 
encodeURIComponent()。与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RestTemplate在发送HTTP请求,有出现URL编码问题。根据引用\[1\]和引用\[3\]的内容,可以看出在发送请求前,可以通过设置RestTemplate的消息转换器来解决URL编码问题。具体做法是使用`restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(StandardCharsets.UTF_8))`来设置编码为UTF-8。这样可以确保URL中的参数不被错误地编码为%25。另外,根据引用\[2\]的内容,还可以通过自己封装URI的方式来解决URL编码问题,具体做法是使用`URI.create(url + myparams + signUrl)`来创建URI对象,然后使用`restTemplate.postForEntity(uriObj, request, String.class)`来发送请求。这样可以确保URL中的参数不被错误地编码。 #### 引用[.reference_title] - *1* [SpringBoot RestTemplate 解决编码问题 UTF8](https://blog.csdn.net/weixin_42195284/article/details/114935420)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [springboot中使用restemplate,请求接口url参数的%编码为%25问题解决](https://blog.csdn.net/weixin_45973130/article/details/120896847)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值