温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2020-10-03 21:09:06 来源:网络 阅读:3458 作者:fengyuzaitu 栏目:系统运维

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

 

2 编码实现

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;

}

3 生产环境编码

上面的代码是对=&也进行了编码,但是在实际的生产环境中,如果请求数据中携带的是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格式内容进行编码,而不是对整一个发送报文进行编码


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI