diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/ResponseHighlightingInterceptorTest.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/ResponseHighlightingInterceptorTest.java index d5d198902c6..3b2818641d3 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/ResponseHighlightingInterceptorTest.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/ResponseHighlightingInterceptorTest.java @@ -61,92 +61,230 @@ import ca.uhn.fhir.util.*; public class ResponseHighlightingInterceptorTest { + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseHighlightingInterceptorTest.class); private static ResponseHighlighterInterceptor ourInterceptor = new ResponseHighlighterInterceptor(); private static CloseableHttpClient ourClient; private static FhirContext ourCtx = FhirContext.forDstu2(); - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseHighlightingInterceptorTest.class); private static int ourPort; private static Server ourServer; private static RestfulServer ourServlet; - @AfterClass - public static void afterClassClearContext() { - TestUtil.clearAllStaticFieldsForUnitTest(); - } - @Before public void before() { ourInterceptor.setShowRequestHeaders(new ResponseHighlighterInterceptor().isShowRequestHeaders()); ourInterceptor.setShowResponseHeaders(new ResponseHighlighterInterceptor().isShowResponseHeaders()); } - /** - * For interactive testing only - */ @Test - public void waitForInput() throws IOException { - System.in.read(); + public void testBinaryReadAcceptBrowser() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary/foo"); + httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); + httpGet.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); + + HttpResponse status = ourClient.execute(httpGet); + byte[] responseContent = IOUtils.toByteArray(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals("foo", status.getFirstHeader("content-type").getValue()); + assertEquals("Attachment;", status.getFirstHeader("Content-Disposition").getValue()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, responseContent); } - /** - * See #464 - */ @Test - public void testPrettyPrintDefaultsToTrue() throws Exception { - ourServlet.setDefaultPrettyPrint(false); - - HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1"); - httpGet.addHeader("Accept", "text/html"); + public void testBinaryReadAcceptFhirJson() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary/foo"); + httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); + httpGet.addHeader("Accept", Constants.CT_FHIR_JSON); HttpResponse status = ourClient.execute(httpGet); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); IOUtils.closeQuietly(status.getEntity().getContent()); - ourLog.info(responseContent); assertEquals(200, status.getStatusLine().getStatusCode()); - assertThat(responseContent, (stringContainsInOrder("", "
", "")));
+		assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
+		assertNull(status.getFirstHeader("Content-Disposition"));
+		assertEquals("{\"resourceType\":\"Binary\",\"id\":\"1\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}", responseContent);
+
 	}
 
-	/**
-	 * See #464
-	 */
 	@Test
-	public void testPrettyPrintDefaultsToTrueWithExplicitTrue() throws Exception {
-		ourServlet.setDefaultPrettyPrint(false);
-		
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_pretty=true");
-		httpGet.addHeader("Accept", "text/html");
+	public void testBinaryReadAcceptMissing() throws Exception {
+		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary/foo");
+
+		HttpResponse status = ourClient.execute(httpGet);
+		byte[] responseContent = IOUtils.toByteArray(status.getEntity().getContent());
+		IOUtils.closeQuietly(status.getEntity().getContent());
+		assertEquals(200, status.getStatusLine().getStatusCode());
+		assertEquals("foo", status.getFirstHeader("content-type").getValue());
+		assertEquals("Attachment;", status.getFirstHeader("Content-Disposition").getValue());
+		assertArrayEquals(new byte[] { 1, 2, 3, 4 }, responseContent);
+
+	}
+
+	@Test
+	public void testDontHighlightWhenOriginHeaderPresent() throws Exception {
+		ResponseHighlighterInterceptor ic = ourInterceptor;
+
+		HttpServletRequest req = mock(HttpServletRequest.class);
+		when(req.getHeaders(Constants.HEADER_ACCEPT)).thenAnswer(new Answer>() {
+			@Override
+			public Enumeration answer(InvocationOnMock theInvocation) throws Throwable {
+				return new ArrayEnumeration("text/html,application/xhtml+xml,application/xml;q=0.9");
+			}
+		});
+		when(req.getHeader(Constants.HEADER_ORIGIN)).thenAnswer(new Answer() {
+			@Override
+			public String answer(InvocationOnMock theInvocation) throws Throwable {
+				return "http://example.com";
+			}
+		});
+
+		HttpServletResponse resp = mock(HttpServletResponse.class);
+		StringWriter sw = new StringWriter();
+		when(resp.getWriter()).thenReturn(new PrintWriter(sw));
+
+		Patient resource = new Patient();
+		resource.addName().addFamily("FAMILY");
+
+		ServletRequestDetails reqDetails = new TestServletRequestDetails();
+		reqDetails.setRequestType(RequestTypeEnum.GET);
+		HashMap params = new HashMap();
+		reqDetails.setParameters(params);
+		reqDetails.setServer(new RestfulServer(ourCtx));
+		reqDetails.setServletRequest(req);
+
+		// true means it decided to not handle the request..
+		assertTrue(ic.outgoingResponse(reqDetails, resource, req, resp));
+
+	}
+
+	@Test
+	public void testForceApplicationJson() throws Exception {
+		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=application/json");
+		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
 
 		HttpResponse status = ourClient.execute(httpGet);
 		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
 		IOUtils.closeQuietly(status.getEntity().getContent());
-		ourLog.info(responseContent);
 		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertThat(responseContent, (stringContainsInOrder("", "
", "")));
+		assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
+		assertThat(responseContent, not(containsString("html")));
 	}
 
-	/**
-	 * See #464
-	 */
 	@Test
-	public void testPrettyPrintDefaultsToTrueWithExplicitFalse() throws Exception {
-		ourServlet.setDefaultPrettyPrint(false);
-		
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_pretty=false");
-		httpGet.addHeader("Accept", "text/html");
+	public void testForceApplicationJsonFhir() throws Exception {
+		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=application/json+fhir");
+		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
 
 		HttpResponse status = ourClient.execute(httpGet);
 		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
 		IOUtils.closeQuietly(status.getEntity().getContent());
-		ourLog.info(responseContent);
 		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertThat(responseContent, not(stringContainsInOrder("", "
", "\n", "
"))); + assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); + assertThat(responseContent, not(containsString("html"))); + } + + @Test + public void testForceApplicationJsonPlusFhir() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=" + UrlUtil.escape("application/json+fhir")); + httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); + + HttpResponse status = ourClient.execute(httpGet); + String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + IOUtils.closeQuietly(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); + assertThat(responseContent, not(containsString("html"))); + } + + @Test + public void testForceApplicationXml() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=application/xml"); + httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); + + HttpResponse status = ourClient.execute(httpGet); + String responseContent = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals(Constants.CT_FHIR_XML + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); + assertThat(responseContent, not(containsString("html"))); + } + + @Test + public void testForceApplicationXmlFhir() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=application/xml+fhir"); + httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); + + HttpResponse status = ourClient.execute(httpGet); + String responseContent = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals(Constants.CT_FHIR_XML + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); + assertThat(responseContent, not(containsString("html"))); + } + + @Test + public void testForceApplicationXmlPlusFhir() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=" + UrlUtil.escape("application/xml+fhir")); + httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); + + HttpResponse status = ourClient.execute(httpGet); + String responseContent = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals(Constants.CT_FHIR_XML + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); + assertThat(responseContent, not(containsString("html"))); + } + + @Test + public void testForceHtmlJson() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json"); + httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); + + HttpResponse status = ourClient.execute(httpGet); + String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + IOUtils.closeQuietly(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); + assertThat(responseContent, containsString("html")); + assertThat(responseContent, containsString(">{<")); + assertThat(responseContent, not(containsString("<"))); + + ourLog.info(responseContent); + } + + @Test + public void testForceHtmlXml() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/xml"); + httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); + + HttpResponse status = ourClient.execute(httpGet); + String responseContent = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); + assertThat(responseContent, containsString("html")); + assertThat(responseContent, not(containsString(">{<"))); + assertThat(responseContent, containsString("<")); + } + + @Test + public void testForceJson() throws Exception { + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=json"); + httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"); + + HttpResponse status = ourClient.execute(httpGet); + String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + IOUtils.closeQuietly(status.getEntity().getContent()); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); + assertThat(responseContent, not(containsString("html"))); } @Test public void testForceResponseTime() throws Exception { HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json"); - + HttpResponse status = ourClient.execute(httpGet); String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); IOUtils.closeQuietly(status.getEntity().getContent()); @@ -154,74 +292,7 @@ public class ResponseHighlightingInterceptorTest { assertEquals(200, status.getStatusLine().getStatusCode()); assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); assertThat(responseContent.replace('\n', ' ').replace('\r', ' '), matchesPattern(".*Response generated in [0-9]+ms.*")); - - } - @Test - public void testShowNeither() throws Exception { - ourInterceptor.setShowRequestHeaders(false); - ourInterceptor.setShowResponseHeaders(false); - - HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json"); - - HttpResponse status = ourClient.execute(httpGet); - String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); - IOUtils.closeQuietly(status.getEntity().getContent()); - ourLog.info(responseContent); - assertEquals(200, status.getStatusLine().getStatusCode()); - assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); - assertThat(responseContent, not(containsStringIgnoringCase("Accept"))); - assertThat(responseContent, not(containsStringIgnoringCase("Content-Type"))); - } - - @Test - public void testShowResponse() throws Exception { - ourInterceptor.setShowResponseHeaders(true); - - HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json"); - - HttpResponse status = ourClient.execute(httpGet); - String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); - IOUtils.closeQuietly(status.getEntity().getContent()); - ourLog.info(responseContent); - assertEquals(200, status.getStatusLine().getStatusCode()); - assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); - assertThat(responseContent, not(containsStringIgnoringCase("Accept"))); - assertThat(responseContent, (containsStringIgnoringCase("Content-Type"))); - } - - @Test - public void testShowRequest() throws Exception { - ourInterceptor.setShowRequestHeaders(true); - ourInterceptor.setShowResponseHeaders(false); - - HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json"); - - HttpResponse status = ourClient.execute(httpGet); - String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); - IOUtils.closeQuietly(status.getEntity().getContent()); - ourLog.info(responseContent); - assertEquals(200, status.getStatusLine().getStatusCode()); - assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); - assertThat(responseContent, (containsStringIgnoringCase("Accept"))); - assertThat(responseContent, not(containsStringIgnoringCase("Content-Type"))); - } - - @Test - public void testShowRequestAndResponse() throws Exception { - ourInterceptor.setShowRequestHeaders(true); - ourInterceptor.setShowResponseHeaders(true); - - HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json"); - - HttpResponse status = ourClient.execute(httpGet); - String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); - IOUtils.closeQuietly(status.getEntity().getContent()); - ourLog.info(responseContent); - assertEquals(200, status.getStatusLine().getStatusCode()); - assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase()); - assertThat(responseContent, (containsStringIgnoringCase("Accept"))); - assertThat(responseContent, (containsStringIgnoringCase("Content-Type"))); } @Test @@ -238,7 +309,7 @@ public class ResponseHighlightingInterceptorTest { assertThat(responseContent, stringContainsInOrder("OperationOutcome", "Unknown resource type 'Foobar' - Server knows how to handle")); } - + @Test public void testGetInvalidResourceNoAcceptHeader() throws Exception { HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Foobar/123"); @@ -296,7 +367,7 @@ public class ResponseHighlightingInterceptorTest { // This can be null depending on the exception type // reqDetails.setParameters(null); - + ResourceNotFoundException exception = new ResourceNotFoundException("Not found"); exception.setOperationOutcome(new OperationOutcome().addIssue(new Issue().setDiagnostics("Hello"))); @@ -307,113 +378,6 @@ public class ResponseHighlightingInterceptorTest { assertThat(output, containsString("OperationOutcome")); } - - @Test - public void testHighlightNormalResponseForcePrettyPrint() throws Exception { - ResponseHighlighterInterceptor ic = ourInterceptor; - - HttpServletRequest req = mock(HttpServletRequest.class); - when(req.getHeaders(Constants.HEADER_ACCEPT)).thenAnswer(new Answer>() { - @Override - public Enumeration answer(InvocationOnMock theInvocation) throws Throwable { - return new ArrayEnumeration("text/html,application/xhtml+xml,application/xml;q=0.9"); - } - }); - - HttpServletResponse resp = mock(HttpServletResponse.class); - StringWriter sw = new StringWriter(); - when(resp.getWriter()).thenReturn(new PrintWriter(sw)); - - Patient resource = new Patient(); - resource.addName().addFamily("FAMILY"); - - ServletRequestDetails reqDetails = new TestServletRequestDetails(); - reqDetails.setRequestType(RequestTypeEnum.GET); - HashMap params = new HashMap(); - params.put(Constants.PARAM_PRETTY, new String[] { Constants.PARAM_PRETTY_VALUE_TRUE }); - reqDetails.setParameters(params); - reqDetails.setServer(new RestfulServer(ourCtx)); - reqDetails.setServletRequest(req); - - assertFalse(ic.outgoingResponse(reqDetails, resource, req, resp)); - - String output = sw.getBuffer().toString(); - ourLog.info(output); - assertThat(output, containsString("Patient")); - assertThat(output, stringContainsInOrder("", "
", ""));
-	}
-
-	@Test
-	public void testHighlightForceRaw() throws Exception {
-		ResponseHighlighterInterceptor ic = ourInterceptor;
-
-		HttpServletRequest req = mock(HttpServletRequest.class);
-		when(req.getHeaders(Constants.HEADER_ACCEPT)).thenAnswer(new Answer>() {
-			@Override
-			public Enumeration answer(InvocationOnMock theInvocation) throws Throwable {
-				return new ArrayEnumeration("text/html,application/xhtml+xml,application/xml;q=0.9");
-			}
-		});
-
-		HttpServletResponse resp = mock(HttpServletResponse.class);
-		StringWriter sw = new StringWriter();
-		when(resp.getWriter()).thenReturn(new PrintWriter(sw));
-
-		Patient resource = new Patient();
-		resource.addName().addFamily("FAMILY");
-
-		ServletRequestDetails reqDetails = new TestServletRequestDetails();
-		reqDetails.setRequestType(RequestTypeEnum.GET);
-		HashMap params = new HashMap();
-		params.put(Constants.PARAM_PRETTY, new String[] { Constants.PARAM_PRETTY_VALUE_TRUE });
-		params.put(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML });
-		params.put(ResponseHighlighterInterceptor.PARAM_RAW, new String[] { ResponseHighlighterInterceptor.PARAM_RAW_TRUE });
-		reqDetails.setParameters(params);
-		reqDetails.setServer(new RestfulServer(ourCtx));
-		reqDetails.setServletRequest(req);
-
-		// true means it decided to not handle the request..
-		assertTrue(ic.outgoingResponse(reqDetails, resource, req, resp));
-
-	}
-	
-	@Test
-	public void testDontHighlightWhenOriginHeaderPresent() throws Exception {
-		ResponseHighlighterInterceptor ic = ourInterceptor;
-
-		HttpServletRequest req = mock(HttpServletRequest.class);
-		when(req.getHeaders(Constants.HEADER_ACCEPT)).thenAnswer(new Answer>() {
-			@Override
-			public Enumeration answer(InvocationOnMock theInvocation) throws Throwable {
-				return new ArrayEnumeration("text/html,application/xhtml+xml,application/xml;q=0.9");
-			}
-		});
-		when(req.getHeader(Constants.HEADER_ORIGIN)).thenAnswer(new Answer() {
-			@Override
-			public String answer(InvocationOnMock theInvocation) throws Throwable {
-				return "http://example.com";
-			}
-		});
-
-		HttpServletResponse resp = mock(HttpServletResponse.class);
-		StringWriter sw = new StringWriter();
-		when(resp.getWriter()).thenReturn(new PrintWriter(sw));
-
-		Patient resource = new Patient();
-		resource.addName().addFamily("FAMILY");
-
-		ServletRequestDetails reqDetails = new TestServletRequestDetails();
-		reqDetails.setRequestType(RequestTypeEnum.GET);
-		HashMap params = new HashMap();
-		reqDetails.setParameters(params);
-		reqDetails.setServer(new RestfulServer(ourCtx));
-		reqDetails.setServletRequest(req);
-
-		// true means it decided to not handle the request..
-		assertTrue(ic.outgoingResponse(reqDetails, resource, req, resp));
-
-	}
-
 	/**
 	 * See #346
 	 */
@@ -482,6 +446,40 @@ public class ResponseHighlightingInterceptorTest {
 		assertFalse(ic.outgoingResponse(reqDetails, resource, req, resp));
 	}
 
+	@Test
+	public void testHighlightForceRaw() throws Exception {
+		ResponseHighlighterInterceptor ic = ourInterceptor;
+
+		HttpServletRequest req = mock(HttpServletRequest.class);
+		when(req.getHeaders(Constants.HEADER_ACCEPT)).thenAnswer(new Answer>() {
+			@Override
+			public Enumeration answer(InvocationOnMock theInvocation) throws Throwable {
+				return new ArrayEnumeration("text/html,application/xhtml+xml,application/xml;q=0.9");
+			}
+		});
+
+		HttpServletResponse resp = mock(HttpServletResponse.class);
+		StringWriter sw = new StringWriter();
+		when(resp.getWriter()).thenReturn(new PrintWriter(sw));
+
+		Patient resource = new Patient();
+		resource.addName().addFamily("FAMILY");
+
+		ServletRequestDetails reqDetails = new TestServletRequestDetails();
+		reqDetails.setRequestType(RequestTypeEnum.GET);
+		HashMap params = new HashMap();
+		params.put(Constants.PARAM_PRETTY, new String[] { Constants.PARAM_PRETTY_VALUE_TRUE });
+		params.put(Constants.PARAM_FORMAT, new String[] { Constants.CT_XML });
+		params.put(ResponseHighlighterInterceptor.PARAM_RAW, new String[] { ResponseHighlighterInterceptor.PARAM_RAW_TRUE });
+		reqDetails.setParameters(params);
+		reqDetails.setServer(new RestfulServer(ourCtx));
+		reqDetails.setServletRequest(req);
+
+		// true means it decided to not handle the request..
+		assertTrue(ic.outgoingResponse(reqDetails, resource, req, resp));
+
+	}
+
 	@Test
 	public void testHighlightNormalResponse() throws Exception {
 		ResponseHighlighterInterceptor ic = ourInterceptor;
@@ -516,6 +514,41 @@ public class ResponseHighlightingInterceptorTest {
 		assertThat(output, containsString(""));
 	}
 
+	@Test
+	public void testHighlightNormalResponseForcePrettyPrint() throws Exception {
+		ResponseHighlighterInterceptor ic = ourInterceptor;
+
+		HttpServletRequest req = mock(HttpServletRequest.class);
+		when(req.getHeaders(Constants.HEADER_ACCEPT)).thenAnswer(new Answer>() {
+			@Override
+			public Enumeration answer(InvocationOnMock theInvocation) throws Throwable {
+				return new ArrayEnumeration("text/html,application/xhtml+xml,application/xml;q=0.9");
+			}
+		});
+
+		HttpServletResponse resp = mock(HttpServletResponse.class);
+		StringWriter sw = new StringWriter();
+		when(resp.getWriter()).thenReturn(new PrintWriter(sw));
+
+		Patient resource = new Patient();
+		resource.addName().addFamily("FAMILY");
+
+		ServletRequestDetails reqDetails = new TestServletRequestDetails();
+		reqDetails.setRequestType(RequestTypeEnum.GET);
+		HashMap params = new HashMap();
+		params.put(Constants.PARAM_PRETTY, new String[] { Constants.PARAM_PRETTY_VALUE_TRUE });
+		reqDetails.setParameters(params);
+		reqDetails.setServer(new RestfulServer(ourCtx));
+		reqDetails.setServletRequest(req);
+
+		assertFalse(ic.outgoingResponse(reqDetails, resource, req, resp));
+
+		String output = sw.getBuffer().toString();
+		ourLog.info(output);
+		assertThat(output, containsString("Patient"));
+		assertThat(output, stringContainsInOrder("", "
", ""));
+	}
+
 	/**
 	 * Browsers declare XML but not JSON in their accept header, we should still respond using JSON if that's the default
 	 */
@@ -553,9 +586,6 @@ public class ResponseHighlightingInterceptorTest {
 		ourLog.info(output);
 		assertThat(output, containsString("resourceType"));
 	}
-
-	
-	
 	
 	@Test
 	public void testHighlightProducesDefaultJsonWithBrowserRequest2() throws Exception {
@@ -589,6 +619,60 @@ public class ResponseHighlightingInterceptorTest {
 		assertTrue(ic.outgoingResponse(reqDetails, resource, req, resp));
 	}
 
+	/**
+	 * See #464
+	 */
+	@Test
+	public void testPrettyPrintDefaultsToTrue() throws Exception {
+		ourServlet.setDefaultPrettyPrint(false);
+
+		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
+		httpGet.addHeader("Accept", "text/html");
+
+		HttpResponse status = ourClient.execute(httpGet);
+		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
+		IOUtils.closeQuietly(status.getEntity().getContent());
+		ourLog.info(responseContent);
+		assertEquals(200, status.getStatusLine().getStatusCode());
+		assertThat(responseContent, (stringContainsInOrder("", "
", "")));
+	}
+
+	/**
+	 * See #464
+	 */
+	@Test
+	public void testPrettyPrintDefaultsToTrueWithExplicitFalse() throws Exception {
+		ourServlet.setDefaultPrettyPrint(false);
+
+		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_pretty=false");
+		httpGet.addHeader("Accept", "text/html");
+
+		HttpResponse status = ourClient.execute(httpGet);
+		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
+		IOUtils.closeQuietly(status.getEntity().getContent());
+		ourLog.info(responseContent);
+		assertEquals(200, status.getStatusLine().getStatusCode());
+		assertThat(responseContent, not(stringContainsInOrder("", "
", "\n", "
"))); + } + + /** + * See #464 + */ + @Test + public void testPrettyPrintDefaultsToTrueWithExplicitTrue() throws Exception { + ourServlet.setDefaultPrettyPrint(false); + + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_pretty=true"); + httpGet.addHeader("Accept", "text/html"); + + HttpResponse status = ourClient.execute(httpGet); + String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); + IOUtils.closeQuietly(status.getEntity().getContent()); + ourLog.info(responseContent); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertThat(responseContent, (stringContainsInOrder("", "
", "")));
+	}
+
 	@Test
 	public void testSearchWithSummaryParam() throws Exception {
 		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_query=searchWithWildcardRetVal&_summary=count");
@@ -603,169 +687,75 @@ public class ResponseHighlightingInterceptorTest {
 	}
 
 	@Test
-	public void testBinaryReadAcceptMissing() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary/foo");
+	public void testShowNeither() throws Exception {
+		ourInterceptor.setShowRequestHeaders(false);
+		ourInterceptor.setShowResponseHeaders(false);
 
-		HttpResponse status = ourClient.execute(httpGet);
-		byte[] responseContent = IOUtils.toByteArray(status.getEntity().getContent());
-		IOUtils.closeQuietly(status.getEntity().getContent());
-		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals("foo", status.getFirstHeader("content-type").getValue());
-		assertEquals("Attachment;", status.getFirstHeader("Content-Disposition").getValue());
-		assertArrayEquals(new byte[] { 1, 2, 3, 4 }, responseContent);
-
-	}
-
-	@Test
-	public void testBinaryReadAcceptBrowser() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary/foo");
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		httpGet.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
-		
-		HttpResponse status = ourClient.execute(httpGet);
-		byte[] responseContent = IOUtils.toByteArray(status.getEntity().getContent());
-		IOUtils.closeQuietly(status.getEntity().getContent());
-		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals("foo", status.getFirstHeader("content-type").getValue());
-		assertEquals("Attachment;", status.getFirstHeader("Content-Disposition").getValue());
-		assertArrayEquals(new byte[] { 1, 2, 3, 4 }, responseContent);
-	}
-	
-	@Test
-	public void testBinaryReadAcceptFhirJson() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Binary/foo");
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		httpGet.addHeader("Accept", Constants.CT_FHIR_JSON);
-		
-		HttpResponse status = ourClient.execute(httpGet);
-		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
-		IOUtils.closeQuietly(status.getEntity().getContent());
-		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertNull(status.getFirstHeader("Content-Disposition"));
-		assertEquals("{\"resourceType\":\"Binary\",\"id\":\"1\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}", responseContent);
-
-	}
-	@Test
-	public void testForceApplicationJson() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=application/json");
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		
-		HttpResponse status = ourClient.execute(httpGet);
-		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
-		IOUtils.closeQuietly(status.getEntity().getContent());
-		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertThat(responseContent, not(containsString("html")));
-	}
-	@Test
-	public void testForceApplicationJsonFhir() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=application/json+fhir");
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		
-		HttpResponse status = ourClient.execute(httpGet);
-		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
-		IOUtils.closeQuietly(status.getEntity().getContent());
-		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertThat(responseContent, not(containsString("html")));
-	}
-
-	@Test
-	public void testForceApplicationJsonPlusFhir() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=" + UrlUtil.escape("application/json+fhir"));
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		
-		HttpResponse status = ourClient.execute(httpGet);
-		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
-		IOUtils.closeQuietly(status.getEntity().getContent());
-		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertThat(responseContent, not(containsString("html")));
-	}
-
-	@Test
-	public void testForceJson() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=json");
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		
-		HttpResponse status = ourClient.execute(httpGet);
-		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
-		IOUtils.closeQuietly(status.getEntity().getContent());
-		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertThat(responseContent, not(containsString("html")));
-	}
-
-
-	
-	@Test
-	public void testForceHtmlJson() throws Exception {
 		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json");
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		
+
 		HttpResponse status = ourClient.execute(httpGet);
 		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
 		IOUtils.closeQuietly(status.getEntity().getContent());
-		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertThat(responseContent, containsString("html"));
-		assertThat(responseContent, containsString(">{<"));
-		assertThat(responseContent, not(containsString("<")));
-		
 		ourLog.info(responseContent);
-	}
-	
-	@Test
-	public void testForceHtmlXml() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/xml");
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		
-		HttpResponse status = ourClient.execute(httpGet);
-		String responseContent = IOUtils.toString(status.getEntity().getContent());
-		IOUtils.closeQuietly(status.getEntity().getContent());
 		assertEquals(200, status.getStatusLine().getStatusCode());
 		assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertThat(responseContent, containsString("html"));
-		assertThat(responseContent, not(containsString(">{<")));
-		assertThat(responseContent, containsString("<"));
+		assertThat(responseContent, not(containsStringIgnoringCase("Accept")));
+		assertThat(responseContent, not(containsStringIgnoringCase("Content-Type")));
 	}
 	
 	@Test
-	public void testForceApplicationXml() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=application/xml");
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		
+	public void testShowRequest() throws Exception {
+		ourInterceptor.setShowRequestHeaders(true);
+		ourInterceptor.setShowResponseHeaders(false);
+
+		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json");
+
 		HttpResponse status = ourClient.execute(httpGet);
-		String responseContent = IOUtils.toString(status.getEntity().getContent());
+		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
 		IOUtils.closeQuietly(status.getEntity().getContent());
+		ourLog.info(responseContent);
 		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals(Constants.CT_FHIR_XML + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertThat(responseContent, not(containsString("html")));
+		assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
+		assertThat(responseContent, (containsStringIgnoringCase("Accept")));
+		assertThat(responseContent, not(containsStringIgnoringCase("Content-Type")));
 	}
+	
 	@Test
-	public void testForceApplicationXmlFhir() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=application/xml+fhir");
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		
+	public void testShowRequestAndResponse() throws Exception {
+		ourInterceptor.setShowRequestHeaders(true);
+		ourInterceptor.setShowResponseHeaders(true);
+
+		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json");
+
 		HttpResponse status = ourClient.execute(httpGet);
-		String responseContent = IOUtils.toString(status.getEntity().getContent());
+		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
 		IOUtils.closeQuietly(status.getEntity().getContent());
+		ourLog.info(responseContent);
 		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals(Constants.CT_FHIR_XML + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertThat(responseContent, not(containsString("html")));
+		assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
+		assertThat(responseContent, (containsStringIgnoringCase("Accept")));
+		assertThat(responseContent, (containsStringIgnoringCase("Content-Type")));
 	}
+
 	@Test
-	public void testForceApplicationXmlPlusFhir() throws Exception {
-		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=" + UrlUtil.escape("application/xml+fhir"));
-		httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
-		
+	public void testShowResponse() throws Exception {
+		ourInterceptor.setShowResponseHeaders(true);
+
+		HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json");
+
 		HttpResponse status = ourClient.execute(httpGet);
-		String responseContent = IOUtils.toString(status.getEntity().getContent());
+		String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
 		IOUtils.closeQuietly(status.getEntity().getContent());
+		ourLog.info(responseContent);
 		assertEquals(200, status.getStatusLine().getStatusCode());
-		assertEquals(Constants.CT_FHIR_XML + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
-		assertThat(responseContent, not(containsString("html")));
+		assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
+		assertThat(responseContent, not(containsStringIgnoringCase("Accept")));
+		assertThat(responseContent, (containsStringIgnoringCase("Content-Type")));
+	}
+
+	@AfterClass
+	public static void afterClassClearContext() {
+		TestUtil.clearAllStaticFieldsForUnitTest();
 	}
 
 	@BeforeClass
@@ -812,6 +802,13 @@ public class ResponseHighlightingInterceptorTest {
 
 	}
 	
+	class TestServletRequestDetails extends ServletRequestDetails {
+		@Override
+		public String getServerBaseForRequest() {
+			return "/baseDstu3";
+		}
+	}
+
 	public static class DummyBinaryResourceProvider implements IResourceProvider {
 
 		@Override
@@ -839,7 +836,6 @@ public class ResponseHighlightingInterceptorTest {
 
 	}
 
-
 	public static class DummyPatientResourceProvider implements IResourceProvider {
 
 		private Patient createPatient1() {
@@ -898,7 +894,7 @@ public class ResponseHighlightingInterceptorTest {
 
 		/**
 		 * Retrieve the resource by its identifier
-		 * 
+		 *
 		 * @param theId
 		 *           The resource identity
 		 * @return The resource
@@ -912,7 +908,7 @@ public class ResponseHighlightingInterceptorTest {
 
 		/**
 		 * Retrieve the resource by its identifier
-		 * 
+		 *
 		 * @param theId
 		 *           The resource identity
 		 * @return The resource
@@ -942,11 +938,4 @@ public class ResponseHighlightingInterceptorTest {
 
 	}
 
-	class TestServletRequestDetails extends ServletRequestDetails {
-		@Override
-		public String getServerBaseForRequest() {
-			return "/baseDstu3";
-		}
-	}
-
 }
diff --git a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ExamineTestTrace.java b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ExamineTestTrace.java
index 4a1e9a74555..6f36d5b953d 100644
--- a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ExamineTestTrace.java
+++ b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ExamineTestTrace.java
@@ -14,12 +14,18 @@ public class ExamineTestTrace {
 	private static final Logger ourLog = LoggerFactory.getLogger(ExamineTestTrace.class);
 
 	public static void main(String[] aaa) {
-		String input = "Running ca.uhn.fhir.model.primitive.BaseResourceReferenceDtTest\n" +
-			"Tests run: 8, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.896 sec - in ca.uhn.fhir.rest.server.OperationServerWithSearchParamTypesDstu2Test";
+		String input = "[INFO] Running ca.uhn.fhir.rest.client.RestfulClientFactoryDstu2Test\n" +
+			"[INFO] Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.982 s - in ca.uhn.fhir.validation.ResourceValidatorDstu2Test";
 
 		Set started = new HashSet<>();
 		Set finished = new HashSet<>();
 		for (String next : input.split("\n")) {
+			if (next.startsWith("[INFO] ")) {
+				next = next.substring("[INFO] ".length());
+			}
+			if (next.startsWith("[WARNING] ")) {
+				next = next.substring("[WARNING] ".length());
+			}
 			if (next.startsWith("Running ")) {
 				started.add(next.substring("Running ".length()));
 			} else if (next.startsWith("Tests run: ")) {
@@ -27,7 +33,7 @@ public class ExamineTestTrace {
 			} else if (isBlank(next)) {
 				continue;
 			} else {
-				throw new IllegalStateException();
+				throw new IllegalStateException("Unknown line: " + next);
 			}
 		}