From 24cdefb785cb8eb6d3edbbc81bf29e395ef034e0 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Thu, 26 Jun 2014 23:39:17 +0200 Subject: [PATCH] Workaround for WFLY-3474 NullPointerException Prior to this commit, the ServletResponseHttpHeaders.get method would throw an NPE when used under Wildfly 8.0.0.Final and 8.1.0.Final. This can be traced to WFLY-3474, which throws an NPE when calling HttpServletResponse.getHeaders("foo") and that header has not been defined prior to that. This would cause NPE being thrown by AbstractSockJsService when checking for CORS HTTP headers in the server HTTP response. This commit surrounds that method call in AbstractSockJsService and guards against this issue. Issue: SPR-11919 --- .../sockjs/support/AbstractSockJsService.java | 13 ++++++++---- .../sockjs/support/SockJsServiceTests.java | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) 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 1484aea81f9..447de17efe1 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 @@ -367,10 +367,15 @@ public abstract class AbstractSockJsService implements SockJsService { HttpHeaders requestHeaders = request.getHeaders(); HttpHeaders responseHeaders = response.getHeaders(); - // Perhaps a CORS Filter has already added this? - if (!CollectionUtils.isEmpty(responseHeaders.get("Access-Control-Allow-Origin"))) { - logger.debug("Skip adding CORS headers, response already contains \"Access-Control-Allow-Origin\""); - return; + try { + // Perhaps a CORS Filter has already added this? + if (!CollectionUtils.isEmpty(responseHeaders.get("Access-Control-Allow-Origin"))) { + logger.debug("Skip adding CORS headers, response already contains \"Access-Control-Allow-Origin\""); + return; + } + } + catch (NullPointerException npe) { + // See SPR-11919 and https://issues.jboss.org/browse/WFLY-3474 } String origin = requestHeaders.getFirst("origin"); 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 20c3eb19c3d..a7117c4bef5 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 @@ -23,6 +23,7 @@ import org.junit.Test; import org.springframework.http.HttpStatus; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; +import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.web.socket.AbstractHttpRequestTests; @@ -30,6 +31,10 @@ import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.sockjs.SockJsException; import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; /** * Test fixture for {@link AbstractSockJsService}. @@ -106,6 +111,21 @@ public class SockJsServiceTests extends AbstractHttpRequestTests { assertEquals("foobar:123", this.servletResponse.getHeader("Access-Control-Allow-Origin")); } + // SPR-11919 + + @Test + public void handleInfoGetWildflyNPE() throws Exception { + HttpServletResponse mockResponse = mock(HttpServletResponse.class); + ServletOutputStream ous = mock(ServletOutputStream.class); + when(mockResponse.getHeaders("Access-Control-Allow-Origin")).thenThrow(NullPointerException.class); + when(mockResponse.getOutputStream()).thenReturn(ous); + this.response = new ServletServerHttpResponse(mockResponse); + + handleRequest("GET", "/echo/info", HttpStatus.OK); + + verify(mockResponse.getOutputStream(), times(1)); + } + @Test public void handleInfoOptions() throws Exception {