Thêm tiêu đề HttpClient tạo ra một FormatException với một số giá trị


83

Điều này xảy ra trong bối cảnh mã hóa Google Cloud Messaging, nhưng áp dụng ở những nơi khác.

Hãy xem xét những điều sau:

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

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

cả hai đều tạo ra một FormatException:

System.FormatException: Định dạng của value key = XXX 'không hợp lệ.

Giải pháp là loại bỏ dấu bằng.

  1. Đào sâu vào phản xạ cho thấy có vô số mã xác thực và phân tích cú pháp sẽ chạy khi thêm một giá trị tiêu đề mới. Tại sao tất cả những điều này là cần thiết? Khách hàng này không nên tránh xa chúng ta sao?

  2. Làm thế nào để bạn thoát khỏi dấu bằng để thêm giá trị này thành công?


@SamIam đang cố gắng đăng thông báo lên API GCN - yêu cầu gửi thông tin xác thực dưới dạng tiêu đề bằng định dạng hiển thị ở trên. Tuy nhiên, đây là một câu hỏi chung chung hơn xoay quanh các giá trị được phép cho tiêu đề HttpClient.
Andrew

Câu trả lời:


176

Không chắc liệu có còn liên quan hay không, nhưng gần đây tôi đã gặp phải vấn đề tương tự này và có thể giải quyết nó bằng cách gọi một phương thức khác để thêm thông tin tiêu đề:

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

2
bạn cũng có thể gọi phương pháp này trên HttpRequestMessage nếu bạn không muốn nó trong các tiêu đề mặc định
Ed Sykes

8
Đã đánh dấu đây là câu trả lời, mặc dù tôi vẫn không hiểu tại sao phương pháp khác không thành công khi xác thực nếu đó là một giá trị hợp lệ.
Andrew

1
Ngoài ra, dường như không giúp đỡ trong Windows 10 của httpclient
Sinaesthetic

4
Tôi thấy đây là một chủ đề cũ nhưng tôi vừa gặp phải vấn đề này @EdSykes và đã thử sử dụng HttpRequestMessagethay thế và nó không có gì khác biệt. Các TryAddWithoutValidationphương pháp làm các trick cho tôi.
Matthew Blott,

23

Đối với câu hỏi "tại sao tất cả những điều này (phân tích cú pháp và xác thực) lại cần thiết", câu trả lời là: nó được định nghĩa trong tiêu chuẩn HTTP.

Trong HTTP / 1.1RFC2617 , giá trị mà một tiêu đề xác thực (chẳng hạn như WWW-Authenticate và Authorization) có hai phần: một phần lược đồ và một phần tham số .

Đối với Xác thực cơ bản HTTP, lược đồ là "Cơ bản" và tham số có thể giống như "QWxhZGRpbjpvcGVuIHNlc2FtZQ ==" , vì vậy toàn bộ tiêu đề trở thành:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Đó là lý do tại sao "key = XXX" của bạn không vượt qua được xác thực, vì nó thiếu phần lược đồ.


Có key = value trong phần tham số là hợp lệ. Xem stackoverflow.com/a/19512506/55732 .
John Kurlak

1
@Kurlak: key = value chỉ hợp lệ cho phần "auth-param", không hợp lệ cho toàn bộ phần "thông tin xác thực". Giải thích của CodeCaster không hoàn toàn đúng.
Terry Chang

3
Tôi thực sự đang sử dụng Bearerdưới dạng lược đồ, nhưng nó vẫn hiển thị cho tôi lỗi.
Tom,

1
Tôi có một khoảng trắng sau Bearer như "Bearer" đang gây ra sự cố. Tôi thấy câu trả lời của @Robert Stokes bên dưới đã giúp tôi xem được.
shanti

7

Tôi đã giải quyết được ngoại lệ này (FormatException của tôi gây ra bởi dấu phẩy trong giá trị) bằng cách đặt tiêu đề Ủy quyền theo cách sau:

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

4

Tôi đã gặp phải lỗi này và tình cờ gặp phải bài đăng này khi tôi thêm khoảng trắng vào cuối tiêu đề Ủy quyền.

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

Bạn có thể thấy "" vi phạm sau khi Ủy quyền.

Tôi mất khoảng 15 phút trước khi tôi thấy lỗi đánh máy của mình


1

Tôi đã trả lời một số câu hỏi sáng nay khi xử lý một API bên ngoài không tuân theo thông số HTTP cho thư.

Là một phần của bài đăng của tôi, họ muốn Content-TypeContent-Dispositionkhông thể được thêm vào HttpClientđối tượng. Để thêm các tiêu đề đó, bạn cần tạo một HttpRequestMessage . Trên đó, bạn cần thêm tiêu đề vào thuộc Contenttính.

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

Trong trường hợp của tôi, tôi đang tạo các giá trị chuỗi ETags từ một trường SQL [] RowVersion SQL. Vì vậy, tôi cần thêm bọc được tạo. tức là AAAAAAAAF5s = string bên trong "như sau ...

        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]);                    
        }
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.