2013-02-15 45 views
3

我正在使用ServiceStack构建REST Web服务。我想允许跨域请求,所以我注册了CorsFeature插件。ServiceStack在选项请求上返回405

我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不允许的方法:

请求:

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 

编辑


添加一个空的选项方法对服务确实防止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()。它是否正确?

回答

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(); 
    } 
}); 
+0

任何想法VB.net版本如何? – Iladarsda 2013-07-19 12:34:56

+0

尝试http://converter.telerik.com/ – sroes 2013-07-21 17:28:12

2

in ServiceStack意味着该方法尚未实施。

因此,您需要为Options动词添加处理程序。该方法的主体可以是空的,如:

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

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

如果你想允许所有选项请求(即无论哪个服务的是),你可以像注册一个全局请求过滤器

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

+0

CorsFilter应该处理CORS对OPTIONS的使用。所以我不确定你的答案是否真的回答了这个问题。 – bmargulies 2013-02-15 21:49:57

+0

[EnableCors属性](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.ServiceInterface/Cors/EnableCorsAttribute.cs)只会发出指定的CORS标头。它不处理隐式处理** Options **或任何其他HTTP动词。 – mythz 2013-02-15 23:15:48

+0

谢谢,但这并不适合我。看我的编辑。 – sroes 2013-02-16 08:50:24

2

我对此行为有点混乱。不想在每个服务上制作虚拟的Options()方法,并在每个Dto类上添加虚假的路线。 所有我需要的 - 即ServiceStack AppHost响应每个'选项'请求,在每个网址上,具有相同的行为。 所以这就是我所结束的。

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

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; 
    } 
} 

然后添加它在主机配置方法:

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()); 

所以这无论url,dto和servi如何,使用“OPTIONS”标题的每个请求都使用双向ServiceStack以“200 OK”响应ce声明。

+0

我试过你的方法,现在,而不是404,我得到一个500,因为“抛出新的System.NotImplementedException()”。你不明白吗? – Dema 2013-09-24 21:12:37

+0

没有。看起来像你遇到了条件,这个过滤器被原始IHttpHandler路由而不是IServiceStackHttpHandler调用。也许在某处内部或其他地方,只需将第一个ProcessRequest()方法内容更改为[此处](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/ServiceStackHttpHandler.cs) – justmara 2013-09-30 08:36:48

+0

@Dema修改ProcessRequest(HttpContext上下文)'方法的内容 - 而不是引发异常,添加:'ProcessRequest(null,new HttpResponseWrapper(context.Response),null);' – eXavier 2013-10-31 15:17:41

相关问题