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

Reply via email to