2

I am developing a Restful API where I need to check the authorization before making the actual DELETE request. So I thought it would be nice to use HEAD method as a preflight check.

I expected that an unauthorized request with HEAD method will return 401/403 response with no body. However, it turns out that WebApi2 crashes with following exception and closes the connection:

Exception caught: 'System.Net.ProtocolViolationException' in System.dll ("Bytes to be written to the stream exceed the Content-Length bytes size specified.")

Other HTTP methods (DELETE,GET) seem to work properly - return 401 response.

I can workaround it with a GET request, but it seems like a bug in WebApi. AuthorizeAttribute always adds a content, no matter what the original request method was.

My question is: Is it a bug or it is an intended behavior and there is a reason why I shouldn't use HEAD method here?

Here is a sample program that reproduces the issue:

namespace OwinServer
{
    [Authorize]
    public class ValuesController : ApiController
    {
        // GET api/values 
        public IEnumerable<string> Get()
        {
            return new[] { "value1", "value2" };
        }

        //HEAD api/values
        public void Head()
        {

        }

        //DELETE api/values
        public void Delete()
        {

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var baseAddress = "http://localhost:9000/";

            // Start OWIN host 
            using (WebApp.Start(baseAddress, Configuration))
            {
                Console.WriteLine("Host started");
                Console.ReadLine();
            }
        }

        public static void Configuration(IAppBuilder appBuilder)
        {
            // Configure Web API for self-host. 
            var config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            appBuilder.UseWebApi(config);
        }
    }
}

The behavior can be tested using PowerShell:

Sample request that fails:

Invoke-WebRequest -Uri 'http://localhost:9000/api/values' -Method HEAD

Sample request that works:

Invoke-WebRequest -Uri 'http://localhost:9000/api/values' -Method DELETE

1 Answers1

1

This has been discussed https://github.com/aspnet/AspNetWebStack/issues/189. Seems they expect you to handle it at your end.

JJ.
  • 879
  • 7
  • 10