/** * Determines the request type. * * @param request * @return */ public CORSRequestType checkRequestType(final HttpServletRequest request) { CORSRequestType requestType = CORSRequestType.INVALID_CORS; if (request == null) { throw new IllegalArgumentException("HttpServletRequest object is null"); } String originHeader = request.getHeader(REQUEST_HEADER_ORIGIN); // Section 6.1.1 and Section 6.2.1 if (originHeader != null) { if (originHeader.isEmpty()) { requestType = CORSRequestType.INVALID_CORS; } else if (!isValidOrigin(originHeader)) { requestType = CORSRequestType.INVALID_CORS; } else { String method = request.getMethod(); if (method != null && HTTP_METHODS.contains(method)) { if ("OPTIONS".equals(method)) { String accessControlRequestMethodHeader = request.getHeader(REQUEST_HEADER_ACCESS_CONTROL_REQUEST_METHOD); if (accessControlRequestMethodHeader != null && !accessControlRequestMethodHeader.isEmpty()) { requestType = CORSRequestType.PRE_FLIGHT; } else if (accessControlRequestMethodHeader != null && accessControlRequestMethodHeader.isEmpty()) { requestType = CORSRequestType.INVALID_CORS; } else { requestType = CORSRequestType.ACTUAL; } } else if ("GET".equals(method) || "HEAD".equals(method)) { requestType = CORSRequestType.SIMPLE; } else if ("POST".equals(method)) { String contentType = request.getContentType(); if (contentType != null) { contentType = contentType.toLowerCase().trim(); if (SIMPLE_HTTP_REQUEST_CONTENT_TYPE_VALUES.contains(contentType)) { requestType = CORSRequestType.SIMPLE; } else { requestType = CORSRequestType.ACTUAL; } } } else if (COMPLEX_HTTP_METHODS.contains(method)) { requestType = CORSRequestType.ACTUAL; } } } } else { requestType = CORSRequestType.NOT_CORS; } return requestType; }
/** * Handles CORS pre-flight request. * * @param request The {@link HttpServletRequest} object. * @param response The {@link HttpServletResponse} object. * @param filterChain The {@link FilterChain} object. * @throws IOException * @throws ServletException */ public void handlePreflightCORS( final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws IOException, ServletException { CORSRequestType requestType = checkRequestType(request); if (requestType != CORSRequestType.PRE_FLIGHT) { throw new IllegalArgumentException( "Expects a HttpServletRequest object of type " + CORSRequestType.PRE_FLIGHT.name().toLowerCase()); } final String origin = request.getHeader(CORSFilter.REQUEST_HEADER_ORIGIN); // Section 6.2.2 if (!isOriginAllowed(origin)) { handleInvalidCORS(request, response, filterChain); return; } // Section 6.2.3 String accessControlRequestMethod = request.getHeader(CORSFilter.REQUEST_HEADER_ACCESS_CONTROL_REQUEST_METHOD); if (accessControlRequestMethod == null || (!HTTP_METHODS.contains(accessControlRequestMethod.trim()))) { handleInvalidCORS(request, response, filterChain); return; } else { accessControlRequestMethod = accessControlRequestMethod.trim(); } // Section 6.2.4 String accessControlRequestHeadersHeader = request.getHeader(CORSFilter.REQUEST_HEADER_ACCESS_CONTROL_REQUEST_HEADERS); List<String> accessControlRequestHeaders = new LinkedList<String>(); if (accessControlRequestHeadersHeader != null && !accessControlRequestHeadersHeader.trim().isEmpty()) { String[] headers = accessControlRequestHeadersHeader.trim().split(","); for (String header : headers) { accessControlRequestHeaders.add(header.trim().toLowerCase()); } } // Section 6.2.5 if (!allowedHttpMethods.contains(accessControlRequestMethod)) { handleInvalidCORS(request, response, filterChain); return; } // Section 6.2.6 if (!accessControlRequestHeaders.isEmpty()) { for (String header : accessControlRequestHeaders) { if (!allowedHttpHeaders.contains(header)) { handleInvalidCORS(request, response, filterChain); return; } } } // Section 6.2.7 if (supportsCredentials) { response.addHeader(CORSFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, origin); response.addHeader(CORSFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); } else { if (anyOriginAllowed) { response.addHeader(CORSFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, "*"); } else { response.addHeader(CORSFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, origin); } } // Section 6.2.8 if (preflightMaxAge > 0) { response.addHeader( CORSFilter.RESPONSE_HEADER_ACCESS_CONTROL_MAX_AGE, String.valueOf(preflightMaxAge)); } // Section 6.2.9 response.addHeader( CORSFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_METHODS, accessControlRequestMethod); // Section 6.2.10 if ((allowedHttpHeaders != null) && (!allowedHttpHeaders.isEmpty())) { response.addHeader( CORSFilter.RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_HEADERS, join(allowedHttpHeaders, ",")); } // Do not forward the request down the filter chain. }