通用应用 HttpClient header:如何禁用某些 header?

Universal app HttpClient header: how to disable some of the headers?

一些背景知识: 我正在尝试将 "port" 一个 android 应用程序 Windows Phone 调用 non-open 网络 API。由于 API 未打开或记录,我使用了 Fiddler,运行 应用程序的 android 版本,并监听了它发出的 API 调用。

我使用 Windows.Web.Http.HttpClient 作为 class 的选择,因为看起来这将是 class 而不是 System.Net.Http.HttpClient。

这是我用来生成 HTTP POST 请求的 C# 代码摘录:

HttpBaseProtocolFilter _httpFilter = new HttpBaseProtocolFilter();
HttpClient _httpClient = new HttpClient(_httpFilter);                    
_httpClient.DefaultRequestHeaders.AcceptEncoding.Clear();
_httpClient.DefaultRequestHeaders.Accept.TryParseAdd("application/xml");
_httpClient.DefaultRequestHeaders.AcceptLanguage.TryParseAdd("en");            
_httpClient.DefaultRequestHeaders.Connection.TryParseAdd("Keep-Alive");
_httpClient.DefaultRequestHeaders.Add("message-version", "1");
_httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("Android|SAMSUNG-  SGH-I337|3.3.1"); 
_httpClient.DefaultRequestHeaders.Cookie.TryParseAdd(cookie); //Some cookie values                                

Uri uri = new Uri(SOMEURI);
XDocument xd = new XDocument(STUFF_TO_BUILD_XML);
string xd_str = string.Concat(xd.Declaration.ToString(), xd.ToString());
xd_str = xd_str.Replace("\r\n", string.Empty);
xd_str = xd_str.Replace("  ", string.Empty); 
HttpRequestMessage req_msg = new HttpRequestMessage(HttpMethod.Post, uri);
HttpStringContent strcnt = new HttpStringContent(xd_str);            
req_msg.Content = strcnt;
req_msg.Content.Headers.ContentType = new     Windows.Web.Http.Headers.HttpMediaTypeHeaderValue("text/xml; charset=UTF-8");
req_msg.Headers.Host = new Windows.Networking.HostName(SOMEHOSTNAME);

HttpResponseMessage rsp_msg = await _httpClient.SendRequestAsync(req_msg);

这是 Fiddler 在使用我的代码进行 API 调用时看到的原始文本:

POST <HTTPS endpoint> HTTP/1.1
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Host: <hostname>
Cookie2: Version=1
Accept: application/xml
message-version: 1
User-Agent: Android|SAMSUNG-SGH-I337|3.3.1
Accept-Language: en
Content-Length: 173
Content-Type: text/xml; charset=UTF-8
Cache-Control: no-cache
Cookie: STR1=VAL1; STR2=VAL2

<MESSAGE_IN_XML>

--Response--
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
Date: Fri, 03 Apr 2015 01:18:07 GMT

0

这是 Fiddler 在通过 Android 应用发出请求时看到的原始文本:

POST <HTTPS endpoint> HTTP/1.1
Content-Type: text/xml; charset=UTF-8
Connection: Keep-Alive
accept: application/xml
user-agent: Android|SAMSUNG-SGH-I337|3.4
message-version: 1
Accept-Language: en
Content-Length: 173
Host: <hostname>
Cookie: STR1=VAL1; STR2=VAL2
Cookie2: $Version=1

<MESSAGE_IN_XML>

--response--
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
X-Frame-Options: SAMEORIGIN
Content-Type: application/xml;charset=utf-8
Date: Fri, 03 Apr 2015 01:08:22 GMT
Content-Length: 364

<MESSAGE_IN_XML>

看,从 Fiddler 的输出中,我看到的唯一区别是 header、Accept-Encoding 和 Cache-Control 条目。有没有办法不发送它们?或者我在这里遗漏了什么?

您应该发送授权 header。

样本:Authorization: Basic àaaaaaaa

这将解决未经授权的问题。

解释:

我们有多种方法来保护提供给 public 的服务。最常用的一种是通过授权将凭据从客户端应用程序传递到目标应用程序 headers.

授权header由客户端添加到请求中。在 C# 中,我们通常使用 AuthenticationHeaderValue

示例可在此处找到。

http://leastprivilege.com/2012/03/14/asp-net-webapi-security-4-examples-for-various-authentication-scenarios/

我同意Saravanan的分析,问题"appears"与请求的授权有关,但是,你问的是如何禁用某些headers(我不会去在没有更多关于你在做什么的上下文的情况下判断这是否是 "correct"),所以......

您可以 "fudge" HttpClient class 通过使用继承来创建您自己的版本,因为我在 System.Net.Http.HttpClient 本身中看不到任何代码(即使在 .NET 中参考来源,奇怪的是)我不得不使用一些技巧创建我自己的版本(实例化基础 class object 然后使用基于密封的 HttpRequestHeaders [= 创建的第二个自定义 class 分配值 class).

将此 class 添加到您的项目中,然后您将希望用 MyHttpClient 替换代码中对 HttpClient 的引用...以下是 class 您可以用来删除那些 headers(Accept-Encoding 和 Cache-Control),我在 Fiddler 中测试过 double-check 它有效:

public class MyHttpClient : HttpClient
{        

    public MyHttpClient(HttpClientHandler handler) : base(handler) {
        DefaultRequestHeaders = new MyHttpRequestHeaders();
    }

    //
    // Summary:
    //     Gets or Sets the headers which should be sent with each request.
    //
    // Returns:
    //     Returns The headers which should
    //     be sent with each request.
    public new MyHttpRequestHeaders DefaultRequestHeaders { get; set; }
}

public class MyHttpRequestHeaders : HttpHeaders
{
    public MyHttpRequestHeaders()
    {
        HttpClient client = new HttpClient();
        this.Accept = client.DefaultRequestHeaders.Accept;
        this.AcceptCharset = client.DefaultRequestHeaders.AcceptCharset;
        this.AcceptLanguage = client.DefaultRequestHeaders.AcceptLanguage;
        this.Authorization = client.DefaultRequestHeaders.Authorization;
        this.Connection = client.DefaultRequestHeaders.Connection;
        this.ConnectionClose = client.DefaultRequestHeaders.ConnectionClose;
        this.Date = client.DefaultRequestHeaders.Date;
        this.Expect = client.DefaultRequestHeaders.Expect;
        this.ExpectContinue = client.DefaultRequestHeaders.ExpectContinue;
        this.From = client.DefaultRequestHeaders.From;
        this.Host = client.DefaultRequestHeaders.Host;
        this.IfMatch = client.DefaultRequestHeaders.IfMatch;
        this.IfModifiedSince = client.DefaultRequestHeaders.IfModifiedSince;
        this.IfNoneMatch = client.DefaultRequestHeaders.IfNoneMatch;
        this.IfRange = client.DefaultRequestHeaders.IfRange;
        this.IfUnmodifiedSince = client.DefaultRequestHeaders.IfUnmodifiedSince;
        this.MaxForwards = client.DefaultRequestHeaders.MaxForwards;
        this.Pragma = client.DefaultRequestHeaders.Pragma;
        this.ProxyAuthorization = client.DefaultRequestHeaders.ProxyAuthorization;
        this.Range = client.DefaultRequestHeaders.Range;
        this.Referrer = client.DefaultRequestHeaders.Referrer;
        this.TE = client.DefaultRequestHeaders.TE;
        this.Trailer = client.DefaultRequestHeaders.Trailer;
        this.TransferEncoding = client.DefaultRequestHeaders.TransferEncoding;
        this.TransferEncodingChunked = client.DefaultRequestHeaders.TransferEncodingChunked;
        this.Upgrade = client.DefaultRequestHeaders.Upgrade;
        this.UserAgent = client.DefaultRequestHeaders.UserAgent;
        this.Via = client.DefaultRequestHeaders.Via;
        this.Warning = client.DefaultRequestHeaders.Warning;
    }

    // Summary:
    //     Gets the value of the Accept header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Accept header for an HTTP request.
    public HttpHeaderValueCollection<MediaTypeWithQualityHeaderValue> Accept { get; set; }
    //
    // Summary:
    //     Gets the value of the Accept-Charset header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Accept-Charset header for an HTTP request.
    public HttpHeaderValueCollection<StringWithQualityHeaderValue> AcceptCharset { get; set; }
    //
    // Summary:
    //     Gets the value of the Accept-Language header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Accept-Language header for an HTTP request.
    public HttpHeaderValueCollection<StringWithQualityHeaderValue> AcceptLanguage { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the Authorization header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.AuthenticationHeaderValue.The value of the
    //     Authorization header for an HTTP request.
    public AuthenticationHeaderValue Authorization { get; set; }
    //
    // Summary:
    //     Gets the value of the Connection header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Connection header for an HTTP request.
    public HttpHeaderValueCollection<string> Connection { get; set; }
    //
    // Summary:
    //     Gets or sets a value that indicates if the Connection header for an HTTP
    //     request contains Close.
    //
    // Returns:
    //     Returns System.Boolean.true if the Connection header contains Close, otherwise
    //     false.
    public bool? ConnectionClose { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the Date header for an HTTP request.
    //
    // Returns:
    //     Returns System.DateTimeOffset.The value of the Date header for an HTTP request.
    public DateTimeOffset? Date { get; set; }
    //
    // Summary:
    //     Gets the value of the Expect header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Expect header for an HTTP request.
    public HttpHeaderValueCollection<NameValueWithParametersHeaderValue> Expect { get; set; }
    //
    // Summary:
    //     Gets or sets a value that indicates if the Expect header for an HTTP request
    //     contains Continue.
    //
    // Returns:
    //     Returns System.Boolean.true if the Expect header contains Continue, otherwise
    //     false.
    public bool? ExpectContinue { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the From header for an HTTP request.
    //
    // Returns:
    //     Returns System.String.The value of the From header for an HTTP request.
    public string From { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the Host header for an HTTP request.
    //
    // Returns:
    //     Returns System.String.The value of the Host header for an HTTP request.
    public string Host { get; set; }
    //
    // Summary:
    //     Gets the value of the If-Match header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the If-Match header for an HTTP request.
    public HttpHeaderValueCollection<EntityTagHeaderValue> IfMatch { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the If-Modified-Since header for an HTTP request.
    //
    // Returns:
    //     Returns System.DateTimeOffset.The value of the If-Modified-Since header for
    //     an HTTP request.
    public DateTimeOffset? IfModifiedSince { get; set; }
    //
    // Summary:
    //     Gets the value of the If-None-Match header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.Gets the value
    //     of the If-None-Match header for an HTTP request.
    public HttpHeaderValueCollection<EntityTagHeaderValue> IfNoneMatch { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the If-Range header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.RangeConditionHeaderValue.The value of the
    //     If-Range header for an HTTP request.
    public RangeConditionHeaderValue IfRange { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the If-Unmodified-Since header for an HTTP request.
    //
    // Returns:
    //     Returns System.DateTimeOffset.The value of the If-Unmodified-Since header
    //     for an HTTP request.
    public DateTimeOffset? IfUnmodifiedSince { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the Max-Forwards header for an HTTP request.
    //
    // Returns:
    //     Returns System.Int32.The value of the Max-Forwards header for an HTTP request.
    public int? MaxForwards { get; set; }
    //
    // Summary:
    //     Gets the value of the Pragma header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Pragma header for an HTTP request.
    public HttpHeaderValueCollection<NameValueHeaderValue> Pragma { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the Proxy-Authorization header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.AuthenticationHeaderValue.The value of the
    //     Proxy-Authorization header for an HTTP request.
    public AuthenticationHeaderValue ProxyAuthorization { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the Range header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.RangeHeaderValue.The value of the Range header
    //     for an HTTP request.
    public RangeHeaderValue Range { get; set; }
    //
    // Summary:
    //     Gets or sets the value of the Referer header for an HTTP request.
    //
    // Returns:
    //     Returns System.Uri.The value of the Referer header for an HTTP request.
    public Uri Referrer { get; set; }
    //
    // Summary:
    //     Gets the value of the TE header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the TE header for an HTTP request.
    public HttpHeaderValueCollection<TransferCodingWithQualityHeaderValue> TE { get; set; }
    //
    // Summary:
    //     Gets the value of the Trailer header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Trailer header for an HTTP request.
    public HttpHeaderValueCollection<string> Trailer { get; set; }
    //
    // Summary:
    //     Gets the value of the Transfer-Encoding header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Transfer-Encoding header for an HTTP request.
    public HttpHeaderValueCollection<TransferCodingHeaderValue> TransferEncoding { get; set; }
    //
    // Summary:
    //     Gets or sets a value that indicates if the Transfer-Encoding header for an
    //     HTTP request contains chunked.
    //
    // Returns:
    //     Returns System.Boolean.true if the Transfer-Encoding header contains chunked,
    //     otherwise false.
    public bool? TransferEncodingChunked { get; set; }
    //
    // Summary:
    //     Gets the value of the Upgrade header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Upgrade header for an HTTP request.
    public HttpHeaderValueCollection<ProductHeaderValue> Upgrade { get; set; }
    //
    // Summary:
    //     Gets the value of the User-Agent header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the User-Agent header for an HTTP request.
    public HttpHeaderValueCollection<ProductInfoHeaderValue> UserAgent { get; set; }
    //
    // Summary:
    //     Gets the value of the Via header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Via header for an HTTP request.
    public HttpHeaderValueCollection<ViaHeaderValue> Via { get; set; }
    //
    // Summary:
    //     Gets the value of the Warning header for an HTTP request.
    //
    // Returns:
    //     Returns System.Net.Http.Headers.HttpHeaderValueCollection<T>.The value of
    //     the Warning header for an HTTP request.
    public HttpHeaderValueCollection<WarningHeaderValue> Warning { get; set; }
}