diff --git a/examples/src/main/java/example/ServletExamples.java b/examples/src/main/java/example/ServletExamples.java index e96c2d69b6d..518bf46b1dd 100644 --- a/examples/src/main/java/example/ServletExamples.java +++ b/examples/src/main/java/example/ServletExamples.java @@ -7,6 +7,7 @@ import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor; import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; +import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; @SuppressWarnings("serial") public class ServletExamples { @@ -47,7 +48,7 @@ public class ServletExamples { // ... define your resource providers here ... - // Now register the logging interceptor + // Now register the interceptor ExceptionHandlingInterceptor interceptor = new ExceptionHandlingInterceptor(); registerInterceptor(interceptor); @@ -59,4 +60,22 @@ public class ServletExamples { } // END SNIPPET: exceptionInterceptor + // START SNIPPET: responseHighlighterInterceptor + @WebServlet(urlPatterns = { "/fhir/*" }, displayName = "FHIR Server") + public class RestfulServerWithResponseHighlighter extends RestfulServer { + + @Override + protected void initialize() throws ServletException { + + // ... define your resource providers here ... + + // Now register the interceptor + ResponseHighlighterInterceptor interceptor = new ResponseHighlighterInterceptor(); + registerInterceptor(interceptor); + + } + + } + // END SNIPPET: responseHighlighterInterceptor + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseResourceReturningMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseResourceReturningMethodBinding.java index 323c8a16965..6cfd3664291 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseResourceReturningMethodBinding.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseResourceReturningMethodBinding.java @@ -277,7 +277,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding nextParams : theRequest.getParameters().entrySet()) { + Map parameters = theRequest.getParameters(); + for (Entry nextParams : parameters.entrySet()) { for (String nextParamValue : nextParams.getValue()) { if (first) { b.append('?'); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java index 33daf07b0fe..e10dbe149cf 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java @@ -170,7 +170,7 @@ public class RestfulServerUtils { public static boolean prettyPrintResponse(RestfulServer theServer, RequestDetails theRequest) { Map requestParams = theRequest.getParameters(); - String[] pretty = requestParams.remove(Constants.PARAM_PRETTY); + String[] pretty = requestParams.get(Constants.PARAM_PRETTY); boolean prettyPrint; if (pretty != null && pretty.length > 0) { if (Constants.PARAM_PRETTY_VALUE_TRUE.equals(pretty[0])) { @@ -304,7 +304,7 @@ public class RestfulServerUtils { public static RestfulServer.NarrativeModeEnum determineNarrativeMode(RequestDetails theRequest) { Map requestParams = theRequest.getParameters(); - String[] narrative = requestParams.remove(Constants.PARAM_NARRATIVE); + String[] narrative = requestParams.get(Constants.PARAM_NARRATIVE); RestfulServer.NarrativeModeEnum narrativeMode = null; if (narrative != null && narrative.length > 0) { try { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseHighlighterInterceptor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseHighlighterInterceptor.java index 72fe098b8cd..f0ac852f18f 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseHighlighterInterceptor.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseHighlighterInterceptor.java @@ -29,6 +29,7 @@ import org.apache.commons.lang3.StringEscapeUtils; import org.hl7.fhir.instance.model.api.IBaseResource; import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.rest.api.RequestTypeEnum; import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.EncodingEnum; @@ -153,11 +154,30 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter { @Override public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException { + + /* + * It's not a browser... + */ String accept = theServletRequest.getHeader(Constants.HEADER_ACCEPT); if (accept == null || !accept.toLowerCase().contains("html")) { return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse); } + + /* + * It's an AJAX request, so no HTML + */ + String requestedWith = theServletRequest.getHeader("X-Requested-With"); + if (requestedWith != null) { + return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse); + } + /* + * Not a GET + */ + if (theRequestDetails.getRequestType() != RequestTypeEnum.GET) { + return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse); + } + // Pretty print boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theRequestDetails.getServer(), theRequestDetails); diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index 73bcc29e16a..bba2f793f0f 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -244,12 +244,6 @@ ${guava_version} - - org.apache.derby - derby - ${derby_version} - test - org.eclipse.jetty jetty-servlets diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java index 1ea6366ceec..0cb6487cd33 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java @@ -25,6 +25,7 @@ import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy; import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; +import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; public class TestRestfulServer extends RestfulServer { @@ -120,7 +121,7 @@ public class TestRestfulServer extends RestfulServer { } setResourceProviders(beans); - List provList = new ArrayList(); + List provList = new ArrayList(); if (systemProviderDstu1 != null) provList.add(systemProviderDstu1); if (systemProviderDstu2 != null) @@ -128,13 +129,11 @@ public class TestRestfulServer extends RestfulServer { setPlainProviders(provList); /* - * This tells the server to use "incorrect" MIME types if it detects that the - * request is coming from a browser in the hopes that the browser won't just treat - * the content as a binary payload and try to download it (which is what generally - * happens if you load a FHIR URL in a browser) + * We want to format the response using nice HTML if it's a browser, since this + * makes things a little easier for testers. */ - setUseBrowserFriendlyContentTypes(true); - + registerInterceptor(new ResponseHighlighterInterceptor()); + /* * Default to XML and pretty printing */ diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/PlainProviderTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/PlainProviderTest.java index 26bc6116b23..325ee42d0c4 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/PlainProviderTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/PlainProviderTest.java @@ -102,7 +102,7 @@ public class PlainProviderTest { Patient patient = (Patient) bundle.getEntries().get(0).getResource(); assertEquals("PatientOne", patient.getName().get(0).getGiven().get(0).getValue()); - assertEquals(uri, bundle.getLinkSelf().getValue()); + assertEquals(uri.replace(":hapitest:", "%3Ahapitest%3A"), bundle.getLinkSelf().getValue()); assertEquals(baseUri, bundle.getLinkBase().getValue()); httpGet.releaseConnection(); diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/RestfulServerSelfReferenceTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/RestfulServerSelfReferenceTest.java index 2a648b3441b..2ec76f3ba3d 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/RestfulServerSelfReferenceTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/RestfulServerSelfReferenceTest.java @@ -134,7 +134,7 @@ public class RestfulServerSelfReferenceTest { Patient patient = (Patient) bundle.getEntries().get(0).getResource(); assertEquals("PatientOne", patient.getName().get(0).getGiven().get(0).getValue()); - assertEquals(uri, bundle.getLinkSelf().getValue()); + assertEquals(uri.replace(":hapitest:", "%3Ahapitest%3A"), bundle.getLinkSelf().getValue()); assertEquals(baseUri, bundle.getLinkBase().getValue()); } finally { hServer.stop(); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/SearchWithDstu2BundleTest.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/SearchWithDstu2BundleTest.java index 13ff660ed0e..b9b963414e4 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/SearchWithDstu2BundleTest.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/SearchWithDstu2BundleTest.java @@ -42,6 +42,8 @@ public class SearchWithDstu2BundleTest { assertEquals(200, status.getStatusLine().getStatusCode()); + responseContent = responseContent.replace("_pretty=true&_format=xml", "_format=xml&_pretty=true"); + ourLog.info(responseContent); //@formatter:off diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index 2a7d7d66359..feb449dc44f 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -79,12 +79,6 @@ ${jetty_version} test - - org.eclipse.jetty - jetty-servlet - ${jetty_version} - test - org.eclipse.jetty jetty-util diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 437102a92dc..0687440ea0d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,11 @@ The self link in the Bundle returned by searches on the server does not respect the server's address strategy (which resulted in an internal IP being shown on fhirtest.uhn.ca) + + Introduce ResponseHighlighterInterceptor, which provides syntax highlighting on RESTful server responses + if the server detects that the request is coming from a browser. This interceptor has been added + to fhirtest.uhn.ca responses. + diff --git a/src/site/xdoc/doc_rest_server_interceptor.xml b/src/site/xdoc/doc_rest_server_interceptor.xml index b89b8036bf5..03a1b72b091 100644 --- a/src/site/xdoc/doc_rest_server_interceptor.xml +++ b/src/site/xdoc/doc_rest_server_interceptor.xml @@ -172,7 +172,30 @@ + + +

+ The + ResponseHighlighterInterceptor + (code) + detects when a request is coming from a browser and returns HTML with syntax highlighted XML/JSON instead + of just the raw text. In other words, if a user uses a browser to request "http://foo/Patient/1" by typing + this address into their URL bar, they will get nice formatted HTML back with a human readable version + of the content. This is helpful for testers. +

+ +

+ The following example shows how to register this interceptor within + a FHIR RESTful server. +

+ + + + + +
+