URL编码
问题场景:URL中有中文字符时,无法向这个URL发送GET请求
我尝试了一下使用Chrome浏览器输入带中文字符的URL是可以的,这就勾起了我的疑问,难道是我中文编码的问题?
显然并不是中文编码GBK或是UTF8的问题,在Chrome里打开F12抓包,发现带有中文的URL在发送时变成了另一种格式,中文字符变成了%2D%FG%…这样的十六进制,网上搜了一下什么是URLencode,总结一下自己遇到的问题和解决办法。
URLencode
为了符合URL规范的一种编码格式。在URL标准规范中,是不允许出现中文字符的。所以要转换为一种通用的且规范的URL格式。
URL规范说明
URLencode 原理(代码解释)
- 空格转换为 ‘+’
- 非ASCII码能打印的字符转换为 %+两个十六进制数表示的字符,例如十六进制数0xAB23 ,要将其转换为%AB%23。
- 一个十六进制数是4位表示,而一个unsigned char是8位,包含了两个十六进制数。故需要将unsigned char 的高4位和低4位转换成为两个字符,先转高4位,再转低4位。
unsigned char CHAR_TO_HEX(unsigned char ch)
{
return (unsigned char)(ch > 9 ? ch + 55 : ch + 48);
}
/// <summary>
/// url编码,使其能够给带中文的url发送请求
/// </summary>
/// <param name="org_url">UTF8编码的url</param>
/// <returns>转码后的url</returns>
string url_encode(const string& org_url)
{
unsigned char ch_temp;
string str_dest;
cout << "原字符串:" << org_url << endl;
for (const char ch : org_url) {
ch_temp = static_cast<unsigned char>(ch);
// 'a'~'z' 'A'~'Z' '0'~'9' \:-_.!~*()/ 这些字符不转
if ((ch_temp >= 'a' && ch_temp <= 'z') || (ch_temp >= 'A' && ch_temp <= 'Z')
|| (ch_temp >= '0' && ch_temp <= '9') || strchr("\\:-_.!~*()/", ch_temp)) {
str_dest += ch_temp;
}
else if (ch_temp == ' ') {
str_dest += '+';
}
else {
str_dest += '%';
/**
* 一个unsigned char 是8位,有两个十六进制数
* 四位是一个十六进制数,先转换高4位,右移4位去除低4位
* 去除高4位再转换低4位
* 0xDE -> "DE"
*/
//cout << "原十六进制数:" <<std::uppercase << std::hex<< (int)ch_temp <<endl;
str_dest += CHAR_TO_HEX((unsigned char)(ch_temp >> 4));
str_dest += CHAR_TO_HEX((unsigned char)(ch_temp & 0x0f));
}
}
cout << "转换后字符串:" << str_dest << endl;
return str_dest;
}