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

84

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

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

Ответы:

179

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

var http = new HttpClient();
http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "key=XXX");
Антонио
источник
2
вы также можете вызвать этот метод в HttpRequestMessage, если он вам не нужен в заголовках по умолчанию
Эд Сайкс
8
Отметил это как ответ, хотя я до сих пор не понимаю, почему другой метод не проходит проверку, если это допустимое значение.
Эндрю
1
Кроме того, похоже, не помогает httpclient в Windows 10
Sinaesthetic
4
Я вижу, что это старый поток, но я только что столкнулся с этой проблемой @EdSykes и попытался использовать HttpRequestMessageвместо этого, и это не имело никакого значения. Этот TryAddWithoutValidationметод помог мне.
Мэтью Блотт,
23

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

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

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

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

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

Терри Чанг
источник
Наличие ключа = значение в разделе параметров допустимо. См. Stackoverflow.com/a/19512506/55732 .
Джон Курлак
1
@Kurlak: key = value действительно только для части "auth-param", а не для всей части "учетных данных". Интерпретация CodeCaster не совсем верна.
Терри Чанг
3
На самом деле я использую Bearerэту схему, но она все еще показывает ошибку.
Tom
1
У меня было место после Bearer, например Bearer, которое вызывало проблемы. Я видел ответ @Robert Stokes ниже, который помог мне это понять.
Шанти
7

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

var authenticationHeaderValue = new AuthenticationHeaderValue("some scheme", "some value");
client.DefaultRequestHeaders.Authorization = authenticationHeaderValue;
CRice
источник
5

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

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

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

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

Роберт Стоукс
источник
1

Сегодня утром я задал несколько вопросов, когда имел дело с внешним 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;
}
крилгар
источник
0

В моем случае я генерирую строковые значения ETags из поля SQL byte [] RowVersion. Поэтому мне нужно добавить обертку сгенерированного файла. т.е. 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]);                    
        }
    }
Alhpe
источник