From 996cb3be85b102e49101e9f6b9894c97de565fec Mon Sep 17 00:00:00 2001 From: ryounes Date: Fri, 17 Jun 2011 14:33:46 +0000 Subject: [PATCH] NIHVIVO-2701 Specify status code 303 when redirecting to RDF in IndividualController. Some incidental refactoring to allow for status codes in TemplateResponseValues objects. --- .../freemarker/FreemarkerHttpServlet.java | 35 +++++++++------ .../freemarker/IndividualController.java | 44 +++++++++++++------ .../responsevalues/BaseResponseValues.java | 6 +++ .../responsevalues/RdfResponseValues.java | 5 +++ .../responsevalues/ResponseValues.java | 2 + .../TemplateResponseValues.java | 4 +- 6 files changed, 68 insertions(+), 28 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java index f0430dc64..8792a0225 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java @@ -184,16 +184,24 @@ public class FreemarkerHttpServlet extends VitroHttpServlet { templateDataModel.put("body", bodyString); // Tell the template and any directives it uses that we're processing a page template. - templateDataModel.put("templateType", PAGE_TEMPLATE_TYPE); - writePage(templateDataModel, config, vreq, response); + templateDataModel.put("templateType", PAGE_TEMPLATE_TYPE); + + writePage(templateDataModel, config, vreq, response, values.getStatusCode()); } protected void doRedirect(HttpServletRequest request, HttpServletResponse response, ResponseValues values) throws ServletException, IOException { String redirectUrl = values.getRedirectUrl(); + setResponseStatus(response, values.getStatusCode()); response.sendRedirect(redirectUrl); } + private void setResponseStatus(HttpServletResponse response, int statusCode) { + if (statusCode > 0) { + response.setStatus(statusCode); + } + } + protected void doForward(HttpServletRequest request, HttpServletResponse response, ResponseValues values) throws ServletException, IOException { String forwardUrl = values.getForwardUrl(); @@ -369,11 +377,6 @@ public class FreemarkerHttpServlet extends VitroHttpServlet { // This value is used only in stylesheets.ftl and already contains the context path. map.put("stylesheetPath", UrlBuilder.getUrl(themeDir + "/css")); -// String bannerImage = portal.getBannerImage(); -// if ( ! StringUtils.isEmpty(bannerImage)) { -// map.put("bannerImage", UrlBuilder.getUrl(themeDir + "site_icons/" + bannerImage)); -// } - String flashMessage = DisplayMessage.getMessageAndClear(vreq); if (! flashMessage.isEmpty()) { map.put("flash", flashMessage); @@ -452,18 +455,24 @@ public class FreemarkerHttpServlet extends VitroHttpServlet { } protected void writePage(Map root, Configuration config, - HttpServletRequest request, HttpServletResponse response) throws TemplateProcessingException { - writeTemplate(getPageTemplateName(), root, config, request, response); + HttpServletRequest request, HttpServletResponse response, int statusCode) throws TemplateProcessingException { + writeTemplate(getPageTemplateName(), root, config, request, response, statusCode); } protected void writeTemplate(String templateName, Map map, Configuration config, - HttpServletRequest request, HttpServletResponse response) throws TemplateProcessingException { - StringWriter sw = processTemplate(templateName, map, config, request); - write(sw, response); + HttpServletRequest request, HttpServletResponse response) throws TemplateProcessingException { + writeTemplate(templateName, map, config, request, response, 0); + } + + protected void writeTemplate(String templateName, Map map, Configuration config, + HttpServletRequest request, HttpServletResponse response, int statusCode) throws TemplateProcessingException { + StringWriter sw = processTemplate(templateName, map, config, request); + write(sw, response, statusCode); } - protected void write(StringWriter sw, HttpServletResponse response) { + protected void write(StringWriter sw, HttpServletResponse response, int statusCode) { try { + setResponseStatus(response, statusCode); PrintWriter out = response.getWriter(); out.print(sw); } catch (IOException e) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java index 303ca289e..23d9082fe 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java @@ -100,7 +100,7 @@ public class IndividualController extends FreemarkerHttpServlet { // Check to see if the request is for a non-information resource, redirect if it is. String redirectURL = checkForRedirect ( url, vreq ); if( redirectURL != null ){ - return new RedirectResponseValues(redirectURL); + return new RedirectResponseValues(redirectURL, HttpServletResponse.SC_SEE_OTHER); } Individual individual = null; @@ -463,12 +463,19 @@ public class IndividualController extends FreemarkerHttpServlet { return null; } - - private static Pattern URI_PATTERN = Pattern.compile("^/individual/([^/]*)$"); - //Redirect if the request is for http://hostname/individual/localname - // if accept is nothing or text/html redirect to ??? - // if accept is some RDF thing redirect to the URL for RDF + /* + * Following recipe 3 from "Best Practice Recipes for Publishing RDF Vocabularies." + * See http://www.w3.org/TR/swbp-vocab-pub/#recipe3. + * The basic idea is that a URI like http://vivo.cornell.edu/individual/n1234 + * identifies a real world individual. HTTP cannot send that as the response + * to a GET request because it can only send bytes and not things. The server + * sends a 303, to mean "you asked for something I cannot send you, but I can + * send you this other stream of bytes about that thing." + * In the case of a request like http://vivo.cornell.edu/individual/n1234/n1234.rdf, + * the request is for a set of bytes rather than an individual, so no 303 is needed. + */ + private static Pattern URI_PATTERN = Pattern.compile("^/individual/([^/]*)$"); private String checkForRedirect(String url, VitroRequest vreq) { Matcher m = URI_PATTERN.matcher(url); if( m.matches() && m.groupCount() == 1 ){ @@ -506,7 +513,11 @@ public class IndividualController extends FreemarkerHttpServlet { protected ContentType checkForLinkedDataRequest(String url, VitroRequest vreq ) { try { Matcher m; - // Check for url param specifying format + /* + * Check for url param specifying format. + * Example: http://vivo.cornell.edu/individual/n23?format=rdfxml + * This request will trigger a redirect with a 303. + */ String formatParam = (String) vreq.getParameter("format"); if (formatParam != null) { m = RDFXML_FORMAT.matcher(formatParam); @@ -523,7 +534,11 @@ public class IndividualController extends FreemarkerHttpServlet { } } - //check the accept header + /* + * Check the accept header. This request will trigger a + * redirect with a 303, because the request is for an individual + * but the server can only provide a set of bytes. + */ String acceptHeader = vreq.getHeader("accept"); if (acceptHeader != null) { String ctStr = ContentType.getBestContentType( @@ -538,10 +553,12 @@ public class IndividualController extends FreemarkerHttpServlet { } /* - * check for parts of URL that indicate request for RDF - http://vivo.cornell.edu/individual/n23/n23.rdf - http://vivo.cornell.edu/individual/n23/n23.n3 - http://vivo.cornell.edu/individual/n23/n23.ttl + * Check for parts of URL that indicate request for RDF + * http://vivo.cornell.edu/individual/n23/n23.rdf + * http://vivo.cornell.edu/individual/n23/n23.n3 + * http://vivo.cornell.edu/individual/n23/n23.ttl + * This request will not trigger a redirect and 303, because + * the request is for a set of bytes rather than an individual. */ m = RDF_REQUEST.matcher(url); if( m.matches() ) { @@ -555,8 +572,7 @@ public class IndividualController extends FreemarkerHttpServlet { if( m.matches() ) { return ContentType.TURTLE; } - - + } catch (Throwable th) { log.error("problem while checking accept header " , th); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/BaseResponseValues.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/BaseResponseValues.java index 229a0c5a8..c4c6b5f4b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/BaseResponseValues.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/BaseResponseValues.java @@ -22,6 +22,11 @@ public abstract class BaseResponseValues implements ResponseValues { BaseResponseValues(ContentType contentType) { this.contentType = contentType; } + + BaseResponseValues(ContentType contentType, int statusCode) { + this.contentType = contentType; + this.statusCode = statusCode; + } @Override public int getStatusCode() { @@ -38,6 +43,7 @@ public abstract class BaseResponseValues implements ResponseValues { return contentType; } + @Override public void setContentType(ContentType contentType) { this.contentType = contentType; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/RdfResponseValues.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/RdfResponseValues.java index 470139e0b..4a3107857 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/RdfResponseValues.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/RdfResponseValues.java @@ -14,6 +14,11 @@ public class RdfResponseValues extends BaseResponseValues { this.model = model; } + public RdfResponseValues(ContentType contentType, Model model, int statusCode) { + super(contentType, statusCode); + this.model = model; + } + @Override public Model getModel() { return model; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/ResponseValues.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/ResponseValues.java index d72d6e22d..6ebdef627 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/ResponseValues.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/ResponseValues.java @@ -28,6 +28,8 @@ public interface ResponseValues { public ContentType getContentType(); + public void setContentType(ContentType contentType); + public Model getModel(); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/TemplateResponseValues.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/TemplateResponseValues.java index 7e35ed737..b02ce7b0c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/TemplateResponseValues.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/TemplateResponseValues.java @@ -49,7 +49,9 @@ public class TemplateResponseValues extends BaseResponseValues { } public static TemplateResponseValues getTemplateResponseValuesFromException(ExceptionResponseValues responseValues) { - return new TemplateResponseValues(responseValues.getTemplateName(), responseValues.getMap()); + return new TemplateResponseValues(responseValues.getTemplateName(), + responseValues.getMap(), + responseValues.getStatusCode()); } }