Servicestack CorsFeature Global Options Handler Not Firing on Certain Routes;

后端 未结 3 757
隐瞒了意图╮
隐瞒了意图╮ 2020-12-17 23:51

I\'ve got a service setup using the CorsFeature, and am using the approach that mythz suggested in other answers, collected in a function used in the appHost file:

3条回答
  •  粉色の甜心
    2020-12-18 00:23

    The PreRequestFilters is only fired for valid routes which doesn't exclude OPTIONS (e.g. by leaving Verbs=null and allow it to handle all Verbs instead - inc. OPTIONS).

    To be able to handle all OPTIONS requests (i.e. even for non-matching routes) you would need to handle the Request at the start of the Request pipeline (i.e. before Routes are matched) with Config.RawHttpHandlers. This is done in the CorsFeature for you in the next major (v4) release of ServiceStack with:

    //Handles Request and closes Response after emitting global HTTP Headers
    var emitGlobalHeadersHandler = new CustomActionHandler(
        (httpReq, httpRes) => httpRes.EndRequest());
    
    appHost.RawHttpHandlers.Add(httpReq =>
        httpReq.HttpMethod == HttpMethods.Options
            ? emitGlobalHeadersHandler
            : null); 
    

    CustomActionHandler doesn't exist in v3, but it's easily created with:

    public class CustomActionHandler : IServiceStackHttpHandler, IHttpHandler 
    {
        public Action Action { get; set; }
    
        public CustomActionHandler(Action action)
        {
            if (action == null)
                throw new Exception("Action was not supplied to ActionHandler");
    
            Action = action;
        }
    
        public void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName)
        {            
            Action(httpReq, httpRes);
        }
    
        public void ProcessRequest(HttpContext context)
        {
            ProcessRequest(context.Request.ToRequest(GetType().Name), 
                context.Response.ToResponse(),
                GetType().Name);
        }
    
        public bool IsReusable
        {
            get { return false; }
        }
    }
    

    Using Fallback handler

    Another way to match all Routes is to specify a FallbackRoute, e.g to handle all routes you can add a wildcard to the Fallback route with:

    [FallbackRoute("/{Path*}")]
    public class Fallback
    {
        public string Path { get; set; }
    }
    

    But as it matches all un-handled routes it no longer gives 404 for non-matching requests since all un-matched routes are now matched. But you can easily handle it manually with:

    public class FallbackService : Service
    {
        public object Any(Fallback request)
        {
            if (base.Request.HttpMethod == "OPTIONS")
                return null;
    
            throw HttpError.NotFound("{0} was not found".Fmt(request.Path));
        }
    }
    

提交回复
热议问题