HttpClient 헤더를 추가하면 일부 값이 포함 된 FormatException이 생성됩니다.


84

이는 Google 클라우드 메시징에 대한 코딩 컨텍스트 내에서 발생했지만 다른 곳에 적용됩니다.

다음을 고려하세요:

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이 GCN API에 메시지를 게시하려고합니다. 인증 정보를 위에 표시된 형식을 사용하여 헤더로 보내야합니다. 그러나 이것은 HttpClient 헤더에 허용되는 값에 대한보다 일반적인 질문입니다.
Andrew

답변:


179

여전히 관련성이 있는지 확실하지 않지만 최근에 동일한 문제가 발생하여 헤더 정보를 추가하는 다른 메서드를 호출하여 해결할 수있었습니다.

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

2
기본 헤더를하지 않으려면 당신은 또한 HttpRequestMessage이 메서드를 호출 할 수 있습니다
에드 사익스

8
다른 방법이 유효한 값인 경우 유효성 검사에 실패하는 이유를 여전히 이해하지 못하더라도 이것을 대답으로 표시했습니다.
앤드류

1
또한, 10의 HttpClient를 Windows에서 지원하지 않는 것
Sinaesthetic

4
나는 이것이 오래된 스레드라는 것을 알지만 방금이 문제 @EdSykes에 부딪쳐 HttpRequestMessage대신 사용해 보았지만 아무런 차이가 없었습니다. 그 TryAddWithoutValidation방법은 나를 위해 트릭을했습니다.
Matthew Blott

23

"이 모든 것 (파싱 및 유효성 검사)이 필요한 이유"에 대한 대답은 HTTP 표준에 정의되어 있습니다.

에서는 HTTP / 1.1RFC2617 : 값 (예를 들면 WWW 인증 및 허가와 같은) 인증 헤더는 두 부분으로 갖는 스킴 부와 파라미터 부를 .

HTTP 기본 인증의 경우 스키마는 "Basic"이고 매개 변수는 "QWxhZGRpbjpvcGVuIHNlc2FtZQ ==" 와 같을 수 있으므로 전체 헤더는 다음과 같습니다.

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

그래서 "key = XXX"는 스키마 부분이 없기 때문에 유효성 검사를 통과하지 못합니다.


매개 변수 섹션에 키 = 값이있는 것은 유효합니다. stackoverflow.com/a/19512506/55732를 참조하십시오 .
John Kurlak

1
@Kurlak : key = value는 전체 "credentials"부분이 아닌 "auth-param"부분에만 유효합니다. CodeCaster의 해석은 옳지 않습니다.
Terry Chang

3
실제로 Bearer구성표로 사용 하고 있지만 여전히 오류가 표시됩니다.
Tom

1
문제를 일으키는 "Bearer"와 같은 Bearer 뒤에 공백이있었습니다. 아래에서 @Robert Stokes 답변을 보았습니다.
shanti

7

다음과 같은 방법으로 Authorization 헤더를 설정하여이 예외 (값의 쉼표로 인한 내 FormatException)를 해결했습니다.

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

5

이 오류가 발생하여 Authorization 헤더 끝에 공백을 추가했을 때이 게시물을 우연히 발견했습니다.

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

승인 후 문제가되는 ""을 볼 수 있습니다.

오타를보기까지 약 15 분이 걸렸습니다 ...


1

오늘 아침에 편지에 HTTP 사양을 따르지 않는 외부 API를 다루는 동안 몇 가지 질문을 살펴 보았습니다.

내 게시물의 일환으로, 그들은 원하는 Content-TypeContent-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

제 경우에는 byte [] RowVersion SQL 필드에서 ETags 문자열 값을 생성하고 있습니다. 그래서 생성 된 랩을 추가해야합니다. ie AAAAAAAAF5s = string inside "다음과 같이 ...

        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]);                    
        }
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.