【问题标题】:ServiceStack returns 405 on OPTIONS requestServiceStack 在 OPTIONS 请求上返回 405
【发布时间】:2013-01-31 22:10:23
【问题描述】:

我正在使用 ServiceStack 构建一个 REST Web 服务。我想允许跨域请求,所以我注册了 CorsFeature 插件。

我的 AppHost 如下所示:

public class HomeAppHost : AppHostHttpListenerBase 
{
    public Context Context { get; set; }

    public HomeAppHost(Context context)
        : base("HomeAutomation", typeof(HomeInterfaceService).Assembly)
    {
        Context = context;
    }

    public override void Configure(Funq.Container container)
    {
        Plugins.Add(new CorsFeature());

        Routes
            .Add<HomeInterface>("/HomeInterface")
            .Add<HomeInterface>("/HomeInterface/{Id}")
            .Add<ViewModel>("/ViewModel")
            .Add<FunctionInput>("/Function")
        ;
    }
}

然后,当向服务发出 OPTIONS 请求时,会导致 405 Method Not Allowed:

请求:

OPTIONS /Function HTTP/1.1
Host: localhost:1337
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0 FirePHP/0.7.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: nl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Origin: http://localhost
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
x-insight: activate
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

回复:

HTTP/1.1 405 Method Not Allowed
Content-Length: 1837
Content-Type: application/xml
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 15 Feb 2013 20:19:33 GMT

编辑


向服务添加一个空的 Options 方法确实可以防止 405 被触发。但是,响应似乎是空的:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Server: Microsoft-HTTPAPI/2.0
Date: Sat, 16 Feb 2013 08:44:21 GMT

添加以下内容也会给我一个空响应:

RequestFilters.Add((httpReq, httpRes, requestDto) =>
{
    //Handles Request and closes Responses after emitting global HTTP Headers
    if (httpReq.HttpMethod == "OPTIONS")
        httpRes.End();
});

我不得不将 httpReq.Method 更改为 httpReq.HttpMethod 并将 httpRes.EndServiceStackRequest() 更改为 httpRes.End()。它是否正确?

【问题讨论】:

标签: cors servicestack http-options-method


【解决方案1】:
ServiceStack 中的

405 表示该方法尚未实现。

所以您需要为Options 动词添加一个处理程序。方法体可以为空,例如:

public MyService : Service 
{ 
    public void Options(HomeInterface request) {}
}

如果您想允许 所有 选项请求(即不管它是哪个服务),您可以注册一个全局请求过滤器,例如:

this.RequestFilters.Add((httpReq, httpRes, requestDto) => {
   //Handles Request and closes Responses after emitting global HTTP Headers
    if (httpReq.Method == "OPTIONS") 
        httpRes.EndServiceStackRequest();
});

如果您想更细粒度地控制 Option 请求的处理方式,您可以在 Filter Attributes 中使用相同的逻辑。

【讨论】:

  • CorsFilter 应该处理 CORS 对 OPTIONS 的使用。所以我不确定你的回答是否真的回答了这个问题。
  • EnableCors Attribute 仅发出指定的 CORS 标头。它不隐式处理 Options 或任何其他 HTTP 动词。
  • 标题不只是神奇地单独出现。你注册Plugins.Add(new CorsFeature());了吗?因为我看不到。有关详细信息,请参阅this question on CORS
  • VB.net版本好吗?
【解决方案2】:

不确定这是否是正确的方法,但我现在正在使用请求过滤器自己处理 CORS:

RequestFilters.Add((httpReq, httpRes, requestDto) =>
{
    httpRes.AddHeader("Access-Control-Allow-Origin", "*");

    if (httpReq.HttpMethod == "OPTIONS")
    {
        httpRes.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
        httpRes.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
        httpRes.End();
    }
});

【讨论】:

  • 知道 VB.net 版本会是什么样子吗?
【解决方案3】:

我对这种行为有点困惑。不想在每个服务上创建虚拟 Options() 方法并在每个 Dto 类上添加假路由。 我所需要的一切——ServiceStack AppHost 在每个 url 上以相同的行为响应每个“OPTIONS”请求。 所以这就是我的结局。

为选项创建了我自己的处理程序:

public class OptionsRequestHandler : IHttpHandler, IServiceStackHttpHandler
{
    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        ProcessRequest(null, new HttpResponseWrapper(context.Response), null);          
    }

    public void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName)
    {
        httpRes.EndServiceStackRequest();
        return;
    }
}

然后在host的Configure方法中添加:

this.CatchAllHandlers.Add((httpMethod, pathInfo, filePath) =>
{
    if ("OPTIONS".Equals(httpMethod, System.StringComparison.InvariantCultureIgnoreCase))
        return new OptionsRequestHandler();
    else return null;
});

当然也没有忘记 CorsFeature:

host.Plugins.Add(new ServiceStack.ServiceInterface.Cors.CorsFeature());

因此,ServiceStack 以“200 OK”响应每个带有“OPTIONS”标头的请求,而不管 url、dto 和服务声明如何。

【讨论】:

  • 我已经尝试过你的方法,现在,由于“抛出新的 System.NotImplementedException()”,我得到了 500 而不是 404。你不明白吗?
  • 没有。看起来您遇到了这样的情况,即此过滤器由原始 IHttpHandler 路由调用,而不是由 IServiceStackHttpHandler 调用。可能是内部的某个地方等等。只需将第一个 ProcessRequest() 方法的内容更改为 here
  • @Dema 修改 ProcessRequest(HttpContext context) 方法的内容 - 而不是抛出异常,添加这个:ProcessRequest(null, new HttpResponseWrapper(context.Response), null);
  • 我已经在代码中替换了那个 'throw' 块,这样它就不会再混淆了 8)
猜你喜欢
  • 2017-04-19
  • 2020-05-02
  • 2016-12-04
  • 2019-05-09
  • 2019-07-14
  • 2016-12-29
  • 2013-10-24
  • 1970-01-01
  • 2020-10-26
相关资源
最近更新 更多