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.