How does HTTP OPTIONS method determine allowed methods in IIS 8.5?

Solution 1:

Interesting question. All the methods to remove response headers from IIS don't seem to work for the Allow and Public headers, an OPTIONS request always returns:

Allow:  OPTIONS, TRACE, GET, HEAD, POST
Public: OPTIONS, TRACE, GET, HEAD, POST

regardless what the server actually allows.

All requests in IIS are handled by modules, the OPTIONS requests are handled by the ProtocolSupportModule which is not essential and as it seems pretty dumb.

If we remove that module, the server doesn't response to Options request anymore, which you still want to support, so we have to use another module to answer those.

Open:

%SystemRoot%\System32\inetsrv\config\applicationHost.config

and search for OPTIONSVerbHandler comment that line and while you are at it the one above (TRACEVerbHandler) as well. Now add a new node:

<add name="MyOPTIONSVerbHandler" path="*" verb="OPTIONS" modules="StaticFileModule" requireAccess="None" />

the whole block should look like this:

    <!--  <add name="TRACEVerbHandler" path="*" verb="TRACE" modules="ProtocolSupportModule" requireAccess="None" /> 
          <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" /> -->
          <add name="MyOPTIONSVerbHandler" path="*" verb="OPTIONS" modules="StaticFileModule" requireAccess="None" /> 

Now the staticFileModule will process the OPTIONS requests but it will not return any content.

If you now make a OPTIONS request to the server, you wont get a Allow nor a Public header, you can add them easily in web.config

<system.webServer>
 <httpProtocol>
      <customHeaders>
          <add name="Allow"  value="GET,POST,HEAD" />  
          <add name="Public" value="GET,POST,HEAD" />
      </customHeaders>
  </httpProtocol>        
</system.webServer>

now your OPTIONS requests work as required, but those extra headers are also sent with any GET or POST requests which I think is still valid http.

If you only want to use those headers for OPTIONS requests you could write a simple http module that sets these headers and use it instead of the StaticFileModule I used above.