我已经找到了问题Automatically Decode GZIP In TRESTResponse?,但由于某种原因,这个答案并没有解决我的问题.
测试设置
在XE5中,我添加了TRestClIEnt,TRestRequest和具有以下相关属性的TRestResponse.我设置了客户端的BaseURL,请求的资源和参数,并将请求的AcceptEnCoding设置为gzip,deflate,这应该使它自动解码gzipped响应.
object RESTClIEnt1: TRESTClIEnt BaseURL = 'https://API.stackexchange.com/2.2' end object RESTRequest1: TRESTRequest AcceptEnCoding = 'gzip,deflate' ClIEnt = RESTClIEnt1 Params = < item Kind = pkURLSEGMENT name = 'ID' Options = [poautocreated] Value = '511529' end item name = 'site' Value = 'stackoverflow' end> Resource = 'users/{ID}' Response = RESTResponse1 end object RESTResponse1: TRESTResponse end
这导致url:
07001
我调用这样的请求,有两个消息框来显示url和请求的结果:
ShowMessage(RESTRequest1.GetFullRequestURL());RESTRequest1.Execute; // Actual callShowMessage(RESTResponse1.Content);
如果我在浏览器中调用该URL,我会得到一个正确的结果,这是一个Json对象,其中包含我的一些用户信息.
问题
但是,在Delphi中,我没有得到JsON响应.实际上,我得到了一堆字节,这似乎是一个错误的gzip响应.我尝试使用TIDCompressorZlib.DecompressGZipStream()解压缩它,但它失败并出现Zlib错误(-3).当我自己检查响应的字节时,我看到它从#1F#3F#08开始.这特别奇怪,因为gzip标题应该是#1F#8B#08,所以#8B转换为#3F,这是一个问号.
所以在我看来,RESTClIEnt试图将gzip流解码为好像是UTF-8响应,并且用问号替换了无效序列(#8B本身不是有效的UTF-8字符).
尝试(表面)
我做了很多实验,比如
>使用RESTResponse.RawBytes并尝试解码它.我注意到这个字节数组中的字节已经无效. TRESTResponse来源中的评论告诉我’RawBytes’已经被解码,所以这是有道理的.
>将RESTResponse.RawBytes保存在一个文件中,并尝试使用7zip和几个在线gzip解压缩程序对其进行解压缩.当然,它们都失败了,因为即使是gzip标头也是错误的.
>将值’gzip,deflate’分配给TRESTClIEnt.AcceptEnCoding,TRESTResponse.AcceptEnCoding及其组合.还尝试将其附加到每个组件的预填充Accept属性.
>从经过身份验证的请求切换到未经身份验证的请求.我有整个oAuth部分工作,但我认为这会使问题过于复杂.我在这个问题中使用的匿名API也有同样的问题.
不幸的是它仍然无效,我仍然得到了错误的回应.
尝试(深入VCL)
最后,我挖了一点,然后潜入TRestRequest.Execute.我不会在这里粘贴所有代码,但最终它会通过调用来执行请求
FClIEnt.httpClIEnt.Get(LURL,LResponseStream);
FClIEnt是链接到请求的TRESTClIEnt,LResponseStream是TMemoryStream.我将LResponseStream.Savetofile(‘…’)添加到手表中,因此它会保存这个未经处理的结果,等等,它给了我一个有效的gz文件,我可以解压缩以获取我的JsON.
解决方案中的错误?
但是,接下来几行,我看到这段代码:
if FClIEnt.httpClIEnt.Response.CharSet > '' then begin LResponseStream.position := 0; S := FClIEnt.httpClIEnt.ReadStringAsCharset(LResponseStream,FClIEnt.httpClIEnt.Response.CharSet); LResponseStream.Free; LResponseStream := TStringStream.Create(S); end;
根据此块上面的注释,这样做是因为内存流的内容“未根据可能存在的EnCoding或Content-Type Charset参数进行编码”,这被VCL代码的编写者认为是Indy中的错误.
所以基本上,这里发生了什么:原始响应被视为一个字符串并转换为’正确’编码. FClIEnt.httpClIEnt.Response.CharSet是’UTF-8′,它确实是JsON的编码,但不幸的是,这种转换只能在解压缩流之后才能完成,但尚未完成.所以我认为这是一个错误. 总结
以上是内存溢出为你收集整理的delphi – TRestClient / TRestRequest错误地解码gzip响应全部内容,希望文章能够帮你解决delphi – TRestClient / TRestRequest错误地解码gzip响应所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)