From 2a39081819ba252a26daaa53588a3fb147115895 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Wed, 8 Oct 2014 16:37:50 +0200 Subject: [PATCH] Add Vary:Origin HTTP header in SockJS responses This change adds a "Vary: Origin" HTTP response header for /info and /iframe SockJS endpoints. This is preventing proxies and browsers from caching a response and reusing it for an invalid Origin. Reference: https://groups.google.com/forum/#!topic/sockjs/svsLWRorSis Issue: SPR-12310 --- .../web/socket/sockjs/support/AbstractSockJsService.java | 4 +++- .../web/socket/sockjs/support/SockJsServiceTests.java | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/support/AbstractSockJsService.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/support/AbstractSockJsService.java index 06a4762582..97e0fa8324 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/support/AbstractSockJsService.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/support/AbstractSockJsService.java @@ -117,7 +117,7 @@ public abstract class AbstractSockJsService implements SockJsService { * server. Since the iframe needs to load the SockJS javascript client library, * this property allows specifying where to load it from. *

By default this is set to point to - * "https://d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.4.min.js". + * "https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js". * However, it can also be set to point to a URL served by the application. *

Note that it's possible to specify a relative URL in which case the URL * must be relative to the iframe URL. For example assuming a SockJS endpoint @@ -390,11 +390,13 @@ public abstract class AbstractSockJsService implements SockJsService { responseHeaders.add("Access-Control-Allow-Methods", StringUtils.arrayToDelimitedString(httpMethods, ", ")); responseHeaders.add("Access-Control-Max-Age", String.valueOf(ONE_YEAR)); } + responseHeaders.add(HttpHeaders.VARY, HttpHeaders.ORIGIN); } protected void addCacheHeaders(ServerHttpResponse response) { response.getHeaders().setCacheControl("public, max-age=" + ONE_YEAR); response.getHeaders().setExpires(new Date().getTime() + ONE_YEAR * 1000); + response.getHeaders().add(HttpHeaders.VARY, HttpHeaders.ORIGIN); } protected void addNoCacheHeaders(ServerHttpResponse response) { diff --git a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/support/SockJsServiceTests.java b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/support/SockJsServiceTests.java index a729e2cbdf..0e99147aa1 100644 --- a/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/support/SockJsServiceTests.java +++ b/spring-websocket/src/test/java/org/springframework/web/socket/sockjs/support/SockJsServiceTests.java @@ -83,6 +83,7 @@ public class SockJsServiceTests extends AbstractHttpRequestTests { assertEquals("*", this.servletResponse.getHeader("Access-Control-Allow-Origin")); assertEquals("true", this.servletResponse.getHeader("Access-Control-Allow-Credentials")); assertEquals("no-store, no-cache, must-revalidate, max-age=0", this.servletResponse.getHeader("Cache-Control")); + assertEquals("Origin", this.servletResponse.getHeader("Vary")); String body = this.servletResponse.getContentAsString(); assertEquals("{\"entropy\"", body.substring(0, body.indexOf(':'))); @@ -133,6 +134,7 @@ public class SockJsServiceTests extends AbstractHttpRequestTests { assertEquals("Last-Modified", this.servletResponse.getHeader("Access-Control-Allow-Headers")); assertEquals("OPTIONS, GET", this.servletResponse.getHeader("Access-Control-Allow-Methods")); assertEquals("31536000", this.servletResponse.getHeader("Access-Control-Max-Age")); + assertEquals("Origin", this.servletResponse.getHeader("Vary")); } @Test