381639 - CrossOriginFilter does not support Access-Control-Expose-Headers.

This commit is contained in:
Simone Bordet 2012-06-05 16:03:08 +02:00
parent 5b3999a7f4
commit 28c3c3e917
2 changed files with 39 additions and 5 deletions

View File

@ -54,15 +54,18 @@ import org.eclipse.jetty.util.log.Logger;
* and any 3 letter top-level domain (.com, .net, .org, etc.).</li>
* <li><b>allowedMethods</b>, a comma separated list of HTTP methods that
* are allowed to be used when accessing the resources. Default value is
* <b>GET,POST</b></li>
* <b>GET,POST,HEAD</b></li>
* <li><b>allowedHeaders</b>, a comma separated list of HTTP headers that
* are allowed to be specified when accessing the resources. Default value
* is <b>X-Requested-With</b></li>
* is <b>X-Requested-With,Content-Type,Accept,Origin</b></li>
* <li><b>preflightMaxAge</b>, the number of seconds that preflight requests
* can be cached by the client. Default value is <b>1800</b> seconds, or 30
* minutes</li>
* <li><b>allowCredentials</b>, a boolean indicating if the resource allows
* requests with credentials. Default value is <b>false</b></li>
* <li><b>exposeHeaders</b>, a comma separated list of HTTP headers that
* are allowed to be exposed on the client. Default value is the
* <b>empty list</b></li>
* </ul></p>
* <p>A typical configuration could be:
* <pre>
@ -79,8 +82,6 @@ import org.eclipse.jetty.util.log.Logger;
* ...
* &lt;/web-app&gt;
* </pre></p>
*
* @version $Revision$ $Date$
*/
public class CrossOriginFilter implements Filter
{
@ -96,12 +97,14 @@ public class CrossOriginFilter implements Filter
public static final String ACCESS_CONTROL_ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers";
public static final String ACCESS_CONTROL_MAX_AGE_HEADER = "Access-Control-Max-Age";
public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER = "Access-Control-Allow-Credentials";
public static final String ACCESS_CONTROL_EXPOSE_HEADERS_HEADER = "Access-Control-Expose-Headers";
// Implementation constants
public static final String ALLOWED_ORIGINS_PARAM = "allowedOrigins";
public static final String ALLOWED_METHODS_PARAM = "allowedMethods";
public static final String ALLOWED_HEADERS_PARAM = "allowedHeaders";
public static final String PREFLIGHT_MAX_AGE_PARAM = "preflightMaxAge";
public static final String ALLOW_CREDENTIALS_PARAM = "allowCredentials";
public static final String EXPOSED_HEADERS_PARAM = "exposedHeaders";
private static final String ANY_ORIGIN = "*";
private static final List<String> SIMPLE_HTTP_METHODS = Arrays.asList("GET", "POST", "HEAD");
@ -109,6 +112,7 @@ public class CrossOriginFilter implements Filter
private List<String> allowedOrigins = new ArrayList<String>();
private List<String> allowedMethods = new ArrayList<String>();
private List<String> allowedHeaders = new ArrayList<String>();
private List<String> exposedHeaders = new ArrayList<String>();
private int preflightMaxAge = 0;
private boolean allowCredentials;
@ -163,6 +167,11 @@ public class CrossOriginFilter implements Filter
allowedCredentialsConfig = "true";
allowCredentials = Boolean.parseBoolean(allowedCredentialsConfig);
String exposedHeadersConfig = config.getInitParameter(EXPOSED_HEADERS_PARAM);
if (exposedHeadersConfig == null)
exposedHeadersConfig = "";
exposedHeaders.addAll(Arrays.asList(exposedHeadersConfig.split(",")));
if (LOG.isDebugEnabled())
{
LOG.debug("Cross-origin filter configuration: " +
@ -170,7 +179,9 @@ public class CrossOriginFilter implements Filter
ALLOWED_METHODS_PARAM + " = " + allowedMethodsConfig + ", " +
ALLOWED_HEADERS_PARAM + " = " + allowedHeadersConfig + ", " +
PREFLIGHT_MAX_AGE_PARAM + " = " + preflightMaxAgeConfig + ", " +
ALLOW_CREDENTIALS_PARAM + " = " + allowedCredentialsConfig);
ALLOW_CREDENTIALS_PARAM + " = " + allowedCredentialsConfig + "," +
EXPOSED_HEADERS_PARAM + " = " + exposedHeadersConfig
);
}
}
@ -305,6 +316,8 @@ public class CrossOriginFilter implements Filter
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);
if (allowCredentials)
response.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
if (!exposedHeaders.isEmpty())
response.setHeader(ACCESS_CONTROL_EXPOSE_HEADERS_HEADER, commify(exposedHeaders));
}
private void handlePreflightResponse(HttpServletRequest request, HttpServletResponse response, String origin)

View File

@ -371,6 +371,27 @@ public class CrossOriginFilterTest
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
}
@Test
public void testSimpleRequestWithExposedHeaders() throws Exception
{
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
filterHolder.setInitParameter("exposedHeaders", "Content-Length");
tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request = "" +
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String response = tester.getResponses(request);
Assert.assertTrue(response.contains("HTTP/1.1 200"));
Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_EXPOSE_HEADERS_HEADER));
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
}
public static class ResourceServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;