网络通信第二课 HTTP报文请求数据编码 application/x-www-form-urlencoded

简介:

1编码说明

网页中的表单使用POST方法提交时,数据内容的类型是 application/x-www-form-urlencoded,这种类型会:

 

1.字符"a"-"z""A"-"Z""0"-"9"".""-""*",和"_"都不会被编码;

 

2.将空格转换为加号 (+) ;

 

3.将非文本内容转换成"%xy"的形式,xy是两位16进制的数值;

 

4.在每个 name=value 对之间放置 & 符号。

 

*/

 

  诸如字符: / & ? @ # ; $ + =  %也可以被使用,但是它们各有其特殊的用途,如果一个文件名包括了这些字符( / & ? @ # ; $ + = %)

这些字符和所有其他字符就应该被编码。

 

 编码过程非常简单,任何字符只要不是ASCII码数字,字母,或者前面提到的标点符,它们都将被转换成字节形式,每个字节都写成这种形式:

一个“%”后面跟着两位16进制的数值。空格是一个特殊情况,因为它们太平常了。它除了被编码成“%20”以外,还能编码为一个“+”。

加号(+)本身被编码%2B。当/ # = & ?作为名字的一部分来使用时,而不是作为URL部分之间的分隔符来使用时,它们都应该被编码。

参考

http://www.cnblogs.com/jingzhishen/p/3506339.html

 

编码实现

C++libcurl库并没有提供一个类似C#URLEncoder类,或者类似Javahttpclient的具体实现,,因此提供如下的案例代码

unsigned char ToHex(unsigned char x)

{

         return  x > 9 ? x + 55 : x + 48;

}

 

unsigned char FromHex(unsigned char x)

{

         unsignedchar y;

         if(x >= 'A' && x <= 'Z') y = x - 'A' + 10;

         elseif (x >= 'a' && x <= 'z') y = x - 'a' + 10;

         elseif (x >= '0' && x <= '9') y = x - '0';

         elseassert(0);

         returny;

}

 

std::string UrlEncode(conststd::string& str)

{

         std::stringstrTemp = "";

         size_tlength = str.length();

         for(size_t i = 0; i < length; i++)

         {

                   if(isalnum((unsigned char)str[i]) ||

                            (str[i]== '-') ||

                            (str[i]== '_') ||

                            (str[i]== '.') ||

                            (str[i]== '~'))

                            strTemp+= str[i];

                   elseif (str[i] == ' ')

                            strTemp+= "+";

                   else

                   {

                            strTemp+= '%';

                            strTemp+= ToHex((unsigned char)str[i] >> 4);

                            strTemp+= ToHex((unsigned char)str[i] % 16);

                   }

         }

         returnstrTemp;

}

 

std::string UrlDecode(conststd::string& str)

{

         std::stringstrTemp = "";

         size_tlength = str.length();

         for(size_t i = 0; i < length; i++)

         {

                   if(str[i] == '+') strTemp += ' ';

                   elseif (str[i] == '%')

                   {

                            assert(i+ 2 < length);

                            unsignedchar high = FromHex((unsigned char)str[++i]);

                            unsignedchar low = FromHex((unsigned char)str[++i]);

                            strTemp+= high * 16 + low;

                   }

                   elsestrTemp += str[i];

         }

         returnstrTemp;

}

生产环境编码

上面的代码是对=&也进行了编码,但是在实际的生产环境中,如果请求数据中携带的是Json格式,并且数据中使用了参数=的方式,这种情况下=&不应该被编码,所以应该单独拆分进行编码,json内容进行编码,参数键值不应该被编,代码修改如下:

std::string UrlEncode(conststd::string& str)

{

         std::stringstrTemp = "";

         size_tlength = str.length();

         for(size_t i = 0; i < length; i++)

         {

                   if(isalnum((unsigned char)str[i]) ||

                            (str[i]== '-') ||

                            (str[i]== '_') ||

                            (str[i]== '.') ||

                            (str[i]== '~') ||

                            (str[i]== '&') ||

                            (str[i]== '='))

                            strTemp+= str[i];

                   elseif (str[i] == ' ')

                            strTemp+= "+";

                   else

                   {

                            strTemp+= '%';

                            strTemp+= ToHex((unsigned char)str[i] >> 4);

                            strTemp+= ToHex((unsigned char)str[i] % 16);

                   }

         }

         returnstrTemp;

}

 

std::string UrlDecode(conststd::string& str)

{

         std::stringstrTemp = "";

         size_tlength = str.length();

         for(size_t i = 0; i < length; i++)

         {

                   if(str[i] == '+') strTemp += ' ';

                   elseif (str[i] == '%')

                   {

                            assert(i+ 2 < length);

                            unsignedchar high = FromHex((unsigned char)str[++i]);

                            unsignedchar low = FromHex((unsigned char)str[++i]);

                            strTemp+= high * 16 + low;

                   }

                   elsestrTemp += str[i];

         }

         returnstrTemp;

}

 

4 restful接口编码

application/x-www-form-urlencoded指定了发送的POST数据,要进行URL编码,但是前面的&,=用在POST报文前面,作为参数的时候,是不需要进行编码的,可以直接跳过。例如:

loginusername=admin&loginpassword=admin&param={JSON报文}

对于前面的两个&&都不能进行编码,否则Java后台无法正常解析出POST数据。目前JSON报文里面存在一个uri:

http://192.168.0.225:8080/kms/services/rest/dataInfoService/downloadFileid=00000001/temp001/097_5848300_10488&token=7a57a5a7ffffffffc1a0316369671314

里面存在&,如果没有进行URL编码的话,Java后台无法正常解析出报文

因此对以前的url编码函数进行了简单的处理

std::string UrlEncode(const std::string&str)

{

         std::stringstrTemp = "";

         size_tlength = str.length();

         for(size_t i = 0; i < length; i++)

         {

                   /*

                   前面的&用来对多个参数键值进行区分,不能进行编码,后面的&必须进行编码

                   */

                   if(i < 50 && str[i] == '&')

                   {

                            strTemp+= str[i];

                            continue;

                   }

                   if(isalnum((unsigned char)str[i]) ||

                            (str[i]== '-') ||

                            (str[i]== '_') ||

                            (str[i]== '.') ||

                            (str[i]== '~') ||

                            (str[i]== '='))

                            strTemp+= str[i];

                   elseif (str[i] == ' ')

                            strTemp+= "+";

                   else

                   {

                            strTemp+= '%';

                            strTemp+= ToHex((unsigned char)str[i] >> 4);

                            strTemp+= ToHex((unsigned char)str[i] % 16);

                   }

         }

         returnstrTemp;

}

 

50是一个大致的数字,应该分别对json格式内容进行编码,而不是对整一个发送报文进行编码




     本文转自fengyuzaitu 51CTO博客,原文链接: http://blog.51cto.com/fengyuzaitu/1956060 ,如需转载请自行联系原作者


相关文章
|
7月前
|
XML JSON JavaScript
从解决跨域CSOR衍生知识 Network 网络请求深度解析:从快递系统到请求王国-优雅草卓伊凡
从解决跨域CSOR衍生知识 Network 网络请求深度解析:从快递系统到请求王国-优雅草卓伊凡
171 0
从解决跨域CSOR衍生知识 Network 网络请求深度解析:从快递系统到请求王国-优雅草卓伊凡
|
11月前
|
存储 C++
UE5 C++:自定义Http节点获取Header数据
综上,通过为UE5创建一个自定义HTTP请求类并覆盖GetResult方法,就能成功地从HTTP响应的Header数据中提取信息。在项目中使用自定义类,不仅可以方便地访问响应头数据,也可随时使用这些信息。希望这种方法可以为你的开发过程带来便利和效益。
422 35
|
10月前
|
存储 数据库 Python
使用HTTP POST协议将本地压缩数据发送到服务器
总的来说,使用HTTP POST协议将本地压缩数据发送到服务器是一个涉及多个步骤的过程,包括创建压缩文件,设置HTTP客户端,发送POST请求,以及服务器端的处理。虽然这个过程可能看起来复杂,但一旦你理解了每个步骤,就会变得相对简单。
353 19
|
11月前
|
安全 网络安全 定位技术
网络通讯技术:HTTP POST协议用于发送本地压缩数据到服务器的方案。
总的来说,无论你是一名网络开发者,还是普通的IT工作人员,理解并掌握POST方法的运用是非常有价值的。它就像一艘快速,稳定,安全的大船,始终为我们在网络海洋中的冒险提供了可靠的支持。
312 22
|
JSON Java 数据格式
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
299 25
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
|
前端开发 小程序 Java
uniapp-网络数据请求全教程
这篇文档介绍了如何在uni-app项目中使用第三方包发起网络请求
958 3
|
消息中间件 测试技术
通过轻量消息队列(原MNS)主题HTTP订阅+ARMS实现自定义数据多渠道告警
轻量消息队列(原MNS)以其简单队列模型、轻量化协议及按量后付费模式,成为阿里云产品间消息传输首选。本文通过创建主题、订阅、配置告警集成等步骤,展示了该产品在实际应用中的部分功能,确保消息的可靠传输。
315 2
|
数据采集 Web App开发 开发工具
|
数据安全/隐私保护
|
JSON Java 数据格式
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
664 1