HttpClient / HttpRequestMessage会在头部添加空格

5

我最近开始学习.NET Core,因为它提供了一些HttpClient的特性(例如设置keep-alive标头上限)。

我正在使用2.1 net core和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

代替:

(正确格式)

text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

"Accept-Language" 头部应该如下所示:(格式不正确)
en-US, en; q=0.9, ar; q=0.8, und; q=0.7

而不是:(正确格式)

en-US,en;q=0.9,ar;q=0.8,und;q=0.7

我正在使用HttpRequestMessage和HttpClient模拟GET请求。

我尝试过的方法:

  1. 尝试在HttpClient实例中设置我的标头,并使用自己的标头触发HttpRequestMessage,但都没有起作用。
  2. 尝试了许多在线解决方案,包括this,但都没有起作用。
  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);

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

1
你尝试过逐个添加头部吗?可以使用 httpReq.Headers.AcceptLanguage.Add("en-US"); 等方式。 - spodger
@spodger,是的。我也尝试过了。它不应该影响我的输入,因为它只涉及标题名称而不是值? - vaiperboy
2
请不要“顶”问题。 - Liam
1
尝试在Postman中生成请求,生成C#代码并将其与您的代码进行比较。 - mr5
@mr5 当使用Postman生成的C#代码(使用RestClient)时,输出相同的结果,并在标头中添加空格。 - vaiperboy
1个回答

3
似乎这是在corefx中硬编码的,看这里:
destination.Append(' ');

完整方法:

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);
            }
        }

这里是相关的代码,它与IT技术有关。

我不知道如何覆盖此内容,但您可以在GitHub上创建一个新问题吗?

编辑:发现了一个相关的问题并提出了issue18449


1
似乎添加分隔符的人可能是从RFC7231#section-5.3中提供的示例中提取的。尽管在5.3中没有提到空格处理,但在其他部分中明确给出了空格的处理方式,并且当提到它时,它提供了指导,说明何时提供的空格将被接收者视为无效或忽略。当主要接收者不是人类时,应避免不必要的空格,因此建议更改分隔符以匹配基本约定。 - K. Alan Bates
@K.AlanBates 我在 GitHub 上找到了一个讨论此问题的链接:https://github.com/dotnet/corefx/issues/18449 - JOSEFtw
感谢您指出问题报告已经提交(好在我不是唯一一个?)。我会尝试直接向微软报告此问题。@JOSEFtw - vaiperboy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接