Reputation: 19738
I want to handle HEAD requests in my Web API 2 application. I copy-pasted the code from StrathWeb's blog post Adding HTTP HEAD support to ASP.NET Web API:
public class HeadHandler : DelegatingHandler
{
private const string Head = "IsHead";
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request.Method == HttpMethod.Head)
{
request.Method = HttpMethod.Get;
request.Properties.Add(Head, true);
}
var response = await base.SendAsync(request, cancellationToken);
object isHead;
response.RequestMessage.Properties.TryGetValue(Head, out isHead);
if (isHead != null && ((bool) isHead))
{
var oldContent = await response.Content.ReadAsByteArrayAsync();
var content = new StringContent(string.Empty);
content.Headers.Clear();
foreach (var header in response.Content.Headers)
{
content.Headers.Add(header.Key, header.Value);
}
content.Headers.ContentLength = oldContent.Length;
response.Content = content;
}
return response;
}
}
When I make a HEAD request from Fiddler:
HEAD http://localhost:54225/api/books/5 HTTP/1.1
User-Agent: Fiddler
Host: localhost:54225
I get the following response back:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 0
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcc2ltb25lXERvY3VtZW50c1xTaW1vbnNEb2N1bWVudHNcSVRcQyNcRGVtb0NvZGVcUkVTVGZ1bFdlYlNlcnZpY2VDbGllbnRERU1PXEJvb2tTZXJ2aWNlXGFwaVxib29rc1w1?=
X-Powered-By: ASP.NET
Date: Sun, 19 Feb 2017 12:09:52 GMT
The Content-Length is 0 but it should be 104 bytes.
When I add a breakpoint to the HeadHandler and step through the code it seems to set the Content-Length header value correctly, to 104 bytes, before returning the response.
Could there be some other step in the pipeline that is running after the HeadHandler, which recognises the response has no body, and sets the Content-Length to 0? The only things in the WebApiConfig.cs that come after the HeadHandler has been added are the mapping of the HttpAttribute routes and the setting up of the default route, neither of which seem likely to me to result in the Content-Length header being reset. Alternatively, could a configuration setting somewhere possibly affect the Content-Length returned in the response?
Upvotes: 4
Views: 5442
Reputation: 1740
All you need to do is set the Content-Length of the response's Content.Headers - no need to create new content for the response. The act of requesting HEAD removes the body content from the response anyway.
This may have been a change since the article you quoted was written (2013), and no longer needs to create content from scratch...
So this is all you should need:
public class HeadHandler : DelegatingHandler
{
private const string Head = "IsHead";
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request.Method == HttpMethod.Head)
{
request.Method = HttpMethod.Get;
request.Properties.Add(Head, true);
}
var response = await base.SendAsync(request, cancellationToken);
object isHead;
response.RequestMessage.Properties.TryGetValue(Head, out isHead);
if (isHead != null && ((bool)isHead))
{
var oldContent = await response.Content.ReadAsByteArrayAsync();
response.Content.Headers.ContentLength = oldContent.Length;
return response;
}
return response;
}
}
Upvotes: 3