Ale*_*lex 6 c# request request-headers dotnet-httpclient
谁能解释一下请求标头和内容标头之间有什么区别?
在本例中,我讨论的是 UWPHttpClient对象。首先创建HttpClient,然后创建HttpRequestMessage,然后分配(在我的例子中分配HttpStreamContent给 HttpRequest 消息的 Content 属性)。上有 Headers 属性HttpRequestMessage, 上也有 Headers 属性HttpStreamContent。
我什么时候应该使用其中一种或另一种?
在一种或另一种情况下,标题到底会出现在哪里?
这是一个代码片段来解释我的意思
using(var objProtocolFilter = new HttpBaseProtocolFilter()) {
objProtocolFilter.AllowUI = false;
objProtocolFilter.CacheControl.ReadBehavior = HttpCacheReadBehavior.NoCache;
objProtocolFilter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.NoCache;
using(var objClient = new HttpClient(objProtocolFilter)) {
HttpMethod eMethod = Method switch {
HttpUploadMethod.Post => HttpMethod.Post,
HttpUploadMethod.Put => HttpMethod.Put,
_ => throw new ValueOutOfRangeException(nameof(Method))
};
using(var objRequest = new HttpRequestMessage(eMethod, RemoteUri)) {
_Headers.Cast<string>().Execute(item => objRequest.Headers.TryAppendWithoutValidation(item, _Headers[item]));
objRequest.Content = new HttpStreamContent(objInputStream.AsInputStream());
_Headers.Cast<string>().Execute(item => objRequest.Content.Headers.TryAppendWithoutValidation(item, _Headers[item]));
objRequest.Content.Headers.ContentLength = (ulong)objInputStream.Length;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我只是将相同的标头列表添加到HttpRequestMessage和 到HttStreamContent。我想这是错误的,除非这些对象足够聪明,可以在一种或另一种情况下仅应用允许的标头。那么,哪些标头应该放在哪里?它们可以互换吗?
Pet*_*ala 12
它们有不同的目的:
Content-Disposition、Content-Range、Content-Length、Content-Type等。Accept、Accept-Encoding、Authorization、Cookie等。HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, address);
request.Headers.Add("Content-Type", "application/json");
Run Code Online (Sandbox Code Playgroud)
这将产生以下异常:
System.InvalidOperationException:'误用标头名称。确保请求标头与 HttpRequestMessage 一起使用,响应标头与 HttpResponseMessage 一起使用,内容标头与 HttpContent 对象一起使用。
var content = new StringContent("Test", Encoding.UTF8);
content.Headers.Add("Accept","application/json");
Run Code Online (Sandbox Code Playgroud)
这将产生以下异常:
System.InvalidOperationException:'误用标头名称。确保请求标头与 HttpRequestMessage 一起使用,响应标头与 HttpResponseMessage 一起使用,内容标头与 HttpContent 对象一起使用。
const string headerKey = "A", requestHeaderValue = "B", contentHeaderValue = "C";
var content = new StringContent("Test", Encoding.UTF8);
content.Headers.Add(headerKey, contentHeaderValue);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, address);
request.Headers.Add(headerKey, requestHeaderValue);
Run Code Online (Sandbox Code Playgroud)
这不会产生任何异常。
为了能够回答这个问题,我将使用WireMock.Net nuget 包来运行模拟服务器。
const string address = "http://localhost:9000", route = "/";
var server = WireMockServer.Start(new WireMockServerSettings { Urls = new[] { address } });
server
.Given(Request.Create()
.WithPath(route)
.WithHeader(headerKey, new ExactMatcher(requestHeaderValue))
.UsingPost())
.RespondWith(Response.Create()
.WithBody("From Request header")
.WithStatusCode(200));
server
.Given(Request.Create()
.WithPath(route)
.WithHeader(headerKey, new ExactMatcher(contentHeaderValue))
.UsingPost())
.RespondWith(Response
.Create()
.WithBody("From Content header")
.WithStatusCode(200));
Run Code Online (Sandbox Code Playgroud)
/并且它预期一个POST请求headerKey它可能响应的值
From Request headerFrom Content header如果我发送一个在两个对象上设置相同标头键的请求,那么我将收到以下响应:
From Request header
Run Code Online (Sandbox Code Playgroud)
如果我切换标题键分配的顺序会怎样?
From Request header
Run Code Online (Sandbox Code Playgroud)
结果将是相同的:From Request header。
为了完整起见,这里是完整的源代码:
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, address);
request.Headers.Add(headerKey, requestHeaderValue);
var content = new StringContent("Test", Encoding.UTF8);
content.Headers.Add(headerKey, contentHeaderValue);
Run Code Online (Sandbox Code Playgroud)
更新 #1在我的示例中发现了一个错误
我刚刚意识到我忘记使用Content以下属性HttpRequestMessage:
var request = new HttpRequestMessage(HttpMethod.Post, address) { Content = content };
Run Code Online (Sandbox Code Playgroud)
{"Status":"No matching mapping found"}From Content headerFrom Request header那么,我们为什么会收到这个No matching mapping found?原因是因为在这种情况下发送了两个值,并且没有针对该情况注册的路由。
为了证明这个理论,让我们编写一些评估代码:
var logs = server.FindLogEntries(Request.Create().WithPath(route).UsingPost());
Console.WriteLine(logs.First().RequestMessage.Headers[headerKey].Count);
Run Code Online (Sandbox Code Playgroud)
FindLogEntries)A标头包含值B和C