24

I'm working on a dropwizard application and js ui to interacte with the api. I need to load json data to update views but I have to enable cors in dropwizard before that. I did some staff but it seems not working because dropwizard returns allways 204 no content.

@Override
public void run(final BGConfiguration configuration, final Environment environment) throws Exception {
  final Map<String, String> params = new HashMap<>();
  params.put("Access-Control-Allow-Origin", "/*");
  params.put("Access-Control-Allow-Credentials", "true");
  params.put("Access-Control-Expose-Headers", "true");
  params.put("Access-Control-Allow-Headers", "Content-Type, X-Requested-With");
  params.put("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
  environment.servlets().addFilter("cors", CrossOriginFilter.class).setInitParameters(params);
}
naslami
  • 345
  • 2
  • 4
  • 12

4 Answers4

69

The bug here is that the filter hasn't been configured with a URL path via the addMappingForUrlPatterns method.

This worked for me using dropwizard 0.7.1:

import org.eclipse.jetty.servlets.CrossOriginFilter;
import javax.servlet.DispatcherType;
import java.util.EnumSet;

public void run(Configuration conf, Environment environment)  {
    // Enable CORS headers
    final FilterRegistration.Dynamic cors =
        environment.servlets().addFilter("CORS", CrossOriginFilter.class);

    // Configure CORS parameters
    cors.setInitParameter("allowedOrigins", "*");
    cors.setInitParameter("allowedHeaders", "X-Requested-With,Content-Type,Accept,Origin");
    cors.setInitParameter("allowedMethods", "OPTIONS,GET,PUT,POST,DELETE,HEAD");

    // Add URL mapping
    cors.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
}

I'm assuming you're testing this live in a browser, but you can verify via CLI with a curl command like this:

$ curl -H "Origin: http://example.com" \
       -H "Access-Control-Request-Method: POST" \
       -H "Access-Control-Request-Headers: X-Requested-With" \
       -X OPTIONS --verbose \
       http://localhost:8080

You should see a bunch of Access-Control-* HTTP headers in the response.

Mike Clarke
  • 873
  • 7
  • 6
  • 3
    Its a good idea to add Authorization in the headers as well if you are using that – Shervin Asgari Dec 23 '14 at 09:42
  • @Mike Clarke Wish I saw your comment earlier. Necessary with AngularJS – neric Aug 03 '15 at 19:27
  • For dropwizard 0.8.4 we needed to set "allowedHeaders" to "*" in order to make it work in AngularJS application. – Ivan Marjanovic Nov 24 '15 at 20:18
  • 5
    Just an FYI for folks who are using this with GWT, I had to set "allowedHeaders" to "*" as well. Without it, GWT would complain `Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9876' is therefore not allowed access.` – atlantis Mar 13 '16 at 20:32
  • Don't forget `import javax.servlet.FilterRegistration;` – BYTE RIDER Aug 21 '17 at 15:44
  • worked like charm for my UI development server. – Wadi Diaz-wong Apr 12 '21 at 05:08
15

Adding to Mike Clarke's answer:

Setting the CHAIN_PREFLIGHT_PARAM to false will let this filter handle preflight requests without your authentication filters intercepting what would be a 200 response and turning them into unauthorized / forbidden.

import org.eclipse.jetty.servlets.CrossOriginFilter;
import javax.servlet.DispatcherType;
import java.util.EnumSet;

public void run(Configuration conf, Environment environment)  {
    // Enable CORS headers
    final FilterRegistration.Dynamic cors =
        environment.servlets().addFilter("CORS", CrossOriginFilter.class);

    // Configure CORS parameters
    cors.setInitParameter("allowedOrigins", "*");
    cors.setInitParameter("allowedHeaders", "X-Requested-With,Content-Type,Accept,Origin");
    cors.setInitParameter("allowedMethods", "OPTIONS,GET,PUT,POST,DELETE,HEAD");

    // Add URL mapping
    cors.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");

    // DO NOT pass a preflight request to down-stream auth filters
    // unauthenticated preflight requests should be permitted by spec
    cors.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, Boolean.FALSE.toString());
}

I was surprised that I didn't find any examples on the interwebs that included this configuration. Spent a few days trying to figure this out.

Jimi
  • 901
  • 7
  • 11
3

For me even after configuring the above, it was not working. Ultimately it turned out that i have to also allow cache-control headers.

filter.setInitParameter("allowedHeaders",
"Cache-Control,If-Modified-Since,Pragma,Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");
Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
Atul Soman
  • 4,612
  • 4
  • 30
  • 45
0

you can try doing this:

final FilterRegistration.Dynamic cors =
        environment.servlets().addFilter("CORS", CrossOriginFilter.class);

// Configure CORS parameters
// Configure CORS parameters
cors.setInitParameter("allowedOrigins", "*");
cors.setInitParameter("allowedHeaders", “<Headers>”);
cors.setInitParameter("allowedMethods", "OPTIONS,GET,PUT,POST,");

// Add URL mapping
cors.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");