当设置逗号时,System.Net.Http.HttpClient实例会抛出异常。为什么?

3

假设以下的 System.Net.Http.HttpClient 可移植类库 抛出了一个异常:

var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Authorization", "aaaa,bbbb");

异常类型是:无效格式

在 System.Net.Http.Headers.HttpHeaders.AddInternal (System.String name, IEnumerable1 values, System.Net.Http.Headers.HeaderInfo headerInfo, Boolean ignoreInvalid) [0x0004c] in /Developer/MonoTouch/Source/mono/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs:195 at System.Net.Http.Headers.HttpHeaders.Add (System.String name, IEnumerable1 values) [0x00011] in /Developer/MonoTouch/Source/mono/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders.cs:170 at System.Net.Http.Headers.HttpHeaders.Add (System.String name, System.String value) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System.Net.Http/System.Net.Http.Headers/HttpHeaders < ... 省略 ...>

现在只会在以下情况下发生:

标头键 = Authorization。如果将其更改为其他内容,则没有问题。 值 = 必须包含逗号。

现在,这个先前的 SO 问题表明,在标头中使用逗号是正确的方式来粘贴多个值。

有人能解释一下发生了什么吗?

注意:这是在 Xamarin 上,所以我猜它是 mono。不确定是否重要。

更新:

这是一个图片。

enter image description here


1
那是堆栈跟踪,异常是什么? - CodeCaster
更新了。哎呀,不好意思。 - Pure.Krome
异常说明它是一个无效的格式。你为什么要在那个标题中设置逗号? - CodeCaster
@CodeCaster 因为我想这么做,并且相信/曾经相信这是有效的。 - Pure.Krome
2个回答

5
根据此链接规范rfc2617, 用逗号分隔似乎是有效的。
“它使用可扩展的、不区分大小写的令牌来标识身份验证方案,后跟由逗号分隔的属性-值对列表,这些属性-值对携带实现该方案所需的参数。”
但其中建议您很可能设置不正确,它们必须采用“属性-值对”的形式:
auth-param     = token "=" ( token | quoted-string )

你具体是如何设置它们的?

httpClient.DefaultRequestHeaders.Add("Authorization", "aaaa,bbbb");

上述内容似乎无效,它们不是属性对“aaaa,bbbb”。您尝试设置的任何属性都没有等号。请尝试以下内容作为测试:
httpClient.DefaultRequestHeaders.Add("Authorization", "aaaa=1234,bbbb=45678");

但我想为授权字段设置的值是“aaa,bbb”而不是键/值结果。然后,在我的服务器上,我通过逗号拆分该,并假定第一个段是Foo,第二个段是Bah。 - Pure.Krome
嗯,你不能这样做,你得想出其他办法。也许你可以对该值进行Base64编码。 - CodeCaster
这仅适用于AUTHORIZATION标头吗?还是适用于任何标头? - Pure.Krome
@Pure.Krome auth参数可以是名称/值对,也可以是token68值,其中逗号不是有效字符。请参见此处http://tools.ietf.org/html/draft-ietf-httpbis-p7-auth-26#section-2.1 - Darrel Miller
@PaulZahra 草案已获批准发布,并将很快成为RFC。http://tools.ietf.org/wg/httpbis/trac/wiki - Darrel Miller
显示剩余2条评论

2

mono实现中存在一个bug,不允许在标题中使用有效字符,即[]。这个问题已经得到解决,但对于Xamarin Android,它尚未达到稳定分支(它将随着Xamarin Android 5一起发布)。

如果您无法等待,需要立即发货,并且标题中必须包含特殊字符,则有一种方法可以绕过此问题(我现在声明不负责任)。

在添加标题之前,您可以将这些字符作为允许标记添加到标题中。这是未记录的、非法的(从适当编码的角度来看)并通过反射完成,但它可以工作:

var assembly = typeof(System.Net.Http.Headers.HttpContentHeaders).Assembly;
var lexer = assembly.GetType("System.Net.Http.Headers.Lexer");
var field = lexer.GetField("token_chars", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
var tokens = ( bool[])field.GetValue(null);
tokens[91] = true;
tokens[93] = true;
field.SetValue(null, tokens);

在上面的示例中,我们允许字符91和93 [和] 分别出现。

请注意,在更新的Android上,具有更新的Mono(版本5)以上代码将失败。它不再需要。如果您确实需要支持旧的Mono框架,请在使用答案之前进行版本>5的测试。 - Peter

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