【问题标题】:"Unexpected character exception" when making GET request to StackExchange API using Flurl使用 Flurl 向 StackExchange API 发出 GET 请求时出现“意外字符异常”
【发布时间】:2019-09-18 17:58:58
【问题描述】:

我创建了一个控制台应用程序,在其中我向 Stack Exchange API 发出一个简单的 GET 请求以获取一些 cmets。我正在使用Flurl。这个方法是从Main调用的

private static async Task GetComments()
{
    dynamic d = await "https://api.stackexchange.com/2.2/comments?page=1&pagesize=5&order=desc&min=1513468800&max=1513555200&sort=creation&site=stackoverflow"
                        .GetJsonAsync();
}

但是,我得到了这个错误:

{"解析值时遇到意外字符:\u001f.Path '', line 0, position 0."}

我试过这样设置标题,但没有成功。

dynamic d = await new Url("https://api.stackexchange.com/2.2/comments.....")
               .WithHeader("Content-Encoding", "gzip")
               .WithHeader("Accept-Encoding", "gzip")
               .GetJsonAsync();

当我open it in the browser时,URL 确实返回了正确的 JSON

【问题讨论】:

  • 可能 flurl 没有浏览器那么宽容,需要去掉 url 中多余的斜杠。
  • @Crowcoder 删除它并尝试。没用:(
  • Flurl 能处理 gzip 吗?
  • 无论您是否请求,API 结果都会被压缩。你需要在调用GetJsonAsync之类的东西之前解压它。
  • @ikegami,SE API 不会接受这样的请求。除非你请求 deflate,否则你会得到 gzip。这些是您使用 SE API 的唯一选择。

标签: c# stackexchange-api flurl


【解决方案1】:

所以看起来 Flurl 不支持开箱即用的 Gzip,要让它工作需要一些按摩。首先你需要一个自定义的 Http Client 工厂:

public class GzipClientFactory : Flurl.Http.Configuration.IHttpClientFactory
{
    public HttpMessageHandler CreateMessageHandler() => new HttpClientHandler()
    {
        AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
    };

    public HttpClient CreateHttpClient(HttpMessageHandler handler) => 
        new HttpClient(handler);
}

现在配置 Flurl 以使用它:

FlurlHttp.Configure(settings => {
    settings.HttpClientFactory = new GzipClientFactory();
});

现在将支持 Gzip 压缩:

dynamic d = await new Url("https://api.stackexchange.com/2.2/comments.....")
               .GetJsonAsync();

【讨论】:

  • 我建议的一点改变是从DefaultHttpClientFactory 继承,并且只覆盖CreateMessageHandler。它会削减一点实现。
  • 从最新版本开始,它现在支持开箱即用。
【解决方案2】:

更新: Flurl.Http 现在默认支持自动解压,所以只需upgrade 就可以避免这一切。


这是一个类似于已接受答案的选项,除了它适用于对api.stackexchange.com 的调用,它或多或少是单行的。启动时调用一次:

FlurlHttp.ConfigureClient("https://api.github.com", cli => 
    ((HttpClientHandler)cli.HttpMessageHandler).AutomaticDecompression =
        DecompressionMethods.GZip | DecompressionMethods.Deflate);

附带说明,Flurl 的默认值与 HttpClient 的默认值在自动解压方面完全相同。评论中有 GZIP 与 HttpClient 一起使用的注释,这让我摸不着头脑,但似乎 HttpClient 有 differences 取决于平台/版本。为了让事情变得更容易和更可预测,我正在考虑在 Flurl 中默认支持 GZIP/DEFLATE,但我首先需要了解性能等方面的含义。

【讨论】:

  • 好的,我也试试这个。 this question 中的答案为HttpWebRequestHttpClient 明确设置DecompressionMethods。但同样,问题是 3 岁。
  • HttpWebRequestHttpClient 的前身(实际上)。 Flurl 在后台使用HttpClient,此代码实际上与您链接到的问题中的HttpClient 答案相同 - 在HttpClientHandler 上设置解压缩方法。
【解决方案3】:

Flurl.Http 2.2 只是 released,现在它将是 automatically decompress GZIP and DEFLATE by default。所以,新的最佳答案是:升级。 :)

【讨论】:

  • 现在可以演示它是如何工作的吗?我认为这对未来的读者会有帮助。
  • 几乎没有什么可证明的。 OP 的第一个代码示例将按原样工作。没有错误,无需配置。
【解决方案4】:

这是 2019 年,我找不到合适的库供 dotnet 使用 API。所以我自己创造了一个。还有很长的路要走。我计划尽可能地维护它。它已将其发布为 nuget,您可以在Github 上查看源代码

来自 Nuget

Install-Package StackExchange.NET -Version 1.1.0

【讨论】:

    猜你喜欢
    • 2015-06-11
    • 2018-03-10
    • 2017-07-17
    • 2020-12-31
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 2018-04-12
    • 2022-10-06
    相关资源
    最近更新 更多