Custom ServletFilterHolder for CORS Headers not working

327 views
Skip to first unread message

Andrew Serff

unread,
Apr 16, 2015, 4:26:33 PM4/16/15
to druid...@googlegroups.com
Hello,

After a suggestion from Eric Tschetter over on this thread (https://groups.google.com/forum/#!topic/druid-development/y01WJAp-UBc), I've started to make a CORS Servlet Filter but I'm having trouble making it work.  I've created my module and added it to druid and I even see druid load it in the logs, but it seems like my filter is never used. I am not 100% sure I set everything up right though, especially the Path and DispatcherTypes in the ServletFilterHolder.  Here is what I have so far:

The DruidModule:

public class CORSFilterExtension implements DruidModule {

    @Override
    public List<? extends Module> getJacksonModules() {
        return ImmutableList.of();
    }

    @Override
    public void configure(Binder binder) {
        Multibinder<ServletFilterHolder> multibinder = Multibinder.newSetBinder(binder, ServletFilterHolder.class);
        multibinder.addBinding().to(SimpleCORSServletFilterHolder.class);
    }

}

The SimpleCORSServletFilterHolder:

public class SimpleCORSServletFilterHolder implements ServletFilterHolder {

    public SimpleCORSServletFilterHolder() {
    }
    
    @Override
    public Filter getFilter() {
        return new SimpleCORSServletFilter();
    }

    @Override
    public Class<? extends Filter> getFilterClass() {
        return SimpleCORSServletFilter.class;
    }

    @Override
    public Map<String, String> getInitParameters() {
        Map<String, String> initParams = new HashMap<>();
        return initParams;
    }

    @Override
    public String getPath() {
        return "/*";
    }

    @Override
    public EnumSet<DispatcherType> getDispatcherType() {
        return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC);
    }
    
}


And the SimpleCORSServletFilter:
public class SimpleCORSServletFilter implements Filter {

    private static final Logger log = Logger.getLogger(SimpleCORSServletFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.info("Adding Access Control Response Headers");
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, HEAD, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

After deploying this, I have a webapp that is trying to submit an AJAX POST to the Broker's API @ /druid/v2/?pretty but I get the error:

XMLHttpRequest cannot load http://192.168.59.103:8084/druid/v2/?pretty. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:1337' is therefore not allowed access. The response had HTTP status code 500.

In the druid logs I just see an exception about an invalid query:

druid_1     | 2015-04-16 20:20:57,466 DEBG 'druid-realtime' stdout output:
druid_1     | 2015-04-16T20:20:57,464 WARN [qtp1458958776-35] io.druid.server.QueryResource - Exception occurred on request [unparsable query]
druid_1     | com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
druid_1     |  at [Source: HttpInputOverHTTP@229757c0; line: 1, column: 1]
druid_1     | at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148) ~[druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3110) ~[druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3051) ~[druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2207) ~[druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at io.druid.server.QueryResource.doPost(QueryResource.java:133) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_76]
druid_1     | at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_76]
druid_1     | at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_76]
druid_1     | at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_76]
druid_1     | at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:302) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1511) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1442) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1391) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1381) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:278) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:268) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:180) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:93) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:120) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.GuiceFilter$1.call(GuiceFilter.java:132) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.GuiceFilter$1.call(GuiceFilter.java:129) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.GuiceFilter$Context.call(GuiceFilter.java:206) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:129) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:364) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1125) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1059) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:52) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.Server.handle(Server.java:497) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:248) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:620) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:540) [druid-services-0.7.1.1-selfcontained.jar:0.7.1.1]
druid_1     | at java.lang.Thread.run(Thread.java:745) [?:1.7.0_76]


And I never see the log statement from my servlet.  So it seems to load my extension, but maybe never register it? Or maybe I need to change the path or something? Oh an I am running 0.7.1.1.  Any help with what I'm doing wrong would be great!

Thanks
Andrew

Nishant Bangarwa

unread,
Apr 17, 2015, 9:57:39 AM4/17/15
to Andrew Serff, druid...@googlegroups.com
Hi Andrew, 
I am not very familiar with filters but you can have a look at DumyAuthFilter in BasicJettyTest  as an example of working filter. 
Another example in druid code base if RedirectFilter. 
 

--
You received this message because you are subscribed to the Google Groups "Druid User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to druid-user+...@googlegroups.com.
To post to this group, send email to druid...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/druid-user/26cc4833-c7f5-4efb-b3ea-7142899cefcb%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Andrew Serff

unread,
Apr 17, 2015, 12:51:12 PM4/17/15
to druid...@googlegroups.com, and...@serff.net
I figured it out and it was a "DOH!" moment.  I forgot to include the META-INF/services property file so it was never loading my module...

Thanks for the examples to look at though.  They at least got me to fix a few things.  Thanks!

Andrew

Deepak Jain

unread,
Jan 28, 2016, 8:40:40 PM1/28/16
to Druid User, and...@serff.net
Andrew,
Can you share the piece of code and how to integrate into Druid.
Or was it made part of Druid core ?

I am facing the same error.

Regards,
Deepak

Deepak Jain

unread,
Jan 28, 2016, 9:17:50 PM1/28/16
to Druid User, and...@serff.net
I created a DruidModule and see it working now. After several hours of beating the bush :)

Andrew Serff

unread,
Jan 29, 2016, 9:50:27 AM1/29/16
to Druid User, and...@serff.net
Sorry I didn't see this eariler, but I did open source the filter we were using:


Might be too late, but feel free to check it out!

Andrew

Shashank NS

unread,
Apr 2, 2020, 10:16:17 AM4/2/20
to Druid User
Hi,

I was following this thread closely for CORS error facing while querying druid from browser.

I was able to perform below steps:

1. Loaded the cors filter extension  with below command

java \
  -cp "lib/*" \
  -Ddruid.extensions.directory="extensions" \
  -Ddruid.extensions.hadoopDependenciesDir="hadoop-dependencies" \
  org.apache.druid.cli.Main tools pull-deps \
  --no-default-hadoop \
  -c "net.acesinc.druid.extensions:cors-servlet-filter:1.0.0"

2. This created a new extension cors-servlet-filter in extensions folder with related jars

3. I set the below field option to true
druid.auth.allowUnauthenticatedHttpOptions

4. I was able to start the druid cluster successfully

I still see CORS error while querying data 

Could you help me out here if i am missing any step

Andrew Serff

unread,
Apr 2, 2020, 12:12:09 PM4/2/20
to druid...@googlegroups.com
Hi Shashank, What version of Druid are you trying to use it with? Someone else reported a bug with it not working in the latest. I think the extension refactor in 0.9 broke our extension and haven't have a chance to fix it.  You can see the issue here: https://github.com/everwatchsolutions/druid-cors-filter-extension/issues/3

--
You received this message because you are subscribed to a topic in the Google Groups "Druid User" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/druid-user/JF9L8-UZy3A/unsubscribe.
To unsubscribe from this group and all its topics, send an email to druid-user+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/druid-user/8fbacf3f-8bf8-4593-95ea-d7f64f1adf44%40googlegroups.com.
Message has been deleted

Shashank NS

unread,
Apr 2, 2020, 12:49:14 PM4/2/20
to Druid User
Hi Andrew,

Im using with 0.15.0 version. I dont see any exceptions after integrating with cors filter though.

Regards
Shashank

To unsubscribe from this group and all its topics, send an email to druid...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages