|
From: Patrick B. <pa...@te...> - 2013-06-02 05:09:09
|
I'm having a lot of trouble trying to set the appropriate CORS headers from
a browser OPTIONS request.
I'm trying to POST a form using the browser FormData and the browser is
calling server-side with OPTIONS before it does the POST:
I'm calling a URL of the form:
http://host/myapplication/import/list
Where I know RESTEasy is handling all paths underneath myapplication since
I have other GETmethods that work properly.
When I send my POSTed FormData from browser the browser requests the URL
http://host/myapplication/import/list with an HTTP method of OPTIONS and I
get this exception server-side:
Failed executing OPTIONS /import/list:
org.jboss.resteasy.spi.DefaultOptionsMethodException: No resource method
found for options, return OK with Allow header
--- ---
Here are the questions I'm trying to answer followed by a detailed
breakdown of what I'm currently trying:
1. Is there a recommended way to handle CORS request that is a "standard"
part of REST Easy?
2. Why doesn't my PostProcessInterceptor work for OPTIONS methods?
3. Is it possible to make a single handler for any OPTIONS method for any
path? (I thought my @Path mapping below might do it ...)
4. Not that it is a great solution to my CORS issue, but why doesn't my
ExceptionMapper get called?
--- ---
I'm trying to handle setting the CORS headers in 2 different ways.
FIRST:
@Provider
@ServerInterceptor
@Precedence("HEADER_DECORATOR")
public class CORSInterceptor
implements PostProcessInterceptor, RESTInterfaceV1
{
@Override
public void postProcess(ServerResponse response)
{
MultivaluedMap<String, Object> headers = response.getMetadata();
if (!headers.containsKey(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER))
{
headers.add(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
}
}
}
Registered via web.xml:
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>packagename.CORSInterceptor</param-value>
</context-param>
SECOND:
@Stateless
@Path("/")
public class CORSInterceptorForOptions
implements RESTInterfaceV1
{
@javax.ws.rs.core.Context
HttpServletRequest servletRequest;
@OPTIONS
@Path("/{path:.*}")
public Response handleCORSRequest()
{
final ResponseBuilder retValue = Response.ok();
String requestHeaders =
servletRequest.getHeader(ACCESS_CONTROL_REQUEST_HEADERS);
if (requestHeaders != null)
{
retValue.header(ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders);
}
String requestMethod =
servletRequest.getHeader(ACCESS_CONTROL_REQUEST_METHOD);
if (requestMethod != null)
{
retValue.header(ACCESS_CONTROL_ALLOW_METHODS, requestMethod);
}
return retValue.build();
}
}
Added to classes for my RESTEasy application:
public class MyApplication
extends Application
{
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public MyApplication()
{
// Geocoder
classes.add(CORSInterceptorForOptions.class);
}
@Override public Set<Class<?>> getClasses() { return classes; } @Override
public Set<Object> getSingletons() { return singletons; }
}
--- ---
While trying to solve this problem from all different angles I've also
tried creating an Exception mapper:
@Provider
public class CORSInterceptorOptionsException
implements ExceptionMapper<DefaultOptionsMethodException>, RESTInterfaceV1
{
@javax.ws.rs.core.Context
HttpServletRequest servletRequest;
@OPTIONS
@Path("/{path:.*}")
public static Response handleCORSRequest(HttpServletRequest servletRequest)
{
final ResponseBuilder retValue = Response.ok();
String requestHeaders =
servletRequest.getHeader(ACCESS_CONTROL_REQUEST_HEADERS);
if (requestHeaders != null)
{
retValue.header(ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders);
}
String requestMethod =
servletRequest.getHeader(ACCESS_CONTROL_REQUEST_METHOD);
if (requestMethod != null)
{
retValue.header(ACCESS_CONTROL_ALLOW_METHODS, requestMethod);
}
return retValue.build();
}
@Override
public Response toResponse(DefaultOptionsMethodException e)
{
return handleCORSRequest(servletRequest);
}
}
And adding that to the comma seperated list of resteasy.providers in
web.xml like so:
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>com.terraura.missionterminal.interceptor.CORSInterceptor,com.terraura.missionterminal.interceptor.CORSInterceptorOptionsException</param-value>
</context-param>
Which also does nothing.
|
|
From: Bill B. <bb...@re...> - 2013-06-03 15:30:56
|
On 6/2/2013 12:08 AM, Patrick Bakker wrote: > I'm having a lot of trouble trying to set the appropriate CORS headers > from a browser OPTIONS request. > I'm trying to POST a form using the browser FormData and the browser is > calling server-side with OPTIONS before it does the POST: > > I'm calling a URL of the form: > > http://host/myapplication/import/list > > Where I know RESTEasy is handling all paths underneath myapplication > since I have other GETmethods that work properly. > When I send my POSTed FormData from browser the browser requests the URL > http://host/myapplication/import/list with an HTTP method of OPTIONS and > I get this exception server-side: > > Failed executing OPTIONS /import/list: > org.jboss.resteasy.spi.DefaultOptionsMethodException: No resource method > found for options, return OK with Allow header > This isn't a failure. This exception implements the default OPTIONS behavior if there is no method supporting @OPTIONS > --- --- > > Here are the questions I'm trying to answer followed by a detailed > breakdown of what I'm currently trying: > > 1. Is there a recommended way to handle CORS request that is a > "standard" part of REST Easy? We have nothing. If you have suggestions, please detail it in a JIRA so we can implement it. Or contribute it if you have time. > 2. Why doesn't my PostProcessInterceptor work for OPTIONS methods? I assume you are on 2.3.x? This is because PostProcessorInterceptor does not get called when there is an exception. Write an ExceptionMapper for DefaultOptionsMethodException. > 3. Is it possible to make a single handler for any OPTIONS method for > any path? (I thought my @Path mapping below might do it ...) Write an ExceptionMapper for DefaultOptionsMethodException. > 4. Not that it is a great solution to my CORS issue, but why doesn't my > ExceptionMapper get called? > Don't know. The ExceptionMapper should work. If this is a Resteasy 3.x problem, then report a JIRA and we can get to it in the next couple of days/weeks. For 2.3.x problems, sorry, but we're 100% focused on getting Resteasy 3.0 out for the next few months and we're only fixing customer problems for 2.3.x. -- Bill Burke JBoss, a division of Red Hat http://bill.burkecentral.com |
|
From: Brian M. <bri...@gm...> - 2013-06-03 15:44:33
|
I've fought CORS stuff too with RestEasy. I ended up with a ServletFilter in front of RestEasy that gobbles up the OPTIONS calls. On Jun 3, 2013, at 10:30 AM, Bill Burke <bb...@re...> wrote: > > > On 6/2/2013 12:08 AM, Patrick Bakker wrote: >> I'm having a lot of trouble trying to set the appropriate CORS headers >> from a browser OPTIONS request. >> I'm trying to POST a form using the browser FormData and the browser is >> calling server-side with OPTIONS before it does the POST: >> >> I'm calling a URL of the form: >> >> http://host/myapplication/import/list >> >> Where I know RESTEasy is handling all paths underneath myapplication >> since I have other GETmethods that work properly. >> When I send my POSTed FormData from browser the browser requests the URL >> http://host/myapplication/import/list with an HTTP method of OPTIONS and >> I get this exception server-side: >> >> Failed executing OPTIONS /import/list: >> org.jboss.resteasy.spi.DefaultOptionsMethodException: No resource method >> found for options, return OK with Allow header >> > > This isn't a failure. This exception implements the default OPTIONS > behavior if there is no method supporting @OPTIONS > >> --- --- >> >> Here are the questions I'm trying to answer followed by a detailed >> breakdown of what I'm currently trying: >> >> 1. Is there a recommended way to handle CORS request that is a >> "standard" part of REST Easy? > > We have nothing. If you have suggestions, please detail it in a JIRA so > we can implement it. Or contribute it if you have time. > >> 2. Why doesn't my PostProcessInterceptor work for OPTIONS methods? > > I assume you are on 2.3.x? This is because PostProcessorInterceptor > does not get called when there is an exception. Write an > ExceptionMapper for DefaultOptionsMethodException. > >> 3. Is it possible to make a single handler for any OPTIONS method for >> any path? (I thought my @Path mapping below might do it ...) > > Write an ExceptionMapper for DefaultOptionsMethodException. > >> 4. Not that it is a great solution to my CORS issue, but why doesn't my >> ExceptionMapper get called? >> > > Don't know. The ExceptionMapper should work. If this is a Resteasy 3.x > problem, then report a JIRA and we can get to it in the next couple of > days/weeks. For 2.3.x problems, sorry, but we're 100% focused on > getting Resteasy 3.0 out for the next few months and we're only fixing > customer problems for 2.3.x. > > > -- > Bill Burke > JBoss, a division of Red Hat > http://bill.burkecentral.com > > ------------------------------------------------------------------------------ > Get 100% visibility into Java/.NET code with AppDynamics Lite > It's a free troubleshooting tool designed for production > Get down to code-level detail for bottlenecks, with <2% overhead. > Download for free and get started troubleshooting in minutes. > http://p.sf.net/sfu/appdyn_d2d_ap2 > _______________________________________________ > Resteasy-developers mailing list > Res...@li... > https://lists.sourceforge.net/lists/listinfo/resteasy-developers |