HttpClient / HttpRequestMessage 在标头中添加空格

vai*_*boy 5 c# httpclient .net-core

我刚刚进入 .net core,因为它为 HttpClient 提供了功能(例如设置 keep-alive 标头上限)。 我正在使用 2.1 网络核心和 C# 7.3

我的问题

我的问题特别是关于设置“Accept”和“Accept-Language”标头。我试图访问的网站按原样解析这两个标头,这意味着它必须具有相同的精确格式(包括空格)。

使用 fiddler (和其他一些工具)来获取我的请求。

  1. 我捕获的“Accept”标头如下:(格式不正确)
text/html, application/xhtml+xml, application/xml; q=0.9, image/webp, image/apng, */*; q=0.8, application/signed-exchange; v=b3
Run Code Online (Sandbox Code Playgroud)

而不是:(正确的格式)

text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Run Code Online (Sandbox Code Playgroud)
  1. “Accept-Language”标头如下:(格式不正确)
en-US, en; q=0.9, ar; q=0.8, und; q=0.7
Run Code Online (Sandbox Code Playgroud)

而不是:(正确格式)

en-US,en;q=0.9,ar;q=0.8,und;q=0.7
Run Code Online (Sandbox Code Playgroud)

我正在 HttpRequestMessage 的帮助下使用 HttpClient 模拟 GET 请求。

我尝试过的

  1. 尝试了在 HttpClient 实例中设置我的标头并使用它自己的标头触发 HttpRequestMessage,但都不起作用。
  2. 网上找了很多解决方案都没有效果,包括这个
  3. 将标头拆分为多个.Headers.TryAddWithoutValidation
  4. 也尝试过 HttpWebRequests。没有运气。需要注意的一件事是,由于我的项目,我也喜欢坚持使用 HttpClient。

你会在下面找到我当前的代码

var client = new HttpClient(new HttpClientHandler() { UseCookies = false,
            AllowAutoRedirect = false,
            Proxy = new WebProxy("localhost:8888") });

var httpReq = new HttpRequestMessage(HttpMethod.Get, $"myurl");


            httpReq.Headers.TryAddWithoutValidation("Host", "myurl");
            httpReq.Headers.TryAddWithoutValidation("Connection", "keep-alive");
            httpReq.Headers.TryAddWithoutValidation("Cookie", $"cookie");
            httpReq.Headers.TryAddWithoutValidation("Upgrade-Insecure-Requests", "1");
            httpReq.Headers.TryAddWithoutValidation("User-Agent", Data.user_agent);
            httpReq.Headers.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate, br");
            httpReq.Headers.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3");
            httpReq.Headers.TryAddWithoutValidation("Referer", Data.homeUrl);
            httpReq.Headers.TryAddWithoutValidation("Accept-Language", "en-US,en;q=0.9,ar;q=0.8,und;q=0.7");

            req = await client.SendAsync(httpReq);
Run Code Online (Sandbox Code Playgroud)

如前所述,所有其他标头都工作正常。只是Accept和Accept-Language这两个输入方式不同。

JOS*_*Ftw 3

看起来它是硬编码在 corefx 中的,看这里:

destination.Append(' ');
Run Code Online (Sandbox Code Playgroud)

完整方法:

internal static void ToString(ObjectCollection<NameValueHeaderValue> values, char separator, bool leadingSeparator,
            StringBuilder destination)
        {
            Debug.Assert(destination != null);

            if ((values == null) || (values.Count == 0))
            {
                return;
            }

            foreach (var value in values)
            {
                if (leadingSeparator || (destination.Length > 0))
                {
                    destination.Append(separator);
                    destination.Append(' ');
                }
                value.AddToStringBuilder(destination);
            }
        }
Run Code Online (Sandbox Code Playgroud)

https://github.com/dotnet/corefx/blob/a10890f4ffe0fadf090c922578ba0e606ebdd16c/src/System.Net.Http/src/System/Net/Http/Headers/NameValueHeaderValue.cs#L183

我不知道如何覆盖它,但也许你可以在 GitHub 上创建一个新问题?

编辑:发现与此相关的问题并解决它:https ://github.com/dotnet/corefx/issues/18449