Добавление заголовков 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: формат значения ключ =XXX'недопустим.

Решение состоит в том, чтобы удалить знак равенства.

  1. Копание в отражатель показывает, что существует множество кодов проверки и анализа, которые запускаются при добавлении нового значения заголовка. Зачем все это нужно? Разве этот клиент не должен просто уйти с нашего пути?

  2. Как вы избегаете знака равенства, чтобы добавить это значение успешно?

5 ответов

Решение

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

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

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

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

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

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

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

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

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

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

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

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

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

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

В моем случае я генерирую строковые значения 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]);                    
        }
    }
Другие вопросы по тегам