Добавление заголовков HttpClient генерирует исключение FormatException с некоторыми значениями.

Это произошло в контексте кодирования для Google Cloud Messaging, но применимо и в других местах.

Рассмотрим следующее:

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. Как избежать знака равенства, чтобы добавление этого значения прошло успешно?


person Andrew    schedule 02.11.2012    source источник
comment
@SamIam пытается опубликовать сообщение в GCN API, для чего требуется, чтобы информация для аутентификации была отправлена ​​​​в виде заголовка с использованием формата, показанного выше. Однако это более общий вопрос о разрешенных значениях заголовков HttpClient.   -  person Andrew    schedule 02.11.2012


Ответы (6)


Не уверен, что все еще актуален, но недавно я столкнулся с этой же проблемой и смог решить ее, вызвав другой метод для добавления информации заголовка:

var http = new HttpClient();
http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "key=XXX");
person Antonio    schedule 06.03.2013
comment
вы также можете вызвать этот метод в HttpRequestMessage, если вы не хотите, чтобы он был в заголовках по умолчанию. - person Ed Sykes; 27.01.2014
comment
Пометил это как ответ, хотя я до сих пор не понимаю, почему другой метод не проходит проверку, если это действительное значение. - person Andrew; 30.09.2014
comment
Кроме того, похоже, не помогает httpclient в Windows 10. - person Sinaesthetic; 23.08.2015
comment
Я вижу, что это старая ветка, но я только что столкнулся с этой проблемой @EdSykes и попытался вместо этого использовать HttpRequestMessage, и это не имело никакого значения. Метод TryAddWithoutValidation помог мне. - person Matthew Blott; 31.08.2016

На ваш вопрос «зачем все это (анализ и проверка) необходимо» ответ таков: это определено в стандарте HTTP.

В HTTP/1.1 и RFC2617 значение заголовка аутентификации (например, WWW-Authenticate и Authorization) состоит из двух частей: часть схемы и часть параметра. .

Для базовой HTTP-аутентификации используется схема «Базовая», а параметр может выглядеть примерно так: "QWxhZGRpbjpvcGVuIHNlc2FtZQ==", поэтому весь заголовок принимает следующий вид:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Вот почему ваш «ключ = XXX» не проходит проверку, потому что в нем отсутствует часть схемы.

person Terry Chang    schedule 12.04.2015
comment
Ключ = значение в разделе параметров допустим. См. stackoverflow.com/a/19512506/55732. - person John Kurlak; 03.02.2016
comment
@Kurlak: key=value действителен только для части auth-param, а не для всей части учетных данных. Интерпретация CodeCaster не совсем верна. - person Terry Chang; 04.02.2016
comment
На самом деле я использую Bearer как схему, но она все еще показывает мне ошибку. - person Tom; 08.07.2018
comment
У меня был пробел после Bearer, например Bearer, который вызывал проблемы. Я видел ответ @Robert Stokes ниже, который помог мне это увидеть. - person shanti; 08.05.2019

Я обошел это исключение (мое исключение FormatException, вызванное запятыми в значении), установив заголовок авторизации следующим образом:

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

Я столкнулся с этой ошибкой и наткнулся на этот пост, когда добавил пробел в конец заголовка авторизации.

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

Вы можете увидеть оскорбительный " " после Авторизации.

Мне потребовалось около 15 минут, прежде чем я увидел свою опечатку...

person Robert Stokes    schedule 12.03.2019

Этим утром я задавал несколько вопросов, имея дело с внешним API, который не соответствует спецификации HTTP буквально.

В рамках моего сообщения им нужны Content-Type и Content-Disposition, которые нельзя добавить к объекту HttpClient. Чтобы добавить эти заголовки, вам нужно создать HttpRequestMessage. Там вам нужно добавить заголовки к свойству Content.

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;
}
person krillgar    schedule 11.07.2017

В моем случае я генерирую строковые значения ETags из поля byte[] RowVersion SQL. Поэтому мне нужно добавить обертку сгенерированного. то есть AAAAAAAAF5s= строка внутри " следующим образом...

        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]);                    
        }
    }
person alhpe    schedule 17.09.2018