Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Net.Http;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Web.Http.Controllers;
- using System.Web.Http.Dispatcher;
- namespace Confirmit.Cml.Storage.Service.Handlers
- {
- /// <summary>
- /// Sends out response to HTTP verb OPTIONS
- /// </summary>
- public sealed class OptionsHandler : DelegatingHandler
- {
- protected override async Task<HttpResponseMessage> SendAsync(
- HttpRequestMessage request, CancellationToken cancellationToken)
- {
- return await base.SendAsync(request, cancellationToken).ContinueWith(
- task =>
- {
- var response = task.Result;
- // If not Http OPTIONS verb requested or there is explicit OPTIONS controller action,
- // then pass through
- if (request.Method != HttpMethod.Options ||
- response.StatusCode != HttpStatusCode.MethodNotAllowed)
- return response;
- // Otherwise obtain allowed methods automatically
- var methods = new ActionSelector(request).GetSupportedMethods();
- if (methods == null)
- return response;
- response = new HttpResponseMessage(HttpStatusCode.OK)
- {
- Content = new StringContent(string.Empty)
- };
- response.Content.Headers.Add("Allow", methods);
- response.Content.Headers.Add("Allow", "OPTIONS");
- return response;
- }, cancellationToken);
- }
- private class ActionSelector
- {
- private readonly HttpRequestMessage _request;
- private readonly HttpControllerContext _context;
- private readonly ApiControllerActionSelector _apiSelector;
- private static readonly string[] Methods =
- {
- "GET", "PUT", "POST", "PATCH", "DELETE", "HEAD", "TRACE"
- };
- public ActionSelector(HttpRequestMessage request)
- {
- try
- {
- var configuration = request.GetConfiguration();
- var requestContext = request.GetRequestContext();
- var controllerDescriptor =
- new DefaultHttpControllerSelector(configuration).SelectController(request);
- _context = new HttpControllerContext
- {
- Request = request,
- RequestContext = requestContext,
- Configuration = configuration,
- ControllerDescriptor = controllerDescriptor
- };
- }
- catch
- {
- return;
- }
- _request = _context.Request;
- _apiSelector = new ApiControllerActionSelector();
- }
- public IEnumerable<string> GetSupportedMethods()
- {
- return _request == null ? null : Methods.Where(IsMethodSupported);
- }
- private bool IsMethodSupported(string method)
- {
- _context.Request = new HttpRequestMessage(new HttpMethod(method), _request.RequestUri);
- var routeData = _context.RouteData;
- try
- {
- return _apiSelector.SelectAction(_context) != null;
- }
- catch
- {
- return false;
- }
- finally
- {
- _context.RouteData = routeData;
- }
- }
- }
- }
- }
- // Example of controller's action
- [Route("Documents", Name = "DocumentsOptions")]
- [HttpOptions]
- [ResponseType(typeof(void))]
- [OverrideAuthorization] // disable authorization for this method
- public IHttpActionResult DocumentsOptions()
- {
- const string supportedMethods = "GET,POST,OPTIONS";
- string methods;
- if (!IsAuthenticated()) // Determine if current user is authenticated
- // This could be CORS request, return all supported methods
- methods = supportedMethods;
- else
- {
- var list = new List<string> { "GET" };
- if (IsInRole(Role.DocumentCreator)) // Check if current user can create new document
- list.Add("POST");
- list.Add("OPTIONS");
- methods = string.Join(",", list);
- }
- HttpContext.Current.Response.AppendHeader("Allow", methods);
- return Ok();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement