Hi Jim! Thanks a lot for your detailed help! It helped a lot!
Best regards, On Sat, Dec 3, 2011 at 3:32 PM, Jim Winfield <j...@ewsystems.com> wrote: > I faced this same challenge for a project I was recently working on. > > The scenario is a Server side JSON API requiring cookie auth, implemented > in Restlet running on a sub domain being used by a web client hosted on a > separate sub-domain, or possibly a different domain and getting http 405 > errors. > > You will want to get a solid understanding of the http access control and > cross-origin sharing standard to understand how browsers support cross-site > requests. Read up here: > https://developer.mozilla.org/En/HTTP_access_control also > http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/has > good info. > > The browser will "pre-flight" any cross-site call to your resource URI > with a http options request and sends along info in the header for you to > decide on if the access should be allowed. Typically your restlet server > resource will not handle the http option method, so this is why you get the > 405 error returned to the browser. Once you add support for http options > requests to your resource you will need to properly set the access control > headers in the http response. > > Here's one way to support cross-origin requests with Restlet: > > - Provide a filter to handle http options requests. You'll add this filter > to individual restlet resources or you can filter all requests. The filter > saves you from having a base resource class or by supporting on a resource > by resource basis. But you can certainly do it either way. The filter can > also be turned on/off which may be another advantage. > > - This filter requires that there is some set of allowed origin domains > configured with the Restlet application. In my case they get injected via > Spring into a config class (MyConfig), but you can verify the origin domain > anyway you want. > > public class OriginFilter extends Filter { > > public OriginFilter(Context context) { > super(context); > } > > @Override > protected int beforeHandle(Request request, Response response) { > if(Method.OPTIONS.equals(request.getMethod())) { > Form requestHeaders = (Form) > request.getAttributes().get("org.restlet.http.headers"); > String origin = requestHeaders.getFirstValue("Origin", true); > > if(MyConfig.getAllowedOrigins().contains(origin)) { > Form responseHeaders = (Form) > response.getAttributes().get("org.restlet.http.headers"); > if (responseHeaders == null) { > responseHeaders = new Form(); > response.getAttributes().put("org.restlet.http.headers", > responseHeaders); > } > responseHeaders.add("Access-Control-Allow-Origin", origin); > responseHeaders.add("Access-Control-Allow-Methods", > "GET,POST,DELETE,OPTIONS"); > responseHeaders.add("Access-Control-Allow-Headers", > "Content-Type"); > responseHeaders.add("Access-Control-Allow-Credentials", "true"); > responseHeaders.add("Access-Control-Max-Age", "60"); > response.setEntity(new EmptyRepresentation()); > return SKIP; > } > } > > return super.beforeHandle(request, response); > } > > @Override > protected void afterHandle(Request request, Response response) { > if(!Method.OPTIONS.equals(request.getMethod())) { > Form requestHeaders = (Form) > request.getAttributes().get("org.restlet.http.headers"); > String origin = requestHeaders.getFirstValue("Origin", true); > > if(MyConfig.getAllowedOrigins().contains(origin)) { > Form responseHeaders = (Form) > response.getAttributes().get("org.restlet.http.headers"); > if (responseHeaders == null) { > responseHeaders = new Form(); > response.getAttributes().put("org.restlet.http.headers", > responseHeaders); > } > responseHeaders.add("Access-Control-Allow-Origin", origin); > responseHeaders.add("Access-Control-Allow-Methods", > "GET,POST,DELETE,OPTIONS"); > responseHeaders.add("Access-Control-Allow-Headers", > "Content-Type"); > responseHeaders.add("Access-Control-Allow-Credentials", "true"); > responseHeaders.add("Access-Control-Max-Age", "60"); > } > } > super.afterHandle(request, response); > } > } > > Then in your app, if you want to support cross-origin resource sharing for > all your routes ... > > @Override > public Restlet createInboundRoot() { > Router router = new Router(context); > // attach your resources ... > // router.attach(...); > OriginFilter originFilter = new OriginFilter(getContext()); > originFilter.setNext(router); > return originFilter; > } > > - For a http options request, the filter checks the http headers to see if > the "Origin" header value is from a known and trusted host that the > configuration class provides in the filter's beforeHandle() method. If you > don't need to process a http options request elsewhere, you can skip > processing and return the response headers. > > - The response headers you set for allow-methods, max-age, etc will depend > on your scenario, this sample filter hard codes values. > > - If you are making any requests that require authentication, like with > cookies you can't wildcard the origin value sent back in the response as > some examples typically show. The origin value passed back in the response > must agree with the origin value sent in the pre-flighted http options > request/response, and the origin value sent in the http request header > otherwise the browser will fail the xhr call. You must also set > allow-credentials to true. > > On the client side, if you're making ajax requests that require cookie > auth you must send the xhr withCredentials property to true. > > With jQuery: > > $.ajax({ > contentType: 'application/json', > type: 'POST', > url: 'http://sub.myappdomain.com/some/resource', > data: JSON.stringify({ > "some":"data", > "another":"value" > }), > success: function() { > alert("oh yeah!"); > }, > xhrFields:{ > withCredentials: true > }, > dataType: 'json', > }); > > > Working with a client-side debugger like Firebug to look at the traffic > and http requests and responses will help tremendously if you still are > having problems. > > This is one way to do it, if there is a better, or another recommended > way, I'm not aware of it. But this works for my particular project and > allows me to configure, enable and disable as I need to. Hope this helps > you and anyone else out that needs to get cross-origin requests working in > Restlet. > > > > Hi all, > > > > does anyone has some update about that? > > > > What is the recommend way to support cross-domain in Restlet 2 ? > > > > Best regards, > > ------------------------------------------------------ > > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2890203 > -- Danilo Rosetto Muñoz munozdan...@gmail.com http://br.linkedin.com/in/danilomunoz ------------------------------------------------------ http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2890966