如何在 Flurl HttpClient 中保留 headers

How to preserve headers in the Flurl HttpClient

我在 .NET Http 客户端上使用 Furl.Http 包装器。对于每个请求,我的 API 都需要发送 User-Agent 和授权 header。

我想设置一次,而不是每次都要声明。

我认为我可以做的是创建一个 FlurlClient 实例并在其上设置 headers,然后在每个请求之前设置 ResetToRoot,如这段代码示例所示:

    var fc = new FlurlClient();
    fc.WithHeader("User-Agent", "Keep/1.0");
    var tokenModel = await
        "https://app.tempuri.com".AppendPathSegment("auth")
        .WithClient(fc)
        .PostUrlEncodedAsync(new { username = "you", password = "secret"})
        .ReceiveJson<TokenModel>();

    fc.WithHeader("Authorization",
         string.Format("Token {0}",tokenModel.Token));                  

fc.Url.ResetToRoot();
    var userModel = await fc.Url
                          .AppendPathSegment("auth").GetJsonAsync<UserModel>();
    Console.WriteLine(userModel.Username);

然而,在 RestToRoot() 之后,header 似乎不再发送。

这是设计使然吗?是否有更好的方法来确保这些 header 被发送到每个请求?

问题是倒数第二行。

fc.Url...GetJsonAsync

FlurlClient 有一个对 Url 对象的引用,但反之则不然,所以当你调用 fc.Url 时,你实际上已经丢失了那个引用和一个新的FlurlClient 是在您调用 GetJsonAsync 时在幕后创建的。这是设计使然 Flurl.Url 是核心 Flurl 库中的一个简单构建器 class,可以独立于 Flurl.Http.

使用

这是我的做法:

var url = "https://app.tempuri.com";

using (var fc = new FlurlClient().WithHeader("User-Agent", "Keep/1.0")) {
    var tokenModel = await url
        .AppendPathSegment("...")
        .WithClient(fc)
        .PostUrlEncodedAsync(new { username = "you", password = "secret"})
        .ReceiveJson<TokenModel>();

    fc.WithHeader("Authorization",
        string.Format("Token {0}",tokenModel.Token));                  

    var userModel = await url
        .AppendPathSegment("...")
        .WithClient(fc)
        .GetJsonAsync<UserModel>();

    Console.WriteLine(userModel.Username);
}

几个注意事项:

  1. 请注意,您在每个 HTTP 调用中附加 FlurlClient
  2. 这里的url变量只是一个字符串,所以不需要调用ResetToRoot.
  3. using 声明在这里不是绝对必需的,但这是一个很好的做法。

还有一种替代方法也可以。对于每个连续的 HTTP 调用,首先修改 fc.Url,然后使用 fc 进行调用:

fc.Url.ResetToRoot().AppendPathSegment(...);
var x = await fc.GetJsonAsync<T>();

在这种情况下,您需要调用 ResetToRoot 而不是 WithClient。 fluent 链在这里被打破了,但你可能会发现它更具可读性。哪种方式都行,只是个人喜好问题。