Fix #837 - Use non-legacy content-type for plain json and xml accept

header
This commit is contained in:
jamesagnew 2018-02-02 06:43:19 -05:00
parent ad8eb0b939
commit 351a2fc2f1
5 changed files with 291 additions and 243 deletions

View File

@ -9,9 +9,9 @@ package ca.uhn.fhir.rest.api;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -19,12 +19,14 @@ package ca.uhn.fhir.rest.api;
* limitations under the License.
* #L%
*/
import java.util.*;
import org.apache.commons.lang3.ObjectUtils;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.IParser;
import org.apache.commons.lang3.ObjectUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public enum EncodingEnum {
@ -40,39 +42,40 @@ public enum EncodingEnum {
public IParser newParser(FhirContext theContext) {
return theContext.newXmlParser();
}
}
};
;
/** "json" */
public static final String JSON_PLAIN_STRING = "json";
private static Map<String, EncodingEnum> ourContentTypeToEncoding;
private static Map<String, EncodingEnum> ourContentTypeToEncodingNonLegacy;
private static Map<String, EncodingEnum> ourContentTypeToEncodingStrict;
/** "xml" */
/**
* "json"
*/
public static final String JSON_PLAIN_STRING = "json";
/**
* "xml"
*/
public static final String XML_PLAIN_STRING = "xml";
private static Map<String, EncodingEnum> ourContentTypeToEncoding;
private static Map<String, EncodingEnum> ourContentTypeToEncodingLegacy;
private static Map<String, EncodingEnum> ourContentTypeToEncodingStrict;
static {
ourContentTypeToEncoding = new HashMap<String, EncodingEnum>();
ourContentTypeToEncodingNonLegacy = new HashMap<String, EncodingEnum>();
ourContentTypeToEncoding = new HashMap<>();
ourContentTypeToEncodingLegacy = new HashMap<>();
for (EncodingEnum next : values()) {
ourContentTypeToEncoding.put(next.myResourceContentTypeNonLegacy, next);
ourContentTypeToEncoding.put(next.myResourceContentTypeLegacy, next);
ourContentTypeToEncodingNonLegacy.put(next.myResourceContentTypeNonLegacy, next);
ourContentTypeToEncodingLegacy.put(next.myResourceContentTypeLegacy, next);
/*
* See #346
*/
ourContentTypeToEncoding.put(next.myResourceContentTypeNonLegacy.replace('+', ' '), next);
ourContentTypeToEncoding.put(next.myResourceContentTypeLegacy.replace('+', ' '), next);
ourContentTypeToEncodingNonLegacy.put(next.myResourceContentTypeNonLegacy.replace('+', ' '), next);
ourContentTypeToEncodingLegacy.put(next.myResourceContentTypeLegacy.replace('+', ' '), next);
}
// Add before we add the lenient ones
ourContentTypeToEncodingStrict = Collections.unmodifiableMap(new HashMap<String, EncodingEnum>(ourContentTypeToEncoding));
ourContentTypeToEncodingStrict = Collections.unmodifiableMap(new HashMap<>(ourContentTypeToEncoding));
/*
* These are wrong, but we add them just to be tolerant of other
@ -89,7 +92,7 @@ public enum EncodingEnum {
ourContentTypeToEncoding.put(JSON_PLAIN_STRING, JSON);
ourContentTypeToEncoding.put(XML_PLAIN_STRING, XML);
ourContentTypeToEncodingNonLegacy = Collections.unmodifiableMap(ourContentTypeToEncodingNonLegacy);
ourContentTypeToEncodingLegacy = Collections.unmodifiableMap(ourContentTypeToEncodingLegacy);
}
@ -107,10 +110,6 @@ public enum EncodingEnum {
return myFormatContentType;
}
public String getRequestContentType() {
return myFormatContentType;
}
/**
* Will return application/xml+fhir style
*/
@ -150,7 +149,7 @@ public enum EncodingEnum {
/**
* Returns the encoding for a given content type, or <code>null</code> if no encoding
* is found.
* is found.
* <p>
* <b>This method is lenient!</b> Things like "application/xml" will return {@link EncodingEnum#XML}
* even if the "+fhir" part is missing from the expected content type.
@ -163,19 +162,23 @@ public enum EncodingEnum {
/**
* Returns the encoding for a given content type, or <code>null</code> if no encoding
* is found.
* is found.
* <p>
* <b>This method is NOT lenient!</b> Things like "application/xml" will return <code>null</code>
* </p>
*
* @see #forContentType(String)
*/
public static EncodingEnum forContentTypeStrict(String theContentType) {
return ourContentTypeToEncodingStrict.get(theContentType);
}
public static boolean isNonLegacy(String theFormat) {
return ourContentTypeToEncodingNonLegacy.containsKey(theFormat);
/**
* Is the given type a FHIR legacy (pre-DSTU3) content type?
*/
public static boolean isLegacy(String theFormat) {
return ourContentTypeToEncodingLegacy.containsKey(theFormat);
}
}

View File

@ -764,12 +764,11 @@ public class RestfulServerUtils {
super();
myEncoding = theEncoding;
if (theContentType != null) {
FhirVersionEnum ctxtEnum = theCtx.getVersion().getVersion();
if (theContentType.equals(EncodingEnum.JSON_PLAIN_STRING) || theContentType.equals(EncodingEnum.XML_PLAIN_STRING)) {
FhirVersionEnum ctxtEnum = theCtx.getVersion().getVersion();
myNonLegacy = ctxtEnum.isNewerThan(FhirVersionEnum.DSTU3)
|| (ctxtEnum.isEquivalentTo(FhirVersionEnum.DSTU3) && !"1.4.0".equals(theCtx.getVersion().getVersion().getFhirVersionString()));
myNonLegacy = ctxtEnum.isNewerThan(FhirVersionEnum.DSTU2);
} else {
myNonLegacy = EncodingEnum.isNonLegacy(theContentType);
myNonLegacy = ctxtEnum.isNewerThan(FhirVersionEnum.DSTU2) && !EncodingEnum.isLegacy(theContentType);
}
} else {
FhirVersionEnum ctxtEnum = theCtx.getVersion().getVersion();

View File

@ -1,18 +1,13 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.MyPatientWithExtensions;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.*;
@ -26,23 +21,45 @@ import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.*;
import org.junit.*;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.MyPatientWithExtensions;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class ServerMimetypeR4Test {
private static CloseableHttpClient ourClient;
private static FhirContext ourCtx = FhirContext.forR4();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerMimetypeR4Test.class);
private static CloseableHttpClient ourClient;
private static FhirContext ourCtx = FhirContext.forR4();
private static int ourPort;
private static Server ourServer;
private static RestfulServer ourServlet;
@Before
public void before() {
ourServlet.setDefaultResponseEncoding(EncodingEnum.XML);
}
private String readAndReturnContentType(String theAccept) throws IOException {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
if (theAccept != null) {
httpGet.addHeader(Constants.HEADER_ACCEPT, theAccept);
}
HttpResponse status = ourClient.execute(httpGet);
String contentType = status.getEntity().getContentType().getValue();
IOUtils.closeQuietly(status.getEntity().getContent());
contentType = contentType.replaceAll(";.*", "");
return contentType;
}
@Test
public void testConformanceMetadataUsesNewMimetypes() throws Exception {
@ -57,25 +74,74 @@ public class ServerMimetypeR4Test {
status.close();
}
}
private List<String> toStrings(List<CodeType> theFormat) {
ArrayList<String> retVal = new ArrayList<String>();
for (CodeType next : theFormat) {
retVal.add(next.asStringValue());
}
return retVal;
@Test
public void testCreateWithJsonLegacyNoAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newJsonParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_JSON, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent);
}
@Test
public void testCreateWithJsonNewNoAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newJsonParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON_NEW + "; charset=utf-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent);
}
@Test
public void testCreateWithJsonNewWithAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newJsonParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8")));
httpPost.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON_NEW);
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent);
}
@Test
public void testCreateWithXmlLegacyNoAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
HttpResponse status = ourClient.execute(httpPost);
@ -90,6 +156,47 @@ public class ServerMimetypeR4Test {
assertEquals("<OperationOutcome xmlns=\"http://hl7.org/fhir\"><issue><diagnostics value=\"FAMILY\"/></issue></OperationOutcome>", responseContent);
}
@Test
public void testCreateWithXmlNewNoAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML_NEW + "; charset=utf-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("<OperationOutcome xmlns=\"http://hl7.org/fhir\"><issue><diagnostics value=\"FAMILY\"/></issue></OperationOutcome>", responseContent);
}
@Test
public void testCreateWithXmlNewWithAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
httpPost.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML_NEW);
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("<OperationOutcome xmlns=\"http://hl7.org/fhir\"><issue><diagnostics value=\"FAMILY\"/></issue></OperationOutcome>", responseContent);
}
@Test
public void testHttpTraceNotEnabled() throws Exception {
HttpTrace req = new HttpTrace("http://localhost:" + ourPort + "/Patient");
@ -108,9 +215,10 @@ public class ServerMimetypeR4Test {
@Override
public String getMethod() {
return "TRACK";
}};
}
};
req.setURI(new URI("http://localhost:" + ourPort + "/Patient"));
CloseableHttpResponse status = ourClient.execute(req);
try {
ourLog.info(status.toString());
@ -120,112 +228,56 @@ public class ServerMimetypeR4Test {
}
}
/**
* See #837
*/
@Test
public void testCreateWithXmlNewNoAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML_NEW + "; charset=utf-8")));
HttpResponse status = ourClient.execute(httpPost);
public void testResponseContentTypesJson() throws IOException {
ourServlet.setDefaultResponseEncoding(EncodingEnum.XML);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
// None given
assertEquals("application/fhir+xml", readAndReturnContentType(null));
ourLog.info("Response was:\n{}", responseContent);
// Legacy given
assertEquals("application/json+fhir", readAndReturnContentType("application/json+fhir"));
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("<OperationOutcome xmlns=\"http://hl7.org/fhir\"><issue><diagnostics value=\"FAMILY\"/></issue></OperationOutcome>", responseContent);
// Everything else JSON
assertEquals("application/fhir+json", readAndReturnContentType("application/fhir+json"));
assertEquals("application/fhir+json", readAndReturnContentType("application/json"));
assertEquals("application/fhir+json", readAndReturnContentType("application/fhir+json,application/json;q=0.9"));
assertEquals("application/fhir+json", readAndReturnContentType("json"));
// Invalid
assertEquals("application/fhir+xml", readAndReturnContentType("text/plain"));
}
/**
* See #837
*/
@Test
public void testResponseContentTypesXml() throws IOException {
ourServlet.setDefaultResponseEncoding(EncodingEnum.JSON);
// None given
assertEquals("application/fhir+json", readAndReturnContentType(null));
// Legacy given
assertEquals("application/xml+fhir", readAndReturnContentType("application/xml+fhir"));
// Everything else JSON
assertEquals("application/fhir+xml", readAndReturnContentType("application/fhir+xml"));
assertEquals("application/fhir+xml", readAndReturnContentType("application/xml"));
assertEquals("application/fhir+xml", readAndReturnContentType("application/fhir+xml,application/xml;q=0.9"));
assertEquals("application/fhir+xml", readAndReturnContentType("xml"));
// Invalid
assertEquals("application/fhir+json", readAndReturnContentType("text/plain"));
}
@Test
public void testCreateWithXmlNewWithAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newXmlParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
httpPost.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML_NEW);
HttpResponse status = ourClient.execute(httpPost);
public void testSearchWithFormatJsonLegacy() throws Exception {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("<OperationOutcome xmlns=\"http://hl7.org/fhir\"><issue><diagnostics value=\"FAMILY\"/></issue></OperationOutcome>", responseContent);
}
@Test
public void testCreateWithJsonLegacyNoAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newJsonParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_JSON, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent);
}
@Test
public void testCreateWithJsonNewNoAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newJsonParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON_NEW + "; charset=utf-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent);
}
@Test
public void testCreateWithJsonNewWithAcceptHeader() throws Exception {
Patient p = new Patient();
p.addName().setFamily("FAMILY");
String enc = ourCtx.newJsonParser().encodeResourceToString(p);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
httpPost.setEntity(new StringEntity(enc, ContentType.parse(Constants.CT_FHIR_JSON + "; charset=utf-8")));
httpPost.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON_NEW);
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertEquals("{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"diagnostics\":\"FAMILY\"}]}", responseContent);
}
@Test
public void testSearchWithFormatXmlSimple() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=xml");
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=" + Constants.CT_FHIR_JSON);
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
@ -234,9 +286,40 @@ public class ServerMimetypeR4Test {
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("<Patient xmlns=\"http://hl7.org/fhir\">"));
assertThat(responseContent, not(containsString("http://hl7.org/fhir/")));
assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
assertThat(responseContent, containsString("\"resourceType\""));
assertEquals(Constants.CT_FHIR_JSON, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
}
@Test
public void testSearchWithFormatJsonNew() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=" + Constants.CT_FHIR_JSON_NEW);
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("\"resourceType\""));
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
}
@Test
public void testSearchWithFormatJsonSimple() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=json");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("\"resourceType\""));
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
}
@Test
@ -273,77 +356,29 @@ public class ServerMimetypeR4Test {
assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
}
/**
* See #837
*/
@Test
public void testResponseContentTypes() throws IOException {
assertEquals("application/fhir+json", readAndReturnContentType("application/fhir+json"));
assertEquals("application/fhir+xml", readAndReturnContentType(null));
assertEquals("application/json+fhir", readAndReturnContentType("application/json+fhir"));
assertEquals("application/json+fhir", readAndReturnContentType("application/json"));
assertEquals("application/fhir+json", readAndReturnContentType("application/fhir+json,application/json;q=0.9"));
public void testSearchWithFormatXmlSimple() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=xml");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("<Patient xmlns=\"http://hl7.org/fhir\">"));
assertThat(responseContent, not(containsString("http://hl7.org/fhir/")));
assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
}
private String readAndReturnContentType(String theAccept) throws IOException {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
if (theAccept != null) {
httpGet.addHeader(Constants.HEADER_ACCEPT, theAccept);
private List<String> toStrings(List<CodeType> theFormat) {
ArrayList<String> retVal = new ArrayList<String>();
for (CodeType next : theFormat) {
retVal.add(next.asStringValue());
}
HttpResponse status = ourClient.execute(httpGet);
String contentType = status.getEntity().getContentType().getValue();
IOUtils.closeQuietly(status.getEntity().getContent());
contentType = contentType.replaceAll(";.*","");
return contentType;
}
@Test
public void testSearchWithFormatJsonSimple() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=json");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("\"resourceType\""));
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
}
@Test
public void testSearchWithFormatJsonLegacy() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=" + 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("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("\"resourceType\""));
assertEquals(Constants.CT_FHIR_JSON, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
}
@Test
public void testSearchWithFormatJsonNew() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=" + Constants.CT_FHIR_JSON_NEW);
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
assertThat(responseContent, containsString("\"resourceType\""));
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
return retVal;
}
@AfterClass
@ -360,10 +395,10 @@ public class ServerMimetypeR4Test {
PatientProvider patientProvider = new PatientProvider();
ServletHandler proxyHandler = new ServletHandler();
RestfulServer servlet = new RestfulServer(ourCtx);
ourServlet = new RestfulServer(ourCtx);
servlet.setResourceProviders(patientProvider);
ServletHolder servletHolder = new ServletHolder(servlet);
ourServlet.setResourceProviders(patientProvider);
ServletHolder servletHolder = new ServletHolder(ourServlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
ourServer.setHandler(proxyHandler);
ourServer.start();

View File

@ -334,7 +334,7 @@ public class Controller extends BaseController {
if (client.getEncoding() != null) {
clientCodeJsonWriter.name("format");
clientCodeJsonWriter.value(client.getEncoding().getRequestContentType());
clientCodeJsonWriter.value(client.getEncoding().getFormatContentType());
} else {
clientCodeJsonWriter.name("format");
clientCodeJsonWriter.nullValue();

View File

@ -98,6 +98,17 @@
to build correctly on JDK 9.0. Currently building is supported on
JDK 8.x and 9.x only.
</action>
<action type="fix" issue="837">
Client requests with an
<![CDATA[<code>Accept</code>]]>
header value of
<![CDATA[<code>application/json</code>]]>
will now be served with the non-legacy content type of
<![CDATA[<code>application/fhir+json</code>]]>
instead of the legacy
<![CDATA[<code>application/json+fhir</code>]]>.
Thanks to John Grimes for reporting!
</action>
</release>
<release version="3.2.0" date="2018-01-13">
<action type="add">