You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Jeff Wang <je...@plutom.com> on 2011/09/12 09:33:48 UTC

CORS Interceptor/Filter/Endpoint?

(different contract, same CXF...)

Ok, I've got a simple REST Endpoint


@Path("/foo")
@Post
@Consumes("multipart/form-data")
public Object registerFoo(@FormParam String name);

Now the issue that I have is that the people calling it are actually calling
the endpoint from a mobile phone app via an AJAX call.  This means that CORS
is going to come in play.  In other words, I'm going to get a preflight
request. (For more information, the good folks at Mozilla has a nice
description. https://developer.mozilla.org/En/HTTP_access_control)

This means, I will get a

OPTIONS /foo
Origin: http://mobile.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-BAR-HEADER

which will expect something to the effect of:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://mobile.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-BAR-HEADER
Access-Control-Max-Age: 1728000

before the actual POST will happen.  Have anyone implemented cross origin
resource sharing on CXF? I see 3 ways of doing this.

1) add @Options on to the endpoint.  (or create an endpoint with
@Path("/foo") @Options) and return the appropriate headers.  the drawback is
that I have to do this for each Endpoint.
2) add a filter that works on CXFServlet, and in the doFilter, check it's an
Options call, and then based upon the endpoint, set the appropriate header.
The problem is that the call should not actually reach CXFServlet, because
the OPTIONS method isn't anywhere, so CXF will (eventually) return a 404.
Whereas I should just set the return headers, and terminate the filter
chain.
3) the same as 2, but use an CXF InInterceptor instead of a filter.

I've been working on method 2, because there's already someone that wrote a
filter (http://software.dzhuvinov.com/cors-filter.html).  I have had
difficulties in getting it to work though.  I could see the headers getting
set, but when I return from the doFilter (instead of calling
chain.doFilter(request, response), all I get is a 200 OK but none of the
extra headers.  Letting the call keep on going to CXF (by calling
chain.doFilter) results in a 404.  So that's not a good thing either.

Any pointers on approahces would be much appreciated.

Jeff Wang

Re: CORS Interceptor/Filter/Endpoint?

Posted by jasminadesai <ja...@yahoo.com>.
Hi Jeff,

Although this post is from 2011, I would like to know if you did find a
solution for the problem?
I am facing a similar problem and would appreciate if you let me know if you
found any solution?

Regards,
Jasmina



--
View this message in context: http://cxf.547215.n5.nabble.com/CORS-Interceptor-Filter-Endpoint-tp4793366p5731618.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: CORS Interceptor/Filter/Endpoint?

Posted by Jeff Wang <je...@plutom.com>.
More updates on my adventures with CORS.

I have not tried an InInterceptor yet.

Using the Filtering method
1) If I call  chain.dofilter(...) and also add a @Options annotation
on each service then the call hits the CXF servlet but the query param
and form params are empty, which is as expected.  So if we go with
this route, defensive programming is required.  But on a 200 return,
the header are set properly. (this is at least reasonably workable)
Without an @Options on the service, we get a 404.  Not good.

2) If I don't call chain.doFilter(...) the headers disappear.  Not
really sure why.  But we don't need to defensively program, as the
filter does not continue to the CXFServlet.

Using the annotation method (@Options @Path("/user"))
1) the main problem here is any path parameters.  For example,
@Path("/user/{id}") as the endpoint will not be able to match the
above path.  This is a little annoying, as I'll need @Paths for all
the possible permutations.  Is there a way to do @Path("/user/*") or
something?

So far, none of the methods I've tried are working out very well,
although the filtering thing at least returned a valid CORS response
to the pre-flight call.  Next steps, probably explore the
InInterceptor idea.

Jeff

On Mon, Sep 12, 2011 at 2:43 AM, Sergey Beryozkin <sb...@gmail.com> wrote:
> Hi Jeff
>
> On 12/09/11 08:33, Jeff Wang wrote:
>>
>> (different contract, same CXF...)
>>
>> Ok, I've got a simple REST Endpoint
>>
>>
>> @Path("/foo")
>> @Post
>> @Consumes("multipart/form-data")
>> public Object registerFoo(@FormParam String name);
>>
>> Now the issue that I have is that the people calling it are actually
>> calling
>> the endpoint from a mobile phone app via an AJAX call.  This means that
>> CORS
>> is going to come in play.  In other words, I'm going to get a preflight
>> request. (For more information, the good folks at Mozilla has a nice
>> description. https://developer.mozilla.org/En/HTTP_access_control)
>>
>> This means, I will get a
>>
>> OPTIONS /foo
>> Origin: http://mobile.example
>> Access-Control-Request-Method: POST
>> Access-Control-Request-Headers: X-BAR-HEADER
>>
>> which will expect something to the effect of:
>>
>> HTTP/1.1 200 OK
>> Access-Control-Allow-Origin: http://mobile.example
>> Access-Control-Allow-Methods: POST, GET, OPTIONS
>> Access-Control-Allow-Headers: X-BAR-HEADER
>> Access-Control-Max-Age: 1728000
>>
>> before the actual POST will happen.  Have anyone implemented cross origin
>> resource sharing on CXF? I see 3 ways of doing this.
>>
>> 1) add @Options on to the endpoint.  (or create an endpoint with
>> @Path("/foo") @Options) and return the appropriate headers.  the drawback
>> is
>> that I have to do this for each Endpoint.
>
> if all the endpoints can be accessed at "/foo", then may be you can
> introduce an abstract class which will only implement @Options...
>
>> 2) add a filter that works on CXFServlet, and in the doFilter, check it's
>> an
>> Options call, and then based upon the endpoint, set the appropriate
>> header.
>> The problem is that the call should not actually reach CXFServlet, because
>> the OPTIONS method isn't anywhere, so CXF will (eventually) return a 404.
>> Whereas I should just set the return headers, and terminate the filter
>> chain.
>> 3) the same as 2, but use an CXF InInterceptor instead of a filter.
>>
>> I've been working on method 2, because there's already someone that wrote
>> a
>> filter (http://software.dzhuvinov.com/cors-filter.html).  I have had
>> difficulties in getting it to work though.  I could see the headers
>> getting
>> set, but when I return from the doFilter (instead of calling
>> chain.doFilter(request, response), all I get is a 200 OK but none of the
>> extra headers.  Letting the call keep on going to CXF (by calling
>> chain.doFilter) results in a 404.  So that's not a good thing either.
>>
> May be that filter is not dealing with HTTPServletResponse correctly, and
> thus the headers are dropped.
> Using CXF JAX-RS filter should work OK - they are allowed to run even if no
> matching resource operation has been found
>
> Cheers, Sergey
>
>> Any pointers on approahces would be much appreciated.
>>
>> Jeff Wang
>>
>
>

Re: CORS Interceptor/Filter/Endpoint?

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Jeff

On 12/09/11 08:33, Jeff Wang wrote:
> (different contract, same CXF...)
>
> Ok, I've got a simple REST Endpoint
>
>
> @Path("/foo")
> @Post
> @Consumes("multipart/form-data")
> public Object registerFoo(@FormParam String name);
>
> Now the issue that I have is that the people calling it are actually calling
> the endpoint from a mobile phone app via an AJAX call.  This means that CORS
> is going to come in play.  In other words, I'm going to get a preflight
> request. (For more information, the good folks at Mozilla has a nice
> description. https://developer.mozilla.org/En/HTTP_access_control)
>
> This means, I will get a
>
> OPTIONS /foo
> Origin: http://mobile.example
> Access-Control-Request-Method: POST
> Access-Control-Request-Headers: X-BAR-HEADER
>
> which will expect something to the effect of:
>
> HTTP/1.1 200 OK
> Access-Control-Allow-Origin: http://mobile.example
> Access-Control-Allow-Methods: POST, GET, OPTIONS
> Access-Control-Allow-Headers: X-BAR-HEADER
> Access-Control-Max-Age: 1728000
>
> before the actual POST will happen.  Have anyone implemented cross origin
> resource sharing on CXF? I see 3 ways of doing this.
>
> 1) add @Options on to the endpoint.  (or create an endpoint with
> @Path("/foo") @Options) and return the appropriate headers.  the drawback is
> that I have to do this for each Endpoint.

if all the endpoints can be accessed at "/foo", then may be you can 
introduce an abstract class which will only implement @Options...

> 2) add a filter that works on CXFServlet, and in the doFilter, check it's an
> Options call, and then based upon the endpoint, set the appropriate header.
> The problem is that the call should not actually reach CXFServlet, because
> the OPTIONS method isn't anywhere, so CXF will (eventually) return a 404.
> Whereas I should just set the return headers, and terminate the filter
> chain.
> 3) the same as 2, but use an CXF InInterceptor instead of a filter.
>
> I've been working on method 2, because there's already someone that wrote a
> filter (http://software.dzhuvinov.com/cors-filter.html).  I have had
> difficulties in getting it to work though.  I could see the headers getting
> set, but when I return from the doFilter (instead of calling
> chain.doFilter(request, response), all I get is a 200 OK but none of the
> extra headers.  Letting the call keep on going to CXF (by calling
> chain.doFilter) results in a 404.  So that's not a good thing either.
>
May be that filter is not dealing with HTTPServletResponse correctly, 
and thus the headers are dropped.
Using CXF JAX-RS filter should work OK - they are allowed to run even if 
no matching resource operation has been found

Cheers, Sergey

> Any pointers on approahces would be much appreciated.
>
> Jeff Wang
>