Advertisement
AndreyRodin

OPTIONS

May 3rd, 2018
965
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.89 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Net;
  4. using System.Net.Http;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using System.Web.Http.Controllers;
  8. using System.Web.Http.Dispatcher;
  9.  
  10. namespace Confirmit.Cml.Storage.Service.Handlers
  11. {
  12.     /// <summary>
  13.     /// Sends out response to HTTP verb OPTIONS
  14.     /// </summary>
  15.     public sealed class OptionsHandler : DelegatingHandler
  16.     {
  17.         protected override async Task<HttpResponseMessage> SendAsync(
  18.             HttpRequestMessage request, CancellationToken cancellationToken)
  19.         {
  20.             return await base.SendAsync(request, cancellationToken).ContinueWith(
  21.                 task =>
  22.                 {
  23.                     var response = task.Result;
  24.  
  25.                     // If not Http OPTIONS verb requested or there is explicit OPTIONS controller action,
  26.                     // then pass through
  27.                     if (request.Method != HttpMethod.Options ||
  28.                         response.StatusCode != HttpStatusCode.MethodNotAllowed)
  29.                         return response;
  30.  
  31.                     // Otherwise obtain allowed methods automatically
  32.                     var methods = new ActionSelector(request).GetSupportedMethods();
  33.                     if (methods == null)
  34.                         return response;
  35.  
  36.                     response = new HttpResponseMessage(HttpStatusCode.OK)
  37.                     {
  38.                         Content = new StringContent(string.Empty)
  39.                     };
  40.                     response.Content.Headers.Add("Allow", methods);
  41.                     response.Content.Headers.Add("Allow", "OPTIONS");
  42.                     return response;
  43.                 }, cancellationToken);
  44.         }
  45.  
  46.         private class ActionSelector
  47.         {
  48.             private readonly HttpRequestMessage _request;
  49.             private readonly HttpControllerContext _context;
  50.             private readonly ApiControllerActionSelector _apiSelector;
  51.             private static readonly string[] Methods =
  52.             {
  53.                 "GET", "PUT", "POST", "PATCH", "DELETE", "HEAD", "TRACE"
  54.             };
  55.  
  56.             public ActionSelector(HttpRequestMessage request)
  57.             {
  58.                 try
  59.                 {
  60.                     var configuration = request.GetConfiguration();
  61.                     var requestContext = request.GetRequestContext();
  62.  
  63.                     var controllerDescriptor =
  64.                         new DefaultHttpControllerSelector(configuration).SelectController(request);
  65.  
  66.                     _context = new HttpControllerContext
  67.                     {
  68.                         Request = request,
  69.                         RequestContext = requestContext,
  70.                         Configuration = configuration,
  71.                         ControllerDescriptor = controllerDescriptor
  72.                     };
  73.                 }
  74.                 catch
  75.                 {
  76.                     return;
  77.                 }
  78.  
  79.                 _request = _context.Request;
  80.                 _apiSelector = new ApiControllerActionSelector();
  81.             }
  82.  
  83.             public IEnumerable<string> GetSupportedMethods()
  84.             {
  85.                 return _request == null ? null : Methods.Where(IsMethodSupported);
  86.             }
  87.  
  88.             private bool IsMethodSupported(string method)
  89.             {
  90.                 _context.Request = new HttpRequestMessage(new HttpMethod(method), _request.RequestUri);
  91.                 var routeData = _context.RouteData;
  92.  
  93.                 try
  94.                 {
  95.                     return _apiSelector.SelectAction(_context) != null;
  96.                 }
  97.                 catch
  98.                 {
  99.                     return false;
  100.                 }
  101.                 finally
  102.                 {
  103.                     _context.RouteData = routeData;
  104.                 }
  105.             }
  106.         }
  107.     }
  108. }
  109.  
  110.         // Example of controller's action
  111.         [Route("Documents", Name = "DocumentsOptions")]
  112.         [HttpOptions]
  113.         [ResponseType(typeof(void))]
  114.         [OverrideAuthorization] // disable authorization for this method
  115.         public IHttpActionResult DocumentsOptions()
  116.         {
  117.             const string supportedMethods = "GET,POST,OPTIONS";
  118.  
  119.             string methods;
  120.             if (!IsAuthenticated()) // Determine if current user is authenticated
  121.                 // This could be CORS request, return all supported methods
  122.                 methods = supportedMethods;
  123.             else
  124.             {
  125.                 var list = new List<string> { "GET" };
  126.                 if (IsInRole(Role.DocumentCreator)) // Check if current user can create new document
  127.                     list.Add("POST");
  128.                 list.Add("OPTIONS");
  129.  
  130.                 methods = string.Join(",", list);
  131.             }
  132.  
  133.             HttpContext.Current.Response.AppendHeader("Allow", methods);
  134.             return Ok();
  135.         }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement