添加 HttpClient 头将生成带有一些值的 FormatException

这发生在对 Google云消息传递进行编码的情况下,但适用于其他领域。

考虑以下几点:

var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("key=XXX");

还有

var http = new HttpClient();
http.DefaultRequestHeaders.Add("Authorization", "key=XXX");

它们都会生成一个 FormatException:

System.FormatException: 值 key = XXX’的格式无效。

解决方案是去掉等号。

  1. 深入研究反射器可以发现,在添加新的头部值时,会运行大量的验证和解析代码。为什么要这样?这个客户不应该给我们让路吗?

  2. 如何转义等号以使该值的加法成功?

71052 次浏览

Not sure if still relevant, but I recently ran into this same issue and was able to solve it by calling a different method to add the header information:

var http = new HttpClient();
http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "key=XXX");

To your "why is all this (parsing and validation) necessary" question, the answer is: it is defined in the HTTP standard.

In HTTP/1.1 and RFC2617, the value an authentication header (such as WWW-Authenticate and Authorization) has two parts: a scheme part, and a parameter part.

For HTTP Basic Authentication, the scheme is "Basic", and the parameter may be something like "QWxhZGRpbjpvcGVuIHNlc2FtZQ==", so the whole header becomes:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

That's why your "key=XXX" doesn't pass validation, because it lacks a scheme part.

I got around this exception (my FormatException caused by commas in the value) by setting the Authorization header in the following way:

var authenticationHeaderValue = new AuthenticationHeaderValue("some scheme", "some value");
client.DefaultRequestHeaders.Authorization = authenticationHeaderValue;

I've been going through a few questions this morning while dealing with an external API that doesn't follow the HTTP spec to the letter.

As part of my posting, they want the Content-Type and Content-Disposition, which cannot be added to the HttpClient object. To add those headers, you need to create an HttpRequestMessage. On there, you need to add the headers to the Content property.

private HttpRequestMessage GetPostMessage(string uri, string contentType,
string fileName, Stream content)
{
var request = new HttpRequestMessage
{
Content = new StreamContent(content),
RequestUri = new Uri(uri),
Method = HttpMethod.Post
};


// contentType = "video/mp4"
request.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);


//Need TryAddWithoutValidation because of the equals sign in the value.
request.Content
.Headers
.TryAddWithoutValidation("Content-Disposition",
$"attachment; filename=\"{Path.GetFileName(fileName)}\"");


// If there is no equals sign in your content disposition, this will work:
// request.Content.Headers.ContentDisposition =
//    new ContentDispositionHeaderValue($"attachment; \"{Path.GetFileName(fileName)}\"");


return request;
}

In my case I am generating ETags string values from a byte[] RowVersion SQL field. So I need to add wrap the generated. i.e. AAAAAAAAF5s= string inside " as follows...

        var eTag = department.RowVersion.ToETagString();


httpClient.DefaultRequestHeaders.Add(Microsoft.Net.Http.Headers.HeaderNames.IfMatch, $"\"{eTag}\"")




public class DepartmentForHandleDto
{
public string Name { get; set; }
public string GroupName { get; set; }
public byte[] RowVersion { get; set; }
}


public static class ByteArrayExtensions
{
public static string ToETagString(this byte[] byteArray)
{
return Convert.ToBase64String(byteArray != null && byteArray.Length > 0 ? byteArray : new byte[8]);
}
}

I ran into this error and stumbled on to this post when I added a space to the end of an Authorization header.

this.bearerAuthHttpClient.DefaultRequestHeaders.Add("Authorization ", $"Bearer {token}");

You can see the offending " " after Authorization.

It took me about 15 min before I saw my typo...