Add interceptor for syntax highlighting

This commit is contained in:
James Agnew 2015-05-15 18:59:54 -04:00
parent 7517709edb
commit 0f9d4b8059
12 changed files with 82 additions and 25 deletions

View File

@ -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
}

View File

@ -277,7 +277,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
// For POST the URL parameters get jumbled with the post body parameters so don't include them, they might be huge
if (theRequest.getRequestType() == RequestTypeEnum.GET) {
boolean first = true;
for (Entry<String, String[]> nextParams : theRequest.getParameters().entrySet()) {
Map<String, String[]> parameters = theRequest.getParameters();
for (Entry<String, String[]> nextParams : parameters.entrySet()) {
for (String nextParamValue : nextParams.getValue()) {
if (first) {
b.append('?');

View File

@ -170,7 +170,7 @@ public class RestfulServerUtils {
public static boolean prettyPrintResponse(RestfulServer theServer, RequestDetails theRequest) {
Map<String, String[]> 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<String, String[]> 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 {

View File

@ -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);

View File

@ -244,12 +244,6 @@
<version>${guava_version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>${derby_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>

View File

@ -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<Object> provList = new ArrayList<Object>();
if (systemProviderDstu1 != null)
provList.add(systemProviderDstu1);
if (systemProviderDstu2 != null)
@ -128,12 +129,10 @@ 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

View File

@ -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();

View File

@ -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();

View File

@ -42,6 +42,8 @@ public class SearchWithDstu2BundleTest {
assertEquals(200, status.getStatusLine().getStatusCode());
responseContent = responseContent.replace("_pretty=true&amp;_format=xml", "_format=xml&amp;_pretty=true");
ourLog.info(responseContent);
//@formatter:off

View File

@ -79,12 +79,6 @@
<version>${jetty_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>

View File

@ -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)
</action>
<action type="add">
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.
</action>
</release>
<release version="1.0" date="2015-May-8">
<action type="add">

View File

@ -173,6 +173,29 @@
</subsection>
<subsection name="Response Syntax Highlighting">
<p>
The
<a href="./apidocs/ca/uhn/fhir/rest/server/interceptor/ResponseHighlighterInterceptor.html">ResponseHighlighterInterceptor</a>
(<a href="./xref/ca/uhn/fhir/rest/server/interceptor/ResponseHighlighterInterceptor.html">code</a>)
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.
</p>
<p>
The following example shows how to register this interceptor within
a FHIR RESTful server.
</p>
<macro name="snippet">
<param name="id" value="responseHighlighterInterceptor" />
<param name="file" value="examples/src/main/java/example/ServletExamples.java" />
</macro>
</subsection>
</section>
<section name="Creating Interceptors">