如何在Restlet 2.3.1中使用CORS? [英] How to use CORS in Restlet 2.3.1?

查看:423
本文介绍了如何在Restlet 2.3.1中使用CORS?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图为响应设置Access-Control-Allow-Origin:*标头。但是,头不存在。我做错了什么?

  public class JsonApplication extends Application 
{
private static final String SERVER_URL =http:// localhost :8111;

public static void main(String [] args)throws Exception
{
服务器testServer =新服务器(Protocol.HTTP,8111);
JsonApplication jsonApplication = new JsonApplication();

CorsService corsService = new CorsService();
corsService.setAllowedOrigins(new HashSet(Arrays.asList(*)));
corsService.setAllowedCredentials(true);

jsonApplication.getServices()。add(corsService);

testServer.setNext(jsonApplication);
testServer.start();
}

@Override
public Restlet createInboundRoot()
{
路由器router = new Router(getContext());
router.attach(SERVER_URL +/,RootResource.class);
return router;
}
}

我检查了org.restlet.engine的源代码.application.CorsResponseHelper并且它包含以下代码:

  public void addCorsResponseHeaders(Request request,Response response){

String origin = request.getHeaders()。getFirstValue(Origin,true);

if(origin == null){
//不是CORS请求
return;
}
...
}

当前CORS实现不支持从本地html文件发出的请求,因为在那种情况下,origin == null。



我向我的servlet应用程序添加了一些日志记录:

  JsonApplication :: createInboundRoot()
16:26 MyCorsService()
16:26 myCorsService = wwwdbase .rest.cors.MyCorsService @ 6e1b241d
16:26 MyCorsService :: setAllowedOrigins(),[*]
16:26 services:[org.restlet.service.TunnelService@4c88fe62,
org .restlet.service.StatusService @ 68349a5b,
org.restlet.service.DecoderService@77cfd8d3,
org.restlet.service.EncoderService@40c331fb,
org.restlet.service.RangeService@4bb3bc6f ,
org.restlet.service.ConnectorService@7990100,
org.restlet.service.ConnegService@e194860,
org.restlet.service.ConverterService@578cfcb1,
org.restlet .service.MetadataService @ 18a62eb,
org.restlet.service.TaskService@4ed4f2db,
wwwdbase.rest.cors.MyCorsService@6e1b241d]

我们可以看到MyCorsService是可用的。然而,它从不被servlet框架调用。另一方面,如果我从IDE运行服务(Java SE版本),MyCorsService被调用。为什么这些案件的行为不同?



部分解决方案:我设法通过更改org.restlet.engine.header.HeaderUtils中的代码添加allow origin标头

  if(response.getAccessControlAllowOrigin()!= null)
{
addHeader(HeaderConstants.HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
response.getAccessControlAllowOrigin标题);
}

  if(response.getAccessControlAllowOrigin()!= null)
{
addHeader(HeaderConstants.HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
response.getAccessControlAllowOrigin(),headers);
}
else
{
// ---添加在任何情况下!
//
response.setAccessControlAllowOrigin(*);
addHeader(HeaderConstants.HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
response.getAccessControlAllowOrigin(),headers);
}

但是,问题的答案为什么Tomcat中的servlet框架没有调用cors服务仍然未知...

解决方案

实际上,您已正确配置Restlet的CORS服务; / p>

在CORS的上下文中,有两种请求:




  • strong>简单请求。简而言之,当您使用方法 GET HEAD 和某些情况下 POST

  • 预发请求其他需要使用CORS标头进行跨网域请求的情况。



所以如果你只是做一个方法 GET 没有。尝试使用带有JSON内容的方法 POST ,您将看到CORS标头。



有关详细信息,可以查看此链接:





已编辑



我对您的问题做了一个更完整的测试。我有两个Restlet服务器在不同的端口上启动(8182为使用AJAX访问资源,8183为JS应用程序访问资源)。



第一个用您的代码配置:

  CorsService corsService = new CorsService 
corsService.setAllowedOrigins(new HashSet(Arrays.asList(*)));
corsService.setAllowedCredentials(true);

RestletApplication application = new RestletApplication();
application.getServices()。add(corsService);
component.getDefaultHost()。attachDefault(application);

服务器资源很简单:

  public class MyServerResource extends ServerResource {
@Get
public TestBean ping(){
TestBean bean = new TestBean();
bean.setMessage(pong);
return bean;
}
}

第二个应用程序仅使用Restlet目录来提供静态内容:

  @Override 
public Restlet createInboundRoot(){
路由器router = new Router(getContext ));
router.attach(/ static,new Directory(
getContext(),clap:/// test / static));
return router;
}

除了JQuery库,我添加了以下HTML文件:

 < html> 
< head>
< script type =text / javascriptsrc =/ static / jquery-1.11.2.min.js>< / script>
< script type =text / javascript>
$(document).ready(function(){
$('#id1')。click(function(){
$ .ajax({
url:'http :// localhost:8182 / ping',
type:'GET',
success:function(result,status){
console.log('ok ='+ result);
},
error:function(result,status,error){
console.log('error');
},
complete:function ){
console.log('complete');
}
});
});
});
< / script>
< / head>
< body>
< div id =id1>点击< / div>
< / body>
< / html>

这是我点击按钮点击 p>

  //请求
接受* / *
Accept-Encoding gzip,deflate
Accept-Language fr,fr-FR; q = 0.8,en-US; q = 0.5,en; q = 0.3
Host localhost:8182
原产地http:// localhost:8183
Referer http: //localhost:8183/static/test.html
User-Agent Mozilla / 5.0(X11; Ubuntu; Linux x86_64; rv:36.0)Gecko / 20100101 Firefox / 36.0

//响应
接受范围字节
Access-Control-Allow-Cred ... true
Access-Control-Allow-Orig ... http:// localhost:8183
Content-类型应用程序/ json
Date Fri,13 Mar 2015 09:16:48 GMT,Fri,13 Mar 2015 09:16:48 GMT
服务器Restlet-Framework / 2.3.1
Transfer-编码分块
Vary Accept-Charset,Accept-Encoding,Accept-Language,Accept



你可以看到,CORS存在; - )



希望它帮助你,
Thierry


I'm trying to set the 'Access-Control-Allow-Origin: *' header for the response. However, the header is not present. What am I doing wrong?

public class JsonApplication extends Application
{
    private static final String SERVER_URL = "http://localhost:8111";

    public static void main(String[] args) throws Exception 
    {
        Server testServer = new Server(Protocol.HTTP, 8111);        
        JsonApplication jsonApplication = new JsonApplication();

        CorsService corsService = new CorsService();         
        corsService.setAllowedOrigins( new HashSet(Arrays.asList("*")));
        corsService.setAllowedCredentials(true);

        jsonApplication.getServices().add( corsService );      

        testServer.setNext( jsonApplication );
        testServer.start();
    }

    @Override
    public Restlet createInboundRoot()
    {
        Router router = new Router( getContext() );
        router.attach( SERVER_URL + "/", RootResource.class );        
        return router;
    }
}

I checked the source code for org.restlet.engine.application.CorsResponseHelper and it contains the following code:

public void addCorsResponseHeaders(Request request, Response response) {

String origin = request.getHeaders().getFirstValue("Origin", true);

if (origin == null) {
    // Not a CORS request
    return;
}
...
}

So, it appears that the current CORS implementation does not support requests made from a local html-file, since in that case origin == null.

I added some logging to my servlet application:

JsonApplication::createInboundRoot()
16:26 MyCorsService()
16:26 myCorsService = wwwdbase.rest.cors.MyCorsService@6e1b241d
16:26 MyCorsService::setAllowedOrigins(), [*]
16:26 services: [org.restlet.service.TunnelService@4c88fe62, 
org.restlet.service.StatusService@68349a5b,
org.restlet.service.DecoderService@77cfd8d3,
org.restlet.service.EncoderService@40c331fb,
org.restlet.service.RangeService@4bb3bc6f,
org.restlet.service.ConnectorService@7990100,
org.restlet.service.ConnegService@e194860,
org.restlet.service.ConverterService@578cfcb1,
org.restlet.service.MetadataService@18a62eb,
org.restlet.service.TaskService@4ed4f2db,
wwwdbase.rest.cors.MyCorsService@6e1b241d]

We can see that MyCorsService is available. However, it is never called by the servlet framework. On the other hand, if I run the service (the Java SE version) from IDE, MyCorsService is called. Why do these cases behave differently?

Partial solution: I managed to add the allow origin header by changing the code in org.restlet.engine.header.HeaderUtils

if (response.getAccessControlAllowOrigin() != null) 
{          
    addHeader(HeaderConstants.HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
            response.getAccessControlAllowOrigin(), headers);
}

to

if (response.getAccessControlAllowOrigin() != null) 
{          
    addHeader(HeaderConstants.HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
            response.getAccessControlAllowOrigin(), headers);
}
else
{
    // --- Add in any case!
    //           
    response.setAccessControlAllowOrigin( "*" );
    addHeader(HeaderConstants.HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
                    response.getAccessControlAllowOrigin(), headers);            
}

However, the answer to the question why the servlet framework in Tomcat did not call the cors service is still unknown...

解决方案

In fact, you have correctly configured the CORS service of Restlet ;-)

In the context of CORS, there are two kinds of requests:

  • Simple requests. To be short, when you use methods GET, HEAD and some cases with POST. In this case, CORS headers aren't required when doing cross domain requests.
  • Preflighted requests The other cases where CORS headers are required to do cross domain requests.

So if you simply do a method GET, it's normal that you saw nothing. Try with a method POST with a JSON content and you will see the CORS headers.

For more details, you can have a look at this link:

Edited

I made a more complete test for your issue. I have two Restlet server launched on different ports (8182 for the resource to be accessed using AJAX, 8183 for the JS application that accesses the resource).

The first one is configured with your code:

CorsService corsService = new CorsService();         
corsService.setAllowedOrigins(new HashSet(Arrays.asList("*")));
corsService.setAllowedCredentials(true);

RestletApplication application = new RestletApplication();
application.getServices().add(corsService);
component.getDefaultHost().attachDefault(application);

The server resource in it is simple:

public class MyServerResource extends ServerResource {
    @Get
    public TestBean ping() {
        TestBean bean = new TestBean();
        bean.setMessage("pong");
        return bean;
    }
}

The second application only uses a Restlet directory to serve static content:

@Override
public Restlet createInboundRoot() {
    Router router = new Router(getContext());
    router.attach("/static", new Directory(
            getContext(), "clap:///test/static"));
    return router;
}

In addition to JQuery library, I added the following HTML file:

<html>
  <head>
    <script type="text/javascript" src="/static/jquery-1.11.2.min.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {
      $('#id1').click(function() {
        $.ajax({
           url : 'http://localhost:8182/ping',
           type : 'GET',
           success : function(result, status){
               console.log('ok = '+result);
           },
           error : function(result, status, error){
               console.log('error');
           },
           complete : function(result, status){
                console.log('complete');
           }
        });
      });
    });
    </script>
  </head>
  <body>
    <div id="id1">Click</div>
  </body>
</html>

Here is what I have when I clicked on the button "Click" at the header level:

// Request
Accept  */*
Accept-Encoding gzip, deflate
Accept-Language fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Host    localhost:8182
Origin  http://localhost:8183
Referer http://localhost:8183/static/test.html
User-Agent  Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0

// Response
Accept-Ranges   bytes
Access-Control-Allow-Cred...    true
Access-Control-Allow-Orig...    http://localhost:8183
Content-Type    application/json
Date    Fri, 13 Mar 2015 09:16:48 GMT, Fri, 13 Mar 2015 09:16:48 GMT
Server  Restlet-Framework/2.3.1
Transfer-Encoding   chunked
Vary    Accept-Charset, Accept-Encoding, Accept-Language, Accept

As you can see, the CORS are present ;-)

Hope it helps you, Thierry

这篇关于如何在Restlet 2.3.1中使用CORS?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆