Dodanie nagłówków HttpClient generuje FormatException z niektórymi wartościami

84

Stało się to w kontekście kodowania w Google Cloud Messaging, ale ma zastosowanie w innych miejscach.

Rozważ następujące:

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

i

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

z których oba generują FormatException:

System.FormatException: format klucza wartości = XXX 'jest nieprawidłowy.

Rozwiązaniem jest usunięcie znaku równości.

  1. Przeglądanie reflektora pokazuje, że jest mnóstwo kodu sprawdzającego i analizującego, który działa podczas dodawania nowej wartości nagłówka. Dlaczego to wszystko jest konieczne? Czy ten klient nie powinien po prostu schodzić nam z drogi?

  2. Jak uniknąć znaku równości, aby dodać tę wartość?

Andrzej
źródło
@SamIam próbuje wysłać wiadomość do interfejsu API GCN - co wymaga przesłania informacji o uwierzytelnianiu jako nagłówka przy użyciu formatu pokazanego powyżej. Jest to jednak bardziej ogólne pytanie dotyczące dozwolonych wartości nagłówków HttpClient.
Andrew

Odpowiedzi:

179

Nie jestem pewien, czy nadal jest to istotne, ale ostatnio napotkałem ten sam problem i udało mi się go rozwiązać, wywołując inną metodę dodawania informacji z nagłówka:

var http = new HttpClient();
http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "key=XXX");
Antonio
źródło
2
możesz również wywołać tę metodę w HttpRequestMessage, jeśli nie chcesz jej w domyślnych nagłówkach
Ed Sykes
8
Oznaczono to jako odpowiedź, mimo że nadal nie rozumiem, dlaczego druga metoda zawodzi podczas walidacji, jeśli jest to prawidłowa wartość.
Andrew,
1
Wydaje się również, że nie pomaga w httpclient systemu Windows 10
Sinaesthetic
4
Widzę, że to stary wątek, ale właśnie natknąłem się na ten problem @EdSykes i próbowałem go użyć, HttpRequestMessageale nie miało to znaczenia. TryAddWithoutValidationMetoda wystarczyły dla mnie.
Matthew Blott
23

Na Twoje pytanie „dlaczego to wszystko (analiza i walidacja) jest konieczne”? Odpowiedź brzmi: jest to zdefiniowane w standardzie HTTP.

W protokołach HTTP / 1.1 i RFC2617 wartość nagłówka uwierzytelniania (na przykład WWW-Authenticate i Authorization) ma dwie części: część schematu i część dotyczącą parametrów .

W przypadku podstawowego uwierzytelniania HTTP schemat to „Podstawowy”, a parametr może wyglądać mniej więcej tak: „QWxhZGRpbjpvcGVuIHNlc2FtZQ ==” , więc cały nagłówek wygląda następująco :

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Dlatego twój „key = XXX” nie przechodzi weryfikacji, ponieważ brakuje mu części schematu.

Terry Chang
źródło
Posiadanie klucza = wartość w sekcji parametrów jest poprawne. Zobacz stackoverflow.com/a/19512506/55732 .
John Kurlak,
1
@Kurlak: klucz = wartość jest ważny tylko dla części „auth-param”, a nie dla całej części „credentials”. Interpretacja CodeCaster nie jest do końca poprawna.
Terry Chang
3
Właściwie używam Bearerschematu, ale nadal pokazuje mi błąd.
Tom
1
Miałem spację po Bearer, na przykład „Bearer”, która powodowała problemy. Widziałem odpowiedź @Robert Stokes poniżej, która pomogła mi ją zobaczyć.
shanti
7

Obejrzałem ten wyjątek (mój FormatException spowodowany przecinkami w wartości), ustawiając nagłówek Authorization w następujący sposób:

var authenticationHeaderValue = new AuthenticationHeaderValue("some scheme", "some value");
client.DefaultRequestHeaders.Authorization = authenticationHeaderValue;
CRice
źródło
5

Napotkałem ten błąd i natknąłem się na ten post, gdy dodałem spację na końcu nagłówka autoryzacji.

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

Po autoryzacji możesz zobaczyć obraźliwy plik „”.

Zajęło mi około 15 minut, zanim zobaczyłem swoją literówkę ...

Robert Stokes
źródło
1

Dziś rano przeszedłem przez kilka pytań, mając do czynienia z zewnętrznym interfejsem API, który nie jest zgodny ze specyfikacją HTTP co do joty.

W ramach mojego postu chcą Content-Typei Content-Disposition, których nie można dodać do HttpClientobiektu. Aby dodać te nagłówki, musisz utworzyć HttpRequestMessage . Tam musisz dodać nagłówki do Contentwłaściwości.

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;
}
krillgar
źródło
0

W moim przypadku generuję wartości ciągu ETags z pola SQL RowVersion bajt []. Więc muszę dodać zawinąć wygenerowany plik. tj. AAAAAAAAF5s = string wewnątrz "w następujący sposób ...

        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
źródło