Add this filter:
package org.example.rest.service.filter; import java.io.IOException; import java.util.Arrays; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import javax.annotation.Priority; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.HttpMethod; import javax.ws.rs.Priorities; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.ext.Provider; import org.glassfish.jersey.server.ExtendedUriInfo; @Provider @Priority(Priorities.HEADER_DECORATOR) public class CORSFilter implements ContainerRequestFilter, ContainerResponseFilter { private static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; private static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; private static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; private static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; private static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers"; private static final String AUTHORIZATION = "authorization"; private static final String ORIGIN = "Origin"; private static String extractAllowedMethods(final ExtendedUriInfo extendedUriInfo) { final Optional<Class<?>> optional = extendedUriInfo.getMatchedRuntimeResources().stream() .flatMap(r -> r.getResources().stream()).flatMap(r -> r.getHandlerClasses().stream()) .filter(r -> r.getPackage().getName().startsWith("org.example.rest.service")).findFirst(); if (optional.isPresent()) { return Arrays.stream(optional.get().getDeclaredMethods())// .flatMap(m -> Arrays.stream(m.getAnnotations()))// .map(a -> a.annotationType().getAnnotation(javax.ws.rs.HttpMethod.class))// .filter(Objects::nonNull)// .map(HttpMethod::value)// .distinct()// .collect(Collectors.joining(", ")); } // Returning OPTIONS is a bit shady, as ACAM is about *real*, actual methods only. return "OPTIONS"; } @Context private HttpServletRequest request; @Context private ExtendedUriInfo extendedUriInfo; @Override public void filter(final ContainerRequestContext requestContext) throws IOException { final String origin = requestContext.getHeaderString(ORIGIN); if (origin != null && "OPTIONS".equals(requestContext.getMethod())) { request.setAttribute(this.getClass().getName(), true); requestContext.abortWith(Response.ok("CORS OK, carry on.", MediaType.TEXT_PLAIN_TYPE).build()); } } /** * @see https://www.w3.org/TR/cors/ * @see https://jmchung.github.io/blog/2013/08/11/cross-domain-on-jersey-restful-web-services/ * @see https://solutionsisee.wordpress.com/2016/06/30/adding-cors-support-in-jersey-server/ */ @Override public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) throws IOException { final MultivaluedMap<String, Object> responseHeaders = responseContext.getHeaders(); final String origin = requestContext.getHeaderString(ORIGIN); if (origin != null) { // The presence of the Origin header marks a CORS request. responseHeaders.add(ACCESS_CONTROL_ALLOW_ORIGIN, origin); responseHeaders.add(ACCESS_CONTROL_ALLOW_METHODS, extractAllowedMethods(extendedUriInfo)); responseHeaders.add(ACCESS_CONTROL_ALLOW_HEADERS, AUTHORIZATION + ", X-Requested-With, Content-Type"); if (requestContext.getHeaderString(ACCESS_CONTROL_REQUEST_HEADERS) != null) { responseHeaders.add(ACCESS_CONTROL_ALLOW_CREDENTIALS, requestContext .getHeaderString(ACCESS_CONTROL_REQUEST_HEADERS).toLowerCase().contains(AUTHORIZATION)); } } if (request.getAttribute(this.getClass().getName()) != null) { // We are in a CORS Preflight answer, fast tracked. The entity (== response body) is not // relevant. } } }
It is almost implementation agnostic, except for the
ExtendedUriInfo
.
No comments :
Post a Comment