WW-4588: Improve the Struts2 Rest plugin to honor Accept header

Conflicts:
	plugins/rest/src/main/java/org/apache/struts2/rest/DefaultContentTypeHandlerManager.java
This commit is contained in:
petersr
2016-01-20 06:34:25 -08:00
committed by Lukasz Lenart
parent 10a612c9da
commit 2ec3890dc7
2 changed files with 103 additions and 8 deletions
@@ -42,9 +42,9 @@ import java.util.Set;
public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManager {
/** ContentTypeHandlers keyed by the extension */
Map<String,ContentTypeHandler> handlersByExtension = new HashMap<String,ContentTypeHandler>();
Map<String, ContentTypeHandler> handlersByExtension = new HashMap<String, ContentTypeHandler>();
/** ContentTypeHandlers keyed by the content-type */
Map<String,ContentTypeHandler> handlersByContentType = new HashMap<String,ContentTypeHandler>();
Map<String, ContentTypeHandler> handlersByContentType = new HashMap<String, ContentTypeHandler>();
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;
}
@@ -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 {