-1

In my Spring Boot app where I am using Jersey, I have the following cors filter setup:

@Provider
@Component
@ConfigurationProperties(prefix = "admin")
public class CorsFilter implements ContainerResponseFilter {

    private static final Logger LOGGER = LogManager.getLogger(CorsFilter.class);

    private List<String> accessControlAllowOrigin;

    @Override
    public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) {
        allowAccessOrigin(containerRequestContext, containerResponseContext);
        containerResponseContext.getHeaders().add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "origin, content-type, accept, authorization");
        containerResponseContext.getHeaders().add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        containerResponseContext.getHeaders().add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }

    // it sets the origin from the header if the setup contains '*' or the exact same origin from the request headers
    private void allowAccessOrigin(ContainerRequestContext containerRequestContext, final ContainerResponseContext containerResponseContext) {
        accessControlAllowOrigin.stream().filter(allowedOrigin -> 
                allowedOrigin.equals("*") 
                || allowedOrigin.equals(containerRequestContext.getHeaders().getFirst(HttpHeaders.ORIGIN))
            .findFirst().ifPresent(
                allowedOrigin -> containerResponseContext.getHeaders().add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, containerRequestContext.getHeaders().getFirst(HttpHeaders.ORIGIN)));
    }

    public List<String> getAccessControlAllowOrigin() {
        return accessControlAllowOrigin;
    }

    public void setAccessControlAllowOrigin(List<String> accessControlAllowOrigin) {
        this.accessControlAllowOrigin = accessControlAllowOrigin;
    }

}

The application.yml contains the "admin" config as this:

admin:
  access-control-allow-origin:
    - "http://10.8.235.222:4200"
    - "http://localhost:4200"

For the Jersey I set up like this:

@Component
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        packages("com.my.app.ws.endpoint");
        register(CorsFilter.class);
    }

}

When I am calling an endpoint which is in the registered package, similar like this:

@Controller
@Path("/user")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class UserEndPoint {

    private static final Logger LOGGER = LogManager.getLogger(UserCandidatesEndPoint.class);

    @Context
    UriInfo uriInfo;

    private final UserService userService;

    public UserEndPoint(final UserService userService) {
        this.userService = userService;
    }

    @GET
    @Path(/{userEmail})
    @Consumes({MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON})
    public Response getUserCandidate(@PathParam("userEmail") final String userEmail) {
        UserDto user = userService.getUserByEmail(userEmail);
        return Response.ok().entity(user).build();
    }
}

If I test the api with postman, it works fine!

If I connect via an Angular app with a browser, I get the following error:

Access to XMLHttpRequest at 'http://10.8.235.222:8081/myapp/user/jo@gmail.com' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

What am I missing still?

I don't have spring security, so I need to setup with Jersey.

victorio
  • 6,224
  • 24
  • 77
  • 113
  • have you tried with the proxy? https://angular.io/guide/build, here there is a guide to configure proxy conf in angular – Dario May 04 '21 at 09:46
  • 1. Your code doesn't compile; you're missing a parenthesis. 2. The error message says _"It does not have HTTP ok status."_ - See [this post](https://stackoverflow.com/a/28067653/2587435). – Paul Samsotha May 05 '21 at 18:49

1 Answers1

0

It is most likely your browser that is blocking these requests. You can check that with the Developer Tools of your browser. Does is say somewhere on the console that the browser blocked it?

For local development I suggest you configure a proxy as follows:

src/app/proxy.conf.json:

{
    "/api/*": {
        "target": "http://localhost:_YOUR_BACKEND_PORT_",
        "secure": false
    }
}

Then, in your angular.json:

                ...
                "serve": {
                    "builder": "@angular-devkit/build-angular:dev-server",
                    "options": {
                        "browserTarget": "your-app:build",
                        "proxyConfig": "src/proxy.conf.json"
                    },
                    ...

Then, make sure that you omit the hostname for all backend requests when developing locally. By that means, all backend requests (in this example all requests starting with /api/) will first be received by the angular dev server which will then proxy them to the backend.

More configuration options are documented here: https://angular.io/guide/build#proxying-to-a-backend-server

Please note that this is not meant to used for your productive build!

times29
  • 2,782
  • 2
  • 21
  • 40