JENA-1294
I've put in a fixed setup activated by "--cors" - I'd be obliged if
people would try it out and let us know if it works.
It's in the latest development build #1834.
Thanks
Andy
On 29/01/2020 11:28, Andy Seaborne wrote:
Barry - thanks for the report
On 28/01/2020 19:28, Nouwt, B. (Barry) wrote:
Hi all,
I enabled CORS on embedded Fuseki (when handling YASGUI SPARQL
requests) and wanted to share the way I did it for others' benefit. It
took me a while to figure out how to do this. I found instructions on
how to enable CORS via the web.xml, but the embedded Fuseki does not
use a web.xml (as far as I am aware). I also found a lot of examples
on how to add the CORS filter in Jetty when you control when filters
are added. The code at the end of the email enables it in my setup.
You are correct - Fuseki main is not a webapp, no war file.
Fuseki Full, a webapp, does put the CORS filter in.
I thought that servlet filters got added before the Fuseki main filter
but it sounds like that is not your experience. That would be a bug.
Could you file a JIRA please? As your code show, getting the order right
is ... a bit opaque.
The complication is that the Fuseki filter catches "/*" (any URL)
because the valid names can change as datasets are added to registry
which is possible at run time.
It might need both "before" and "after" filters.
And/or : It might be a good idea to have an "enableCORS" setting to the
Fuseki Server builder which will need its own configuration.
Andy
Some remarks:
- as far as I could see, Fuseki builder does not allow custom filters
to be chained/configured before the FusekiFilter (which intercepts all
traffic to datasets).
- adding the CORS filter after the FusekiFilter does not work in case
of a SPARQL request to a particular dataset, because FusekiFilter
intercepts its and prevents it from continuing through the filter chain.
- the above two remarks forced me to add the CORS filter directly to
the Jetty Server, however, it does not allow insertion of filters
before other filters, it only supports adding it to the end of the chain.
- After succeeding to add my filter before the FusekiFilter, it still
did not work, because (after some searching) a FilterMapping (to a
particular path) is also required.
- So, the not so elegant code below retrieves both the filters and the
filtermappings and inserts the filter (and filtermapping) before the
FusekiFilter.
Maybe someone can check whether there is an easier way to enable it
and hopefully it saves somebody a few hours in the future!
Regards, Barry
----------- code to enable CORS for embedded fuseki (note that this
code is not directly runnable)------------------------------
//... configure server through builder ...
server = builder.build();
Server jettyServer = server.getJettyServer();
/*
* trying to add the cross origin filter. Fuseki adds its
FusekiFilter as the
* first and this one consumes a SPARQL request to a particular
dataset. So, to
* be able to add the cross origin filter, we have to add it BEFORE the
* FusekiFilter. This is not as easy as it looks, because you need to
add the
* filter as a filter and as a filtermapping to the /* pathspec.
*/
Handler handler = jettyServer.getHandler();
FilterHolder holder = new FilterHolder(CrossOriginFilter.class);
// we use the default CrossOriginFilter settings, but you can specify
them.
//holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
//holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER,
"*");
//holder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM,
"GET,POST,HEAD,OPTIONS");
// holder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM,
// "X-Requested-With,Content-Type,Accept,Origin");
assert (handler instanceof ServletContextHandler);
ServletContextHandler h = (ServletContextHandler) handler;
ServletHandler servletHandler = h.getServletHandler();
List<FilterMapping> mappings = new
ArrayList<FilterMapping>(Arrays.asList(servletHandler.getFilterMappings()));
List<FilterHolder> holders = new
ArrayList<FilterHolder>(Arrays.asList(servletHandler.getFilters()));
FilterMapping mapping = new FilterMapping();
mapping.setFilterName(holder.getName());
mapping.setPathSpec("/*");
mapping.setDispatcherTypes(EnumSet.of(DispatcherType.REQUEST));
mappings.add(0, mapping);
holders.add(0, holder);
FilterMapping[] mappings3 = new FilterMapping[mappings.size()];
mappings3 = mappings.toArray(mappings3);
FilterHolder[] holders3 = new FilterHolder[holders.size()];
holders3 = holders.toArray(holders3);
servletHandler.setFilters(holders3);
servletHandler.setFilterMappings(mappings3);
server.start();
This message may contain information that is not intended for you. If
you are not the addressee or if this message was sent to you by
mistake, you are requested to inform the sender and delete the
message. TNO accepts no liability for the content of this e-mail, for
the manner in which you use it and for damage of any kind resulting
from the risks inherent to the electronic transmission of messages.