diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/DefaultContentTypeHandlerManager.java b/plugins/rest/src/main/java/org/apache/struts2/rest/DefaultContentTypeHandlerManager.java index 5f50bf9ac..dba7d1306 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/DefaultContentTypeHandlerManager.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/DefaultContentTypeHandlerManager.java @@ -42,9 +42,9 @@ import java.util.Set; public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManager { /** ContentTypeHandlers keyed by the extension */ - Map handlersByExtension = new HashMap<>(); + Map handlersByExtension = new HashMap(); /** ContentTypeHandlers keyed by the content-type */ - Map handlersByContentType = new HashMap<>(); + Map handlersByContentType = new HashMap(); private String defaultExtension; @@ -61,7 +61,7 @@ public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManag if (handler.getExtension() != null) { // Check for overriding handlers for the current extension - String overrideName = container.getInstance(String.class, STRUTS_REST_HANDLER_OVERRIDE_PREFIX +handler.getExtension()); + String overrideName = container.getInstance(String.class, STRUTS_REST_HANDLER_OVERRIDE_PREFIX + handler.getExtension()); if (overrideName != null) { if (!handlersByExtension.containsKey(handler.getExtension())) { handler = container.getInstance(ContentTypeHandler.class, overrideName); @@ -74,7 +74,15 @@ public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManag } if (handler.getContentType() != null) { - this.handlersByContentType.put(handler.getContentType(), handler); + //dont store character encoding + String typeOnly = handler.getContentType() ; + int index = handler.getContentType().indexOf(';'); + if (index != -1) + { + typeOnly = handler.getContentType().substring(0, index).trim(); + } + + this.handlersByContentType.put(typeOnly, handler); } } } @@ -109,12 +117,42 @@ public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManag * Gets the handler for the response by looking at the extension of the request * @param req The request * @return The appropriate handler + * + * WW-4588: modified to get a handler for the response side and auto generate the response type + * from the Accept: header + * */ - public ContentTypeHandler getHandlerForResponse(HttpServletRequest req, HttpServletResponse res) { - String extension = findExtension(req.getRequestURI()); + public ContentTypeHandler getHandlerForResponse(HttpServletRequest request, HttpServletResponse res) { + + String extension = getExtensionIfPresent(request.getRequestURI()); + if (extension == null) { + extension = defaultExtension; + final String acceptHeader = request.getHeader("accept") ; + if (acceptHeader != null) { + final String[] types = acceptHeader.split(","); + for (final String type : types) { + final ContentTypeHandler handler = findHandler(type); + if (handler != null) { + return handler; + } + } + } + } return handlersByExtension.get(extension); } + private ContentTypeHandler findHandler(final String type) { + ContentTypeHandler handler = handlersByContentType.get(type); + if (handler == null) { + // strip off encoding and search again (e.g., application/json;charset=ISO-8859-1) + final int index = type.indexOf(';'); + if (index != -1) { + return handlersByContentType.get(type.substring(0, index).trim()); + } + } + return handler; + } + /** * Handles the result using handlers to generate content type-specific content * @@ -174,17 +212,32 @@ public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManag } } + /** + * Gets the extension in the url + * + * @param url The url + * @return The extension, or null + */ + public String getExtensionIfPresent(String url) { + int dotPos = url.lastIndexOf('.'); + int slashPos = url.lastIndexOf('/'); + if (dotPos > slashPos && dotPos > -1) { + return url.substring(dotPos + 1); + } + return null; + } + /** * Finds the extension in the url * * @param url The url - * @return The extension + * @return The extension, or the default extension if there is none */ public String findExtension(String url) { int dotPos = url.lastIndexOf('.'); int slashPos = url.lastIndexOf('/'); if (dotPos > slashPos && dotPos > -1) { - return url.substring(dotPos+1); + return url.substring(dotPos + 1); } return defaultExtension; } diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/DefaultContentTypeHandlerManagerTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/DefaultContentTypeHandlerManagerTest.java index 10f24229f..7904f7d9c 100644 --- a/plugins/rest/src/test/java/org/apache/struts2/rest/DefaultContentTypeHandlerManagerTest.java +++ b/plugins/rest/src/test/java/org/apache/struts2/rest/DefaultContentTypeHandlerManagerTest.java @@ -5,6 +5,7 @@ import com.opensymphony.xwork2.inject.Container; import com.opensymphony.xwork2.inject.Scope; import org.apache.struts2.rest.handler.ContentTypeHandler; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; import java.io.IOException; import java.io.Reader; @@ -64,6 +65,47 @@ public class DefaultContentTypeHandlerManagerTest extends XWorkTestCase { assertEquals("json", handler.getExtension()); } + public void testObtainingHandlerForRequestByContentType() throws Exception { + // given + DefaultContentTypeHandlerManager handlerManager = new DefaultContentTypeHandlerManager(); + handlerManager.setContainer(new DummyContainer("application/json", "")); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setContentType("application/json;charset=UTF-8"); + request.setRequestURI("/index"); + + // when + ContentTypeHandler handler = handlerManager.getHandlerForRequest(request); + + // then + assertNotNull(handler); + assertEquals("application/json", handler.getContentType()); + assertEquals("", handler.getExtension()); + } + + public void testObtainingHandlerForResponseByAcceptHeader() throws Exception { + + // given + final DefaultContentTypeHandlerManager handlerManager = new DefaultContentTypeHandlerManager(); + handlerManager.setContainer(new DummyContainer("application/json", "json")); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setContentType("application/json;charset=UTF-8"); + request.addHeader("accept","application/json;charset=UTF-8"); + request.setRequestURI("/index"); + + final MockHttpServletResponse response = new MockHttpServletResponse(); + response.setContentType("application/json;charset=UTF-8"); + + // when + ContentTypeHandler handler = handlerManager.getHandlerForResponse(request,response); + + // then + assertNotNull(handler); + assertEquals("application/json", handler.getContentType()); + assertEquals("json", handler.getExtension()); + } + } class DummyContainer implements Container {