快捷搜索:  汽车  科技

urlencode怎么使用(最近遇到的问题记录)

urlencode怎么使用(最近遇到的问题记录)xxx接口前面铺垫的话有点啰嗦了,开发这个小工具时,开发小哥遇到一个问题:一条设备录入成功,单身多年的手速可能也花不了几分钟,其实这也没啥。突然领导说有1000个设备需要搞?运维小哥哥哭了,这时就该开发人员上场了:经过几天的开发工作,开发哥哥将精心打磨的小工具交给运维小哥,运维小哥哥使用后投来了赞许的目光...

本文阅读前了解知识:什么时候需要使用UrlEncode和UrlDecode函数

作者使用谷歌浏览器,通过按下F12对第三方网站http协议的接口抓包进行分析操作。

场景

运维小哥哥偶尔使用某某外包公司的网站系统,做设备录入工作,流程简单:

urlencode怎么使用(最近遇到的问题记录)(1)

录入设备信息

  1. 录入设备基本信息,有7、8个字段需要输入,然后点击保存按钮;
  2. 基本信息保存成功,进入设备类型选择操作,然后点击生成设备标识按钮;
  3. 设备标识生成成功,录入设备关联的模块信息,简单设备只需要录入2条模块,复杂的设备有6条模块,每个模块有3、4个字段需要输入,最后点击保存。

一条设备录入成功,单身多年的手速可能也花不了几分钟,其实这也没啥。

突然领导说有1000个设备需要搞?运维小哥哥哭了,这时就该开发人员上场了:

  1. 运维准备一个Excel模板,输入需要录入的1000个设备基本信息、设备类型信息,这个工作量不大,就半天吧,最多一天工作量;
  2. 开发做个C/S客户端小工具,程序中按业务要求配置模块录入规则;
  3. 程序执行过程中录入一个设备就把生成的设备标识与设备关联;
  4. 全部录入完成,提供一个Excel导出,可将设备基本信息、生成的设备标识全部关联导出,工作完成。

经过几天的开发工作,开发哥哥将精心打磨的小工具交给运维小哥,运维小哥哥使用后投来了赞许的目光...

问题

前面铺垫的话有点啰嗦了,开发这个小工具时,开发小哥遇到一个问题:

urlencode怎么使用(最近遇到的问题记录)(2)

xxx接口

这是某个接口的信息,Content-Type 是 application/x-www-form-urlencoded 下面参数使用的Form Data,即参数使用了UrlEncode,比如未编码前的一个参数:

"Content":"{"AP_Name":"HK_7889" "IP":"192.168.0.1"}"

编码后(可以使用这个在线URL编码解码工具验证):

"Content":"{"AP_Name":"HK_7889" "IP":"92.168.0.1"}"

使用Postman测试时,未对参数使用UrlEncode,接口测试成功 开发这个小工具时,有3个接口都是类似的,未进行UrlEncode操作:

varclient=newRestClient("http://admin.lqclass.com/api/device"); client.Timeout=-1; varrequest=newRestRequest(Method.POST); request.AddHeader("Content-Type" "application/x-www-form-urlencoded"); request.AddParameter("Content" "{\"AP_Name\":\"HK_7889\" \"IP\":\"92.168.0.1\"}"); IRestResponseresponse=client.Execute(request); Console.WriteLine(response.Content);

但遇到稍微复杂一点的接口,比如截图中的参数为:

"Content":"{"AP_Name":"HK_7889" "IP":"192.168.0.1" "Module":[{"M_Name":"cameri0" "Desc":"cameri0" "AP_PUID":"54632325461320320"} {"M_Name":"cameri1" "Desc":"cameri1" "AP_PUID":"54636325461320320"} {"M_Name":"cameri2" "Desc":"cameri2" "AP_PUID":"54632325421320320"}]}"

Content值格式化看得清楚一点,Module是设备关联的模块信息:

{ "AP_Name":"HK_7889" "IP":"192.168.0.1" "Module":[ { "M_Name":"cameri0" "Desc":"cameri0" "AP_PUID":"54632325461320320" } { "M_Name":"cameri1" "Desc":"cameri1" "AP_PUID":"54636325461320320" } { "M_Name":"cameri2" "Desc":"cameri2" "AP_PUID":"54632325421320320" } ] }

实际UrlEncode后的参数为:

"Content":"{"AP_Name":"HK_7889" "IP":"192.168.0.1" "Module":"%5B%7B%22M_Name%22%3A%22cameri0%22%2C%22Desc%22%3A%22cameri0%22%2C%22AP_PUID%22%3A%2254632325461320320%22%7D%2C%7B%22M_Name%22%3A%22cameri1%22%2C%22Desc%22%3A%22cameri1%22%2C%22AP_PUID%22%3A%2254636325461320320%22%7D%2C%7B%22M_Name%22%3A%22cameri2%22%2C%22Desc%22%3A%22cameri2%22%2C%22AP_PUID%22%3A%2254632325421320320%22%7D%5D"}"

本来一般接口,如上面成功执行的C#代码那般直接未UrlEncode调用是没问题的。

但这个接口调用,服务器返回错误信息:“xxx解析失败”,调用代码如下:

varclient=newRestClient("http://admin.lqclass.com/api/device"); client.Timeout=-1; varrequest=newRestRequest(Method.POST); request.AddHeader("Content-Type" "application/x-www-form-urlencoded"); request.AddParameter("Content" "{\"AP_Name\":\"HK_7889\" \"IP\":\"192.168.0.1\" \"Module\":[{\"M_Name\":\"cameri0\" \"Desc\":\"cameri0\" \"AP_PUID\":\"54632325461320320\"} {\"M_Name\":\"cameri1\" \"Desc\":\"cameri1\" \"AP_PUID\":\"54636325461320320\"} {\"M_Name\":\"cameri2\" \"Desc\":\"cameri2\" \"AP_PUID\":\"54632325421320320\"}]}"); IRestResponseresponse=client.Execute(request); Console.WriteLine(response.Content);

两处调用代码哪里不同?只是Content值不一样,最后怀疑是不是需要手动进行UrlEncode?又不是url参数,为啥需要编码呢?不管啦,先编码了再说。

问题解决

参数编码后,调用:

varclient=newRestClient("http://admin.lqclass.com/api/device"); client.Timeout=-1; varrequest=newRestRequest(Method.POST); request.AddHeader("Content-Type" "application/x-www-form-urlencoded"); request.AddParameter("Content" "{"AP_Name":"HK_7889" "IP":"192.168.0.1" "Module":"%5B%7B%22M_Name%22%3A%22cameri0%22%2C%22Desc%22%3A%22cameri0%22%2C%22AP_PUID%22%3A%2254632325461320320%22%7D%2C%7B%22M_Name%22%3A%22cameri1%22%2C%22Desc%22%3A%22cameri1%22%2C%22AP_PUID%22%3A%2254636325461320320%22%7D%2C%7B%22M_Name%22%3A%22cameri2%22%2C%22Desc%22%3A%22cameri2%22%2C%22AP_PUID%22%3A%2254632325421320320%22%7D%5D"}"); IRestResponseresponse=client.Execute(request); Console.WriteLine(response.Content);

哈哈,成功了,这里简单猜测下:别人的服务对接收的参数可能做了UrlDecode操作。

其实中间还做了一个参数的UrlEncode操作,即下面的Module参数值:

"Content":{"AP_Name":"HK_7889" "IP":"192.168.0.1" "Module":[{"M_Name":"cameri0" "Desc":"cameri0" "AP_PUID":"54632325461320320"} {"M_Name":"cameri1" "Desc":"cameri1" "AP_PUID":"54636325461320320"} {"M_Name":"cameri2" "Desc":"cameri2" "AP_PUID":"54632325421320320"}]}

第一次UrlEncode,即先对Module的值进行UrlEncode:

"Content":{"AP_Name":"HK_7889" "IP":"192.168.0.1" "Module":[{"M_Name":"cameri0" "Desc":"cameri0" "AP_PUID":"54632325461320320"} {"M_Name":"cameri1" "Desc":"cameri1" "AP_PUID":"54636325461320320"} {"M_Name":"cameri2" "Desc":"cameri2" "AP_PUID":"54632325421320320"}]}

第二次UrlEncode即是上面成功的参数方式了,对整个Content的值进行UrlEncode,看上面成功的参数,不重复贴了。

最后总结

抓别人数据包时,不要凭印象、已有知识判定该怎么怎么做,比如前面的参数,不使用UrlEncode时,调用成功了,其他包我是否也沿用相同的方式使用就正确呢?搞不定时,多尝试猜测的方法。

总结:“管他的,干就是了”。

本文使用的UrlEncode C# 代码:

publicstaticstringUrlEncode(stringstr) { StringBuildersb=newStringBuilder(); byte[]byStr=System.Text.Encoding.UTF8.GetBytes(str);//默认是System.Text.Encoding.Default.GetBytes(str) for(inti=0;i<byStr.Length;i ) { sb.Append(@"%" Convert.ToString(byStr[i] 16)); } return(sb.ToString()); }

猜您喜欢: