diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java index cde6942e331..98e4c0671d4 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java @@ -149,6 +149,7 @@ public class MethodOutcome { * @param theCreated * If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called * whether the result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist. + * @return Returns a reference to this for easy method chaining */ public MethodOutcome setCreated(Boolean theCreated) { myCreated = theCreated; @@ -158,16 +159,20 @@ public class MethodOutcome { /** * @param theId * The ID of the created/updated resource + * @return Returns a reference to this for easy method chaining */ - public void setId(IIdType theId) { + public MethodOutcome setId(IIdType theId) { myId = theId; + return this; } /** * Sets the {@link IBaseOperationOutcome} resource to return to the client. Set to null (which is the default) if none. + * @return Returns a reference to this for easy method chaining */ - public void setOperationOutcome(IBaseOperationOutcome theBaseOperationOutcome) { + public MethodOutcome setOperationOutcome(IBaseOperationOutcome theBaseOperationOutcome) { myOperationOutcome = theBaseOperationOutcome; + return this; } /** @@ -178,9 +183,11 @@ public class MethodOutcome { * This field is optional, but if it is populated the server will return the resource body if requested to * do so via the HTTP Prefer header. *

+ * @return Returns a reference to this for easy method chaining */ - public void setResource(IBaseResource theResource) { + public MethodOutcome setResource(IBaseResource theResource) { myResource = theResource; + return this; } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java index 1da6d932a4a..7af96417244 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseClient.java @@ -214,12 +214,14 @@ public abstract class BaseClient implements IRestfulClient { try { Map> params = createExtraParams(); - if (theEncoding == EncodingEnum.XML) { - params.put(Constants.PARAM_FORMAT, Collections.singletonList("xml")); - } else if (theEncoding == EncodingEnum.JSON) { - params.put(Constants.PARAM_FORMAT, Collections.singletonList("json")); + if (clientInvocation instanceof HttpGetClientInvocation) { + if (theEncoding == EncodingEnum.XML) { + params.put(Constants.PARAM_FORMAT, Collections.singletonList("xml")); + } else if (theEncoding == EncodingEnum.JSON) { + params.put(Constants.PARAM_FORMAT, Collections.singletonList("json")); + } } - + if (theSummaryMode != null) { params.put(Constants.PARAM_SUMMARY, Collections.singletonList(theSummaryMode.getCode())); } else if (mySummary != null) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/apache/ApacheHttpClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/apache/ApacheHttpClient.java index 350ed578ec1..48ac411ea50 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/apache/ApacheHttpClient.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/apache/ApacheHttpClient.java @@ -49,6 +49,7 @@ import ca.uhn.fhir.rest.client.api.IHttpClient; import ca.uhn.fhir.rest.client.api.IHttpRequest; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.EncodingEnum; +import ca.uhn.fhir.rest.server.RestfulServerUtils; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.VersionUtil; @@ -148,13 +149,7 @@ public class ApacheHttpClient implements IHttpClient { theHttpRequest.addHeader("Accept-Charset", "utf-8"); theHttpRequest.addHeader("Accept-Encoding", "gzip"); - if (theEncoding == null) { - theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON); - } else if (theEncoding == EncodingEnum.JSON) { - theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON); - } else if (theEncoding == EncodingEnum.XML) { - theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML); - } + RestfulServerUtils.addAcceptHeaderToRequest(theEncoding, theHttpRequest, theContext); } private ApacheHttpRequest createHttpRequest(HttpEntity theEntity) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/StringCriterion.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/StringCriterion.java index 15b035b963b..2492a4be1bd 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/StringCriterion.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/StringCriterion.java @@ -1,5 +1,7 @@ package ca.uhn.fhir.rest.gclient; +import static org.apache.commons.lang3.StringUtils.isBlank; + import java.util.List; import org.apache.commons.lang3.StringUtils; @@ -67,6 +69,9 @@ class StringCriterion implements ICriterion, ICriterionInte @Override public String getParameterValue(FhirContext theContext) { + if (isBlank(myValue)) { + return ""; + } if (myPrefix != null) { return myPrefix.getValueForContext(theContext) + myValue; } 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 c2068a85d78..89921da720d 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 @@ -58,6 +58,7 @@ import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.IRestfulServer; import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory; import ca.uhn.fhir.rest.server.RestfulServerUtils; +import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; @@ -372,8 +373,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory(); - EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding()); - EncodingEnum linkEncoding = theRequest.getParameters().containsKey(Constants.PARAM_FORMAT) ? responseEncoding : null; + ResponseEncoding responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding()); + EncodingEnum linkEncoding = theRequest.getParameters().containsKey(Constants.PARAM_FORMAT) && responseEncoding != null ? responseEncoding.getEncoding() : null; boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest); bundleFactory.initializeBundleFromBundleProvider(theServer, result, linkEncoding, theRequest.getFhirServerBase(), linkSelf, prettyPrint, start, count, null, getResponseBundleType(), includes); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpPostClientInvocation.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpPostClientInvocation.java index 5426eda3aef..54b364050a0 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpPostClientInvocation.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/HttpPostClientInvocation.java @@ -62,6 +62,7 @@ public class HttpPostClientInvocation extends BaseHttpClientInvocationWithConten super(theContext, theParams, theUrlExtension); } + @Override protected RequestTypeEnum getRequestType() { return RequestTypeEnum.POST; } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PageMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PageMethodBinding.java index ed30812773a..2fb108c1401 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PageMethodBinding.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/PageMethodBinding.java @@ -26,8 +26,6 @@ import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; -import javax.servlet.http.HttpServletResponse; - import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -45,6 +43,7 @@ import ca.uhn.fhir.rest.server.IPagingProvider; import ca.uhn.fhir.rest.server.IRestfulServer; import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory; import ca.uhn.fhir.rest.server.RestfulServerUtils; +import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; @@ -74,12 +73,12 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding { @Override public Object invokeServer(IRestfulServer theServer, RequestDetails theRequest, Object[] theMethodParams) throws InvalidRequestException, InternalErrorException { - return handlePagingRequest(theServer, theRequest, null, theRequest.getParameters().get(Constants.PARAM_PAGINGACTION)[0]); + return handlePagingRequest(theServer, theRequest, theRequest.getParameters().get(Constants.PARAM_PAGINGACTION)[0]); } @Override public ResourceOrDstu1Bundle doInvokeServer(IRestfulServer theServer, RequestDetails theRequest) { - IBase bundle = handlePagingRequest(theServer, theRequest, null, theRequest.getParameters().get(Constants.PARAM_PAGINGACTION)[0]); + IBase bundle = handlePagingRequest(theServer, theRequest, theRequest.getParameters().get(Constants.PARAM_PAGINGACTION)[0]); if (bundle instanceof Bundle) { return new ResourceOrDstu1Bundle((Bundle) bundle); } else { @@ -87,7 +86,7 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding { } } - private IBase handlePagingRequest(IRestfulServer theServer, RequestDetails theRequest, HttpServletResponse theResponse, String thePagingAction) { + private IBase handlePagingRequest(IRestfulServer theServer, RequestDetails theRequest, String thePagingAction) { IPagingProvider pagingProvider = theServer.getPagingProvider(); if (pagingProvider == null) { throw new InvalidRequestException("This server does not support paging"); @@ -112,7 +111,7 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding { int start = Math.min(offsetI, resultList.size() - 1); - EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding()); + ResponseEncoding responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding()); boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theServer, theRequest); IVersionSpecificBundleFactory bundleFactory = theServer.getFhirContext().newBundleFactory(); @@ -136,7 +135,11 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding { bundleType = BundleTypeEnum.VALUESET_BINDER.fromCodeString(bundleTypeValues[0]); } - bundleFactory.initializeBundleFromBundleProvider(theServer, resultList, responseEncoding, theRequest.getFhirServerBase(), linkSelf, prettyPrint, start, count, thePagingAction, bundleType, includes); + EncodingEnum encodingEnum = null; + if (responseEncoding != null) { + encodingEnum = responseEncoding.getEncoding(); + } + bundleFactory.initializeBundleFromBundleProvider(theServer, resultList, encodingEnum, theRequest.getFhirServerBase(), linkSelf, prettyPrint, start, count, thePagingAction, bundleType, includes); Bundle bundle = bundleFactory.getDstu1Bundle(); if (bundle != null) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ResourceParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ResourceParameter.java index c81556c4e29..8027d96d043 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ResourceParameter.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ResourceParameter.java @@ -111,7 +111,7 @@ public class ResourceParameter implements IParameter { case BODY_BYTE_ARRAY: return theRequest.loadRequestContents(); case ENCODING: - return RestfulServerUtils.determineRequestEncoding(theRequest); + return RestfulServerUtils.determineRequestEncodingNoDefault(theRequest); case RESOURCE: default: return parseResourceFromRequest(theRequest, theMethodBinding, myResourceType); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java index 5483257cf84..69927cae815 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java @@ -34,7 +34,9 @@ public class Constants { public static final String CHARSET_UTF8_CTSUFFIX = "; charset=" + CHARSET_NAME_UTF8; public static final String CT_ATOM_XML = "application/atom+xml"; public static final String CT_FHIR_JSON = "application/json+fhir"; + public static final String CT_FHIR_JSON_NEW = "application/fhir+json"; public static final String CT_FHIR_XML = "application/xml+fhir"; + public static final String CT_FHIR_XML_NEW = "application/fhir+xml"; public static final String CT_HTML = "text/html"; public static final String CT_HTML_WITH_UTF8 = "text/html" + CHARSET_UTF8_CTSUFFIX; public static final String CT_JSON = "application/json"; @@ -50,9 +52,6 @@ public class Constants { public static final String EXTOP_VALIDATE_RESOURCE = "resource"; public static final String FORMAT_HTML = "html"; public static final String FORMAT_JSON = "json"; - public static final Set FORMAT_VAL_JSON; - public static final Map FORMAT_VAL_TO_ENCODING; - public static final Set FORMAT_VAL_XML; public static final String FORMAT_XML = "xml"; /** * "text/html" and "html" @@ -62,7 +61,8 @@ public class Constants { public static final String FORMATS_HTML_XML = "html/xml"; public static final String HEADER_ACCEPT = "Accept"; public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; - public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON = CT_FHIR_XML + ";q=1.0, " + CT_FHIR_JSON + ";q=1.0"; + public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY = CT_FHIR_XML + ";q=1.0, " + CT_FHIR_JSON + ";q=1.0"; + public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON_NON_LEGACY = CT_FHIR_XML_NEW + ";q=1.0, " + CT_FHIR_JSON_NEW + ";q=1.0, " + HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY.replace("1.0", "0.9"); public static final String HEADER_ALLOW = "Allow"; public static final String HEADER_AUTHORIZATION = "Authorization"; public static final String HEADER_AUTHORIZATION_VALPREFIX_BASIC = "Basic "; @@ -167,32 +167,6 @@ public class Constants { public static final String URL_TOKEN_METADATA = "metadata"; static { - Map valToEncoding = new HashMap(); - - HashSet valXml = new HashSet(); - valXml.add(CT_FHIR_XML); - valXml.add(CT_FHIR_XML.replace('+', ' ')); // See #346 - valXml.add("text/xml"); - valXml.add("application/xml"); - valXml.add("xml"); - FORMAT_VAL_XML = Collections.unmodifiableSet(valXml); - for (String string : valXml) { - valToEncoding.put(string, EncodingEnum.XML); - } - - HashSet valJson = new HashSet(); - valJson.add(CT_FHIR_JSON); - valJson.add(CT_FHIR_JSON.replace('+', ' ')); // See #346 - valJson.add("text/json"); - valJson.add("application/json"); - valJson.add("json"); - FORMAT_VAL_JSON = Collections.unmodifiableSet(valJson); - for (String string : valJson) { - valToEncoding.put(string, EncodingEnum.JSON); - } - - FORMAT_VAL_TO_ENCODING = Collections.unmodifiableMap(valToEncoding); - CHARSET_UTF8 = Charset.forName(CHARSET_NAME_UTF8); HashMap statusNames = new HashMap(); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/EncodingEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/EncodingEnum.java index 7dc4380632a..3d1dadce725 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/EncodingEnum.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/EncodingEnum.java @@ -30,34 +30,40 @@ import ca.uhn.fhir.parser.IParser; public enum EncodingEnum { - XML(Constants.CT_FHIR_XML, Constants.CT_ATOM_XML, Constants.FORMAT_XML) { - @Override - public IParser newParser(FhirContext theContext) { - return theContext.newXmlParser(); - } - }, - - JSON(Constants.CT_FHIR_JSON, Constants.CT_FHIR_JSON, Constants.FORMAT_JSON) { + JSON(Constants.CT_FHIR_JSON, Constants.CT_FHIR_JSON_NEW, Constants.CT_FHIR_JSON, Constants.FORMAT_JSON) { @Override public IParser newParser(FhirContext theContext) { return theContext.newJsonParser(); } + }, + + XML(Constants.CT_FHIR_XML, Constants.CT_FHIR_XML_NEW, Constants.CT_ATOM_XML, Constants.FORMAT_XML) { + @Override + public IParser newParser(FhirContext theContext) { + return theContext.newXmlParser(); + } } ; private static Map ourContentTypeToEncoding; + private static Map ourContentTypeToEncodingNonLegacy; private static Map ourContentTypeToEncodingStrict; static { ourContentTypeToEncoding = new HashMap(); + ourContentTypeToEncodingNonLegacy = new HashMap(); for (EncodingEnum next : values()) { ourContentTypeToEncoding.put(next.getBundleContentType(), next); - ourContentTypeToEncoding.put(next.getResourceContentType(), next); + ourContentTypeToEncoding.put(next.myResourceContentTypeNonLegacy, next); + ourContentTypeToEncoding.put(next.myResourceContentTypeLegacy, next); + + ourContentTypeToEncodingNonLegacy.put(next.myResourceContentTypeNonLegacy, next); } // Add before we add the lenient ones ourContentTypeToEncodingStrict = Collections.unmodifiableMap(new HashMap(ourContentTypeToEncoding)); + ourContentTypeToEncodingNonLegacy = Collections.unmodifiableMap(ourContentTypeToEncodingNonLegacy); /* * These are wrong, but we add them just to be tolerant of other @@ -65,36 +71,65 @@ public enum EncodingEnum { */ ourContentTypeToEncoding.put("application/json", JSON); ourContentTypeToEncoding.put("application/xml", XML); - ourContentTypeToEncoding.put("application/fhir+xml", XML); ourContentTypeToEncoding.put("text/json", JSON); ourContentTypeToEncoding.put("text/xml", XML); + /* + * Plain values, used for parameter values + */ + ourContentTypeToEncoding.put("json", JSON); + ourContentTypeToEncoding.put("xml", XML); + + /* + * See #346 + */ + for (EncodingEnum next : values()) { + ourContentTypeToEncoding.put(next.myResourceContentTypeNonLegacy.replace('+', ' '), next); + ourContentTypeToEncoding.put(next.myResourceContentTypeLegacy.replace('+', ' '), next); + } + } - private String myResourceContentType; private String myBundleContentType; private String myFormatContentType; + private String myResourceContentTypeNonLegacy; + private String myResourceContentTypeLegacy; - EncodingEnum(String theResourceContentType, String theBundleContentType, String theFormatContentType) { - myResourceContentType = theResourceContentType; + EncodingEnum(String theResourceContentTypeLegacy, String theResourceContentType, String theBundleContentType, String theFormatContentType) { + myResourceContentTypeLegacy = theResourceContentTypeLegacy; + myResourceContentTypeNonLegacy = theResourceContentType; myBundleContentType = theBundleContentType; myFormatContentType = theFormatContentType; } + public String getBundleContentType() { + return myBundleContentType; + } + + public String getFormatContentType() { + return myFormatContentType; + } + public String getRequestContentType() { return myFormatContentType; } - public abstract IParser newParser(FhirContext theContext); - - public String getBundleContentType() { - return myBundleContentType; - } - + /** + * Will return application/xml+fhir style + */ public String getResourceContentType() { - return myResourceContentType; + return myResourceContentTypeLegacy; } + /** + * Will return application/fhir+xml style + */ + public String getResourceContentTypeNonLegacy() { + return myResourceContentTypeNonLegacy; + } + + public abstract IParser newParser(FhirContext theContext); + /** * Returns the encoding for a given content type, or null if no encoding * is found. @@ -119,20 +154,9 @@ public enum EncodingEnum { return ourContentTypeToEncodingStrict.get(theContentType); } - /** - * Returns a map containing the encoding for a given content type, or null if no encoding - * is found. - *

- * This method is NOT lenient! Things like "application/xml" will return null - *

- * @see #forContentType(String) - */ - public static Map getContentTypeToEncodingStrict() { - return ourContentTypeToEncodingStrict; + public static boolean isNonLegacy(String theFormat) { + return ourContentTypeToEncodingNonLegacy.containsKey(theFormat); } - public String getFormatContentType() { - return myFormatContentType; - } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java index e598a7d00b8..94b3a448ac8 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java @@ -68,6 +68,7 @@ import ca.uhn.fhir.rest.method.BaseMethodBinding; import ca.uhn.fhir.rest.method.ConformanceMethodBinding; import ca.uhn.fhir.rest.method.ParseAction; import ca.uhn.fhir.rest.method.RequestDetails; +import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding; import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; @@ -1163,10 +1164,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer acceptValues = theReq.getHeaders(Constants.HEADER_CONTENT_TYPE).iterator(); if (acceptValues != null) { while (acceptValues.hasNext() && retVal == null) { @@ -193,8 +206,9 @@ public class RestfulServerUtils { nextPart = nextPart.substring(0, scIdx); } nextPart = nextPart.trim(); - retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextPart); - if (retVal != null) { + EncodingEnum encoding = EncodingEnum.forContentType(nextPart); + if (encoding != null) { + retVal = new ResponseEncoding(encoding, nextPart); break; } } @@ -208,13 +222,13 @@ public class RestfulServerUtils { * Returns null if the request doesn't express that it wants FHIR. If it expresses that it wants XML and JSON * equally, returns thePrefer. */ - public static EncodingEnum determineResponseEncodingNoDefault(RequestDetails theReq, EncodingEnum thePrefer) { + public static ResponseEncoding determineResponseEncodingNoDefault(RequestDetails theReq, EncodingEnum thePrefer) { String[] format = theReq.getParameters().get(Constants.PARAM_FORMAT); if (format != null) { for (String nextFormat : format) { - EncodingEnum retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextFormat); + EncodingEnum retVal = EncodingEnum.forContentType(nextFormat); if (retVal != null) { - return retVal; + return new ResponseEncoding(retVal, nextFormat); } } } @@ -228,9 +242,9 @@ public class RestfulServerUtils { * since Binary is supposed to use native content types unless the client has * explicitly requested FHIR. */ - Map contentTypeToEncoding = Constants.FORMAT_VAL_TO_ENCODING; + boolean strict = false; if ("Binary".equals(theReq.getResourceName())) { - contentTypeToEncoding = EncodingEnum.getContentTypeToEncodingStrict(); + strict = true; } /* @@ -240,7 +254,7 @@ public class RestfulServerUtils { List acceptValues = theReq.getHeaders(Constants.HEADER_ACCEPT); float bestQ = -1f; - EncodingEnum retVal = null; + ResponseEncoding retVal = null; if (acceptValues != null) { for (String nextAcceptHeaderValue : acceptValues) { StringTokenizer tok = new StringTokenizer(nextAcceptHeaderValue, ","); @@ -267,15 +281,15 @@ public class RestfulServerUtils { } float q = 1.0f; - EncodingEnum encoding; + ResponseEncoding encoding; if (endSpaceIndex == -1) { if (startSpaceIndex == 0) { - encoding = contentTypeToEncoding.get(nextToken); + encoding = getEncodingForContentType(strict, nextToken); } else { - encoding = contentTypeToEncoding.get(nextToken.substring(startSpaceIndex)); + encoding = getEncodingForContentType(strict, nextToken.substring(startSpaceIndex)); } } else { - encoding = contentTypeToEncoding.get(nextToken.substring(startSpaceIndex, endSpaceIndex)); + encoding = getEncodingForContentType(strict, nextToken.substring(startSpaceIndex, endSpaceIndex)); String remaining = nextToken.substring(endSpaceIndex + 1); StringTokenizer qualifierTok = new StringTokenizer(remaining, ";"); while (qualifierTok.hasMoreTokens()) { @@ -297,7 +311,7 @@ public class RestfulServerUtils { } if (encoding != null) { - if (q > bestQ || (q == bestQ && encoding == thePrefer)) { + if (q > bestQ || (q == bestQ && encoding.getEncoding() == thePrefer)) { retVal = encoding; bestQ = q; } @@ -305,58 +319,31 @@ public class RestfulServerUtils { } - // - // - // - // - // Matcher m = ACCEPT_HEADER_PATTERN.matcher(nextAcceptHeaderValue); - // float q = 1.0f; - // while (m.find()) { - // String contentTypeGroup = m.group(1); - // EncodingEnum encoding = Constants.FORMAT_VAL_TO_ENCODING.get(contentTypeGroup); - // if (encoding != null) { - // - // String name = m.group(3); - // String value = m.group(4); - // if (name != null && value != null) { - // if ("q".equals(name)) { - // try { - // q = Float.parseFloat(value); - // q = Math.max(q, 0.0f); - // } catch (NumberFormatException e) { - // ourLog.debug("Invalid Accept header q value: {}", value); - // } - // } - // } - // } - // - // if (encoding != null) { - // if (q > bestQ || (q == bestQ && encoding == thePrefer)) { - // retVal = encoding; - // bestQ = q; - // } - // } - // - // if (!",".equals(m.group(5))) { - // break; - // } - // } - // } - return retVal; } - return null; + + /* + * If the client hasn't given any indication about which response + * encoding they want, let's try the request encoding in case that + * is useful (basically this catches the case where the request + * has a Content-Type header but not an Accept header) + */ + if (retVal == null) { + retVal = determineRequestEncodingNoDefaultReturnRE(theReq); + } + + return retVal; } - + /** * Determine whether a response should be given in JSON or XML format based on the incoming HttpServletRequest's * "_format" parameter and "Accept:" HTTP header. */ - public static EncodingEnum determineResponseEncodingWithDefault(RequestDetails theReq) { - EncodingEnum retVal = determineResponseEncodingNoDefault(theReq, theReq.getServer().getDefaultResponseEncoding()); + public static ResponseEncoding determineResponseEncodingWithDefault(RequestDetails theReq) { + ResponseEncoding retVal = determineResponseEncodingNoDefault(theReq, theReq.getServer().getDefaultResponseEncoding()); if (retVal == null) { - retVal = theReq.getServer().getDefaultResponseEncoding(); + retVal = new ResponseEncoding(theReq.getServer().getDefaultResponseEncoding(), null); } return retVal; } @@ -402,10 +389,48 @@ public class RestfulServerUtils { return RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_COUNT); } + public static IPrimitiveType extractLastUpdatedFromResource(IBaseResource theResource) { + IPrimitiveType lastUpdated = null; + if (theResource instanceof IResource) { + lastUpdated = ResourceMetadataKeyEnum.UPDATED.get((IResource) theResource); + } else if (theResource instanceof IAnyResource) { + lastUpdated = new InstantDt(((IAnyResource) theResource).getMeta().getLastUpdated()); + } + return lastUpdated; + } + + public static IIdType fullyQualifyResourceIdOrReturnNull(IRestfulServerDefaults theServer, IBaseResource theResource, String theServerBase, IIdType theResourceId) { + IIdType retVal = null; + if (theResourceId.hasIdPart() && isNotBlank(theServerBase)) { + String resName = theResourceId.getResourceType(); + if (theResource != null && isBlank(resName)) { + resName = theServer.getFhirContext().getResourceDefinition(theResource).getName(); + } + if (isNotBlank(resName)) { + retVal = theResourceId.withServerBase(theServerBase, resName); + } + } + return retVal; + } + + private static ResponseEncoding getEncodingForContentType(boolean theStrict, String theContentType) { + EncodingEnum encoding; + if (theStrict) { + encoding = EncodingEnum.forContentTypeStrict(theContentType); + }else { + encoding = EncodingEnum.forContentType(theContentType); + } + if (encoding == null) { + return null; + } else { + return new ResponseEncoding(encoding, theContentType); + } + } + public static IParser getNewParser(FhirContext theContext, RequestDetails theRequestDetails) { // Determine response encoding - EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequestDetails); + EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequestDetails).getEncoding(); IParser parser; switch (responseEncoding) { case JSON: @@ -532,7 +557,7 @@ public class RestfulServerUtils { int status = 200; // Determine response encoding - EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequestDetails); + EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequestDetails).getEncoding(); String contentType = responseEncoding.getBundleContentType(); @@ -550,17 +575,17 @@ public class RestfulServerUtils { } return theRequestDetails.getResponse().sendWriterResponse(status, contentType, charset, writer); } - + + public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set theSummaryMode, int stausCode, boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails) throws IOException { return streamResponseAsResource(theServer, theResource, theSummaryMode, stausCode, null, theAddContentLocationHeader, respondGzip, theRequestDetails, null, null); } - - + public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set theSummaryMode, int theStausCode, String theStatusMessage, boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType theOperationResourceLastUpdated) throws IOException { IRestfulResponse restUtil = theRequestDetails.getResponse(); // Determine response encoding - EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequestDetails, theServer.getDefaultResponseEncoding()); + ResponseEncoding responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequestDetails, theServer.getDefaultResponseEncoding()); String serverBase = theRequestDetails.getFhirServerBase(); IIdType fullId = null; @@ -600,8 +625,10 @@ public class RestfulServerUtils { } // Ok, we're not serving a binary resource, so apply default encoding - responseEncoding = responseEncoding != null ? responseEncoding : theServer.getDefaultResponseEncoding(); - + if (responseEncoding == null) { + responseEncoding = new ResponseEncoding(theServer.getDefaultResponseEncoding(), null); + } + boolean encodingDomainResourceAsText = theSummaryMode.contains(SummaryEnum.TEXT); if (encodingDomainResourceAsText) { /* @@ -669,28 +696,17 @@ public class RestfulServerUtils { return restUtil.sendWriterResponse(theStausCode, contentType, charset, writer); } - public static IIdType fullyQualifyResourceIdOrReturnNull(IRestfulServerDefaults theServer, IBaseResource theResource, String theServerBase, IIdType theResourceId) { - IIdType retVal = null; - if (theResourceId.hasIdPart() && isNotBlank(theServerBase)) { - String resName = theResourceId.getResourceType(); - if (theResource != null && isBlank(resName)) { - resName = theServer.getFhirContext().getResourceDefinition(theResource).getName(); - } - if (isNotBlank(resName)) { - retVal = theResourceId.withServerBase(theServerBase, resName); - } + public static Integer tryToExtractNamedParameter(RequestDetails theRequest, String theParamName) { + String[] retVal = theRequest.getParameters().get(theParamName); + if (retVal == null) { + return null; } - return retVal; - } - - public static IPrimitiveType extractLastUpdatedFromResource(IBaseResource theResource) { - IPrimitiveType lastUpdated = null; - if (theResource instanceof IResource) { - lastUpdated = ResourceMetadataKeyEnum.UPDATED.get((IResource) theResource); - } else if (theResource instanceof IAnyResource) { - lastUpdated = new InstantDt(((IAnyResource) theResource).getMeta().getLastUpdated()); + try { + return Integer.parseInt(retVal[0]); + } catch (NumberFormatException e) { + ourLog.debug("Failed to parse {} value '{}': {}", new Object[] { theParamName, retVal[0], e }); + return null; } - return lastUpdated; } // static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) { @@ -706,19 +722,6 @@ public class RestfulServerUtils { // return count; // } - public static Integer tryToExtractNamedParameter(RequestDetails theRequest, String theParamName) { - String[] retVal = theRequest.getParameters().get(theParamName); - if (retVal == null) { - return null; - } - try { - return Integer.parseInt(retVal[0]); - } catch (NumberFormatException e) { - ourLog.debug("Failed to parse {} value '{}': {}", new Object[] { theParamName, retVal[0], e }); - return null; - } - } - public static void validateResourceListNotNull(List theResourceList) { if (theResourceList == null) { throw new InternalErrorException("IBundleProvider returned a null list of resources - This is not allowed"); @@ -733,4 +736,51 @@ public class RestfulServerUtils { } } + /** + * Return type for {@link RestfulServerUtils#determineRequestEncodingNoDefault(RequestDetails)} + */ + public static class ResponseEncoding + { + private final EncodingEnum myEncoding; + private final Boolean myNonLegacy; + public ResponseEncoding(EncodingEnum theEncoding, String theContentType) { + super(); + myEncoding = theEncoding; + if (theContentType != null) { + myNonLegacy = EncodingEnum.isNonLegacy(theContentType); + } else { + myNonLegacy = null; + } + } + public EncodingEnum getEncoding() { + return myEncoding; + } + public String getResourceContentType() { + if (Boolean.TRUE.equals(isNonLegacy())) { + return getEncoding().getResourceContentTypeNonLegacy(); + } else { + return getEncoding().getResourceContentType(); + } + } + + public Boolean isNonLegacy() { + return myNonLegacy; + } + } + + public static void addAcceptHeaderToRequest(EncodingEnum theEncoding, IHttpRequest theHttpRequest, FhirContext theContext) { + if (theEncoding == null) { + if (!theContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2)) { + theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY); + } else { + theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_NON_LEGACY); + } + } else if (theEncoding == EncodingEnum.JSON) { + theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON); + } else if (theEncoding == EncodingEnum.XML) { + theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML); + } + + } + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptor.java index 436fd42eb6e..01c75e4935b 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptor.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptor.java @@ -43,6 +43,7 @@ import org.slf4j.LoggerFactory; import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.RestfulServerUtils; +import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding; import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; @@ -283,9 +284,9 @@ public class LoggingInterceptor extends InterceptorAdapter { } else if (theKey.startsWith("remoteAddr")) { return StringUtils.defaultString(myRequest.getRemoteAddr()); } else if (theKey.equals("responseEncodingNoDefault")) { - EncodingEnum encoding = RestfulServerUtils.determineResponseEncodingNoDefault(myRequestDetails, myRequestDetails.getServer().getDefaultResponseEncoding()); + ResponseEncoding encoding = RestfulServerUtils.determineResponseEncodingNoDefault(myRequestDetails, myRequestDetails.getServer().getDefaultResponseEncoding()); if (encoding != null) { - return encoding.name(); + return encoding.getEncoding().name(); } else { return ""; } diff --git a/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/client/JaxRsHttpClient.java b/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/client/JaxRsHttpClient.java index df91ab53116..09a3e5a2c12 100644 --- a/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/client/JaxRsHttpClient.java +++ b/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/client/JaxRsHttpClient.java @@ -41,6 +41,7 @@ import ca.uhn.fhir.rest.client.api.IHttpClient; import ca.uhn.fhir.rest.client.api.IHttpRequest; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.EncodingEnum; +import ca.uhn.fhir.rest.server.RestfulServerUtils; /** * A Http Request based on JaxRs. This is an adapter around the class @@ -119,13 +120,7 @@ public class JaxRsHttpClient implements IHttpClient { Builder request = theHttpRequest.getRequest(); request.acceptEncoding("gzip"); - if (theEncoding == null) { - request.accept(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON); - } else if (theEncoding == EncodingEnum.JSON) { - request.accept(Constants.CT_FHIR_JSON); - } else if (theEncoding == EncodingEnum.XML) { - request.accept(Constants.CT_FHIR_XML); - } + RestfulServerUtils.addAcceptHeaderToRequest(theEncoding, theHttpRequest, theContext); } private JaxRsHttpRequest createHttpRequest(Entity entity) { diff --git a/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/util/JaxRsResponse.java b/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/util/JaxRsResponse.java index 5b1c0c32471..0d1d0edd7d4 100644 --- a/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/util/JaxRsResponse.java +++ b/hapi-fhir-jaxrsserver-base/src/main/java/ca/uhn/fhir/jaxrs/server/util/JaxRsResponse.java @@ -104,7 +104,7 @@ public class JaxRsResponse extends RestfulResponse { } protected String getParserType() { - EncodingEnum encodingEnum = RestfulServerUtils.determineResponseEncodingWithDefault(getRequestDetails()); + EncodingEnum encodingEnum = RestfulServerUtils.determineResponseEncodingWithDefault(getRequestDetails()).getEncoding(); return encodingEnum == EncodingEnum.JSON ? MediaType.APPLICATION_JSON : MediaType.APPLICATION_XML; } diff --git a/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu2Test.java b/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu2Test.java index 2442999b7e8..75aadbb0269 100644 --- a/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu2Test.java +++ b/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu2Test.java @@ -133,7 +133,7 @@ public class GenericJaxRsClientDstu2Test { client.fetchConformance().ofType(Conformance.class).execute(); assertEquals("http://localhost:" + ourPort + "/fhir/metadata", ourRequestUri); assertEquals(1, ourRequestHeaders.get("Accept").size()); - assertThat(ourRequestHeaders.get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON)); + assertThat(ourRequestHeaders.get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY)); client.fetchConformance().ofType(Conformance.class).encodedJson().execute(); @@ -169,12 +169,12 @@ public class GenericJaxRsClientDstu2Test { assertEquals("FAMILY", resp.getName().get(0).getFamily().get(0).getValue()); assertEquals("http://localhost:" + ourPort + "/fhir/metadata", ourRequestUriAll.get(0)); assertEquals(1, ourRequestHeadersAll.get(0).get("Accept").size()); - assertThat(ourRequestHeadersAll.get(0).get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON)); + assertThat(ourRequestHeadersAll.get(0).get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY)); assertThat(ourRequestHeadersAll.get(0).get("Accept").get(0).getValue(), containsString(Constants.CT_FHIR_XML)); assertThat(ourRequestHeadersAll.get(0).get("Accept").get(0).getValue(), containsString(Constants.CT_FHIR_JSON)); assertEquals("http://localhost:" + ourPort + "/fhir/Patient/123", ourRequestUriAll.get(1)); assertEquals(1, ourRequestHeadersAll.get(1).get("Accept").size()); - assertThat(ourRequestHeadersAll.get(1).get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON)); + assertThat(ourRequestHeadersAll.get(1).get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY)); assertThat(ourRequestHeadersAll.get(1).get("Accept").get(0).getValue(), containsString(Constants.CT_FHIR_XML)); assertThat(ourRequestHeadersAll.get(1).get("Accept").get(0).getValue(), containsString(Constants.CT_FHIR_JSON)); } @@ -1600,7 +1600,7 @@ public class GenericJaxRsClientDstu2Test { assertEquals("name=james", ourRequestBodyString); assertEquals("application/x-www-form-urlencoded", ourRequestContentType.replace(";char", "; char").toLowerCase()); - assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, ourRequestFirstHeaders.get("Accept").getValue()); + assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY, ourRequestFirstHeaders.get("Accept").getValue()); assertThat(ourRequestFirstHeaders.get("User-Agent").getValue(), not(emptyString())); } diff --git a/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu3Test.java b/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu3Test.java index 42e032949d8..a122cac3bec 100644 --- a/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu3Test.java +++ b/hapi-fhir-jaxrsserver-base/src/test/java/ca/uhn/fhir/jaxrs/client/GenericJaxRsClientDstu3Test.java @@ -137,7 +137,7 @@ public class GenericJaxRsClientDstu3Test { client.fetchConformance().ofType(Conformance.class).execute(); assertEquals("http://localhost:" + ourPort + "/fhir/metadata", ourRequestUri); assertEquals(1, ourRequestHeaders.get("Accept").size()); - assertThat(ourRequestHeaders.get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON)); + assertThat(ourRequestHeaders.get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY)); client.fetchConformance().ofType(Conformance.class).encodedJson().execute(); @@ -173,12 +173,12 @@ public class GenericJaxRsClientDstu3Test { assertEquals("FAMILY", resp.getName().get(0).getFamily().get(0).getValue()); assertEquals("http://localhost:" + ourPort + "/fhir/metadata", ourRequestUriAll.get(0)); assertEquals(1, ourRequestHeadersAll.get(0).get("Accept").size()); - assertThat(ourRequestHeadersAll.get(0).get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON)); + assertThat(ourRequestHeadersAll.get(0).get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY)); assertThat(ourRequestHeadersAll.get(0).get("Accept").get(0).getValue(), containsString(Constants.CT_FHIR_XML)); assertThat(ourRequestHeadersAll.get(0).get("Accept").get(0).getValue(), containsString(Constants.CT_FHIR_JSON)); assertEquals("http://localhost:" + ourPort + "/fhir/Patient/123", ourRequestUriAll.get(1)); assertEquals(1, ourRequestHeadersAll.get(1).get("Accept").size()); - assertThat(ourRequestHeadersAll.get(1).get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON)); + assertThat(ourRequestHeadersAll.get(1).get("Accept").get(0).getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY)); assertThat(ourRequestHeadersAll.get(1).get("Accept").get(0).getValue(), containsString(Constants.CT_FHIR_XML)); assertThat(ourRequestHeadersAll.get(1).get("Accept").get(0).getValue(), containsString(Constants.CT_FHIR_JSON)); } @@ -1605,7 +1605,7 @@ public class GenericJaxRsClientDstu3Test { assertEquals("name=james", ourRequestBodyString); assertEquals("application/x-www-form-urlencoded", ourRequestContentType.replace(";char", "; char").toLowerCase()); - assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, ourRequestFirstHeaders.get("Accept").getValue()); + assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY, ourRequestFirstHeaders.get("Accept").getValue()); assertThat(ourRequestFirstHeaders.get("User-Agent").getValue(), not(emptyString())); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java index 54b32de78b2..f48bd6545a5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java @@ -49,7 +49,6 @@ import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; -import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler implements ISubscriptionWebsocketHandler, Runnable { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SubscriptionWebsocketHandlerDstu2.class); @@ -263,7 +262,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl EncodingEnum encoding = EncodingEnum.JSON; for (NameValuePair nameValuePair : paramValues) { if (Constants.PARAM_FORMAT.equals(nameValuePair.getName())) { - EncodingEnum nextEncoding = Constants.FORMAT_VAL_TO_ENCODING.get(nameValuePair.getValue()); + EncodingEnum nextEncoding = EncodingEnum.forContentType(nameValuePair.getValue()); if (nextEncoding != null) { encoding = nextEncoding; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java index bddb1af9cfc..2c67e79f3a4 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java @@ -49,7 +49,6 @@ import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; -import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler implements ISubscriptionWebsocketHandler, Runnable { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SubscriptionWebsocketHandlerDstu3.class); @@ -263,7 +262,7 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl EncodingEnum encoding = EncodingEnum.JSON; for (NameValuePair nameValuePair : paramValues) { if (Constants.PARAM_FORMAT.equals(nameValuePair.getName())) { - EncodingEnum nextEncoding = Constants.FORMAT_VAL_TO_ENCODING.get(nameValuePair.getValue()); + EncodingEnum nextEncoding = EncodingEnum.forContentType(nameValuePair.getValue()); if (nextEncoding != null) { encoding = nextEncoding; } diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java index 966a608a569..29c4bccc48d 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/GenericClientTest.java @@ -370,7 +370,7 @@ public class GenericClientTest { when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("LKJHLKJGLKJKLL"), Charset.forName("UTF-8"))); outcome = (OperationOutcome) client.delete().resourceById(new IdDt("Location", "123", "456")).prettyPrint().encodedJson().execute(); - assertEquals("http://example.com/fhir/Location/123?_format=json&_pretty=true", capt.getAllValues().get(1).getURI().toString()); + assertEquals("http://example.com/fhir/Location/123?_pretty=true", capt.getAllValues().get(1).getURI().toString()); assertEquals("DELETE", capt.getValue().getMethod()); assertEquals(null, outcome); @@ -1542,7 +1542,7 @@ public class GenericClientTest { assertNotNull(ct); assertEquals(Constants.CT_FHIR_JSON + "; charset=UTF-8", ct.getValue()); - assertEquals("http://example.com/fhir?_format=json", value.getURI().toString()); + assertEquals("http://example.com/fhir", value.getURI().toString()); assertThat(IOUtils.toString(value.getEntity().getContent()), StringContains.containsString("\"resourceType\"")); assertEquals(bundle.getEntries().get(0).getResource().getId(), response.getEntries().get(0).getResource().getId()); } diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/CreateTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/CreateTest.java index cc9080ac5ac..3545114dcf0 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/CreateTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/CreateTest.java @@ -222,7 +222,7 @@ public class CreateTest { ourLog.info("Response was:\n{}", responseContent); assertEquals(400, status.getStatusLine().getStatusCode()); - assertThat(responseContent, containsString("Content does not appear to be FHIR JSON, first non-whitespace character was: '<' (must be '{')")); + assertThat(responseContent, containsString("Content does not appear to be FHIR JSON, first non-whitespace character was: '<' (must be '{')")); } @Test diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java index 7dae4b622a1..9c9c18bd926 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java @@ -168,7 +168,7 @@ public class GenericClientDstu2Test { client.fetchConformance().ofType(Conformance.class).execute(); assertEquals("http://example.com/fhir/metadata", capt.getAllValues().get(idx).getURI().toASCIIString()); assertEquals(1, capt.getAllValues().get(idx).getHeaders("Accept").length); - assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON)); + assertThat(capt.getAllValues().get(idx).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY)); idx++; client.fetchConformance().ofType(Conformance.class).encodedJson().execute(); @@ -217,12 +217,12 @@ public class GenericClientDstu2Test { assertEquals("FAMILY", resp.getName().get(0).getFamily().get(0).getValue()); assertEquals("http://" + methodName + ".example.com/fhir/metadata", capt.getAllValues().get(0).getURI().toASCIIString()); assertEquals(1, capt.getAllValues().get(0).getHeaders("Accept").length); - assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON)); + assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY)); assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML)); assertThat(capt.getAllValues().get(0).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON)); assertEquals("http://" + methodName + ".example.com/fhir/Patient/123", capt.getAllValues().get(1).getURI().toASCIIString()); assertEquals(1, capt.getAllValues().get(1).getHeaders("Accept").length); - assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON)); + assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY)); assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_XML)); assertThat(capt.getAllValues().get(1).getHeaders("Accept")[0].getValue(), containsString(Constants.CT_FHIR_JSON)); } @@ -1905,7 +1905,7 @@ public class GenericClientDstu2Test { assertEquals("name=james", req); assertEquals("application/x-www-form-urlencoded;charset=utf-8", v.getEntity().getContentType().getValue().replace(" ", "").toLowerCase()); - assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, capt.getValue().getFirstHeader("accept").getValue()); + assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY, capt.getValue().getFirstHeader("accept").getValue()); assertThat(capt.getValue().getFirstHeader("user-agent").getValue(), not(emptyString())); } @@ -1933,7 +1933,7 @@ public class GenericClientDstu2Test { assertThat(capt.getValue().getURI().toString(), containsString("http://example.com/fhir/Patient/_search?")); assertThat(capt.getValue().getURI().toString(), containsString("_elements=identifier%2Cname")); - assertThat(capt.getValue().getURI().toString(), containsString("_format=json")); + assertThat(capt.getValue().getURI().toString(), not(containsString("_format=json"))); // assertThat(capt.getValue().getURI().toString(), // either(equalTo("http://example.com/fhir/Patient?name=james&_elements=name%2Cidentifier")).or(equalTo("http://example.com/fhir/Patient?name=james&_elements=identifier%2Cname"))); @@ -2269,7 +2269,7 @@ public class GenericClientDstu2Test { .execute(); //@formatter:on - assertEquals("http://example.com/fhir?_format=json", capt.getValue().getURI().toString()); + assertEquals("http://example.com/fhir", capt.getValue().getURI().toString()); assertEquals(2, response.size()); String requestString = IOUtils.toString(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent()); @@ -2278,6 +2278,7 @@ public class GenericClientDstu2Test { assertEquals("POST", requestBundle.getEntry().get(0).getRequest().getMethod()); assertEquals("PUT", requestBundle.getEntry().get(1).getRequest().getMethod()); assertEquals("Patient/2", requestBundle.getEntry().get(1).getRequest().getUrl()); + assertEquals("application/json+fhir", capt.getAllValues().get(0).getFirstHeader("content-type").getValue().replaceAll(";.*", "")); p1 = (Patient) response.get(0); assertEquals(new IdDt("Patient/1/_history/1"), p1.getId().toUnqualified()); @@ -2335,7 +2336,7 @@ public class GenericClientDstu2Test { .execute(); //@formatter:on - assertEquals("http://example.com/fhir/?_format=xml", capt.getValue().getURI().toString()); + assertEquals("http://example.com/fhir/", capt.getValue().getURI().toString()); assertEquals(respStringJson, response); requestString = IOUtils.toString(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent()); IOUtils.closeQuietly(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent()); @@ -2378,7 +2379,7 @@ public class GenericClientDstu2Test { .execute(); //@formatter:on - assertEquals("http://example.com/fhir?_format=json", capt.getValue().getURI().toString()); + assertEquals("http://example.com/fhir", capt.getValue().getURI().toString()); assertEquals(2, response.getEntry().size()); assertEquals("Patient/1/_history/1", response.getEntry().get(0).getResponse().getLocation()); @@ -2571,30 +2572,34 @@ public class GenericClientDstu2Test { response = client.validate().resource(p).execute(); assertEquals("http://example.com/fhir/Patient/$validate", capt.getAllValues().get(idx).getURI().toASCIIString()); assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); + assertEquals("application/xml+fhir", capt.getAllValues().get(idx).getFirstHeader("content-type").getValue().replaceAll(";.*", "")); assertEquals("", extractBody(capt, idx)); assertNotNull(response.getOperationOutcome()); assertEquals("FOOBAR", toOo(response.getOperationOutcome()).getIssueFirstRep().getDiagnosticsElement().getValue()); idx++; response = client.validate().resource(ourCtx.newXmlParser().encodeResourceToString(p)).execute(); - assertEquals("http://example.com/fhir/Patient/$validate?_format=xml", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals("http://example.com/fhir/Patient/$validate", capt.getAllValues().get(idx).getURI().toASCIIString()); assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); + assertEquals("application/xml+fhir", capt.getAllValues().get(idx).getFirstHeader("content-type").getValue().replaceAll(";.*", "")); assertEquals("", extractBody(capt, idx)); assertNotNull(response.getOperationOutcome()); assertEquals("FOOBAR", toOo(response.getOperationOutcome()).getIssueFirstRep().getDiagnosticsElement().getValue()); idx++; response = client.validate().resource(ourCtx.newJsonParser().encodeResourceToString(p)).execute(); - assertEquals("http://example.com/fhir/Patient/$validate?_format=json", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals("http://example.com/fhir/Patient/$validate", capt.getAllValues().get(idx).getURI().toASCIIString()); assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); + assertEquals("application/json+fhir", capt.getAllValues().get(idx).getFirstHeader("content-type").getValue().replaceAll(";.*", "")); assertEquals("{\"resourceType\":\"Parameters\",\"parameter\":[{\"name\":\"resource\",\"resource\":{\"resourceType\":\"Patient\",\"name\":[{\"given\":[\"GIVEN\"]}]}}]}", extractBody(capt, idx)); assertNotNull(response.getOperationOutcome()); assertEquals("FOOBAR", toOo(response.getOperationOutcome()).getIssueFirstRep().getDiagnosticsElement().getValue()); idx++; response = client.validate().resource(ourCtx.newJsonParser().encodeResourceToString(p)).prettyPrint().execute(); - assertEquals("http://example.com/fhir/Patient/$validate?_format=json&_pretty=true", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals("http://example.com/fhir/Patient/$validate?_pretty=true", capt.getAllValues().get(idx).getURI().toASCIIString()); assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); + assertEquals("application/json+fhir", capt.getAllValues().get(idx).getFirstHeader("content-type").getValue().replaceAll(";.*", "")); assertThat(extractBody(capt, idx), containsString("\"resourceType\": \"Parameters\",\n")); assertNotNull(response.getOperationOutcome()); assertEquals("FOOBAR", toOo(response.getOperationOutcome()).getIssueFirstRep().getDiagnosticsElement().getValue()); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/TransactionWithBundleResourceParamTest.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/TransactionWithBundleResourceParamTest.java index da90f8fb92a..0132434cc78 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/TransactionWithBundleResourceParamTest.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/TransactionWithBundleResourceParamTest.java @@ -38,9 +38,6 @@ import ca.uhn.fhir.rest.client.api.IRestfulClient; import ca.uhn.fhir.util.PortUtil; import ca.uhn.fhir.util.TestUtil; -/** - * Created by dsotnikov on 2/25/2014. - */ public class TransactionWithBundleResourceParamTest { @@ -108,7 +105,7 @@ public class TransactionWithBundleResourceParamTest { ourLog.info(responseContent); - Bundle bundle = ourCtx.newXmlParser().parseResource(Bundle.class, responseContent); + Bundle bundle = ourCtx.newJsonParser().parseResource(Bundle.class, responseContent); assertEquals(3, bundle.getEntry().size()); Entry entry0 = bundle.getEntry().get(0); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java index bb113db9453..36534b0623f 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java @@ -75,7 +75,7 @@ import ca.uhn.fhir.util.TestUtil; public class AuthorizationInterceptorDstu2Test { - private static final String ERR403 = ""; + private static final String ERR403 = "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"error\",\"code\":\"processing\",\"diagnostics\":\"Access denied by default policy (no applicable rules)\"}]}"; private static CloseableHttpClient ourClient; private static FhirContext ourCtx = FhirContext.forDstu2(); private static boolean ourHitMethod; diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/ClientMimetypeDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/ClientMimetypeDstu3Test.java new file mode 100644 index 00000000000..782b0979478 --- /dev/null +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/ClientMimetypeDstu3Test.java @@ -0,0 +1,174 @@ +package ca.uhn.fhir.rest.client; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.Charset; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.input.ReaderInputStream; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.ProtocolVersion; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicStatusLine; +import org.hl7.fhir.dstu3.model.Patient; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.server.Constants; +import ca.uhn.fhir.util.TestUtil; + +/** + * http://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_id=677&tracker_item_id=10199 + */ +public class ClientMimetypeDstu3Test { + private static FhirContext ourCtx; + private HttpClient myHttpClient; + private HttpResponse myHttpResponse; + + @Before + public void before() { + myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs()); + ourCtx.getRestfulClientFactory().setHttpClient(myHttpClient); + ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs()); + } + + @Test + public void testMimetypeXmlNew() throws Exception { + String requestCt = Constants.CT_FHIR_XML_NEW; + + ArgumentCaptor capt = prepareMimetypePostTest(requestCt, true); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + Patient pt = new Patient(); + pt.getText().setDivAsString("A PATIENT"); + + MethodOutcome outcome = client.create().resource(pt).execute(); + + assertEquals("
FINAL VALUE
", ((Patient) outcome.getResource()).getText().getDivAsString()); + assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(0).getURI().toASCIIString()); + assertEquals(Constants.CT_FHIR_XML, capt.getAllValues().get(0).getFirstHeader("content-type").getValue().replaceAll(";.*", "")); + assertEquals("application/xml+fhir", capt.getAllValues().get(0).getFirstHeader("accept").getValue()); + assertEquals("
A PATIENT
", extractBodyAsString(capt)); + } + + @Test + public void testMimetypeXmlLegacy() throws Exception { + String requestCt = Constants.CT_FHIR_XML; + + ArgumentCaptor capt = prepareMimetypePostTest(requestCt, true); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + Patient pt = new Patient(); + pt.getText().setDivAsString("A PATIENT"); + + MethodOutcome outcome = client.create().resource(pt).execute(); + + assertEquals("
FINAL VALUE
", ((Patient) outcome.getResource()).getText().getDivAsString()); + assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(0).getURI().toASCIIString()); + assertEquals(Constants.CT_FHIR_XML, capt.getAllValues().get(0).getFirstHeader("content-type").getValue().replaceAll(";.*", "")); + assertEquals("application/xml+fhir", capt.getAllValues().get(0).getFirstHeader("accept").getValue()); + assertEquals("
A PATIENT
", extractBodyAsString(capt)); + } + + @Test + public void testMimetypeJsonNew() throws Exception { + String requestCt = Constants.CT_FHIR_JSON_NEW; + + ArgumentCaptor capt = prepareMimetypePostTest(requestCt, false); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + Patient pt = new Patient(); + pt.getText().setDivAsString("A PATIENT"); + + MethodOutcome outcome = client.create().resource(pt).encodedJson().execute(); + + assertEquals("
FINAL VALUE
", ((Patient) outcome.getResource()).getText().getDivAsString()); + assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(0).getURI().toASCIIString()); + assertEquals(Constants.CT_FHIR_JSON, capt.getAllValues().get(0).getFirstHeader("content-type").getValue().replaceAll(";.*", "")); + assertEquals("application/json+fhir", capt.getAllValues().get(0).getFirstHeader("accept").getValue()); + assertEquals("{\"resourceType\":\"Patient\",\"text\":{\"div\":\"
A PATIENT
\"}}", extractBodyAsString(capt)); + } + + @Test + public void testMimetypeJsonLegacy() throws Exception { + String requestCt = Constants.CT_FHIR_JSON; + + ArgumentCaptor capt = prepareMimetypePostTest(requestCt, false); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + Patient pt = new Patient(); + pt.getText().setDivAsString("A PATIENT"); + + MethodOutcome outcome = client.create().resource(pt).encodedJson().execute(); + + assertEquals("
FINAL VALUE
", ((Patient) outcome.getResource()).getText().getDivAsString()); + assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(0).getURI().toASCIIString()); + assertEquals(Constants.CT_FHIR_JSON, capt.getAllValues().get(0).getFirstHeader("content-type").getValue().replaceAll(";.*", "")); + assertEquals("application/json+fhir", capt.getAllValues().get(0).getFirstHeader("accept").getValue()); + assertEquals("{\"resourceType\":\"Patient\",\"text\":{\"div\":\"
A PATIENT
\"}}", extractBodyAsString(capt)); + } + + private String extractBodyAsString(ArgumentCaptor capt) throws IOException { + String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent(), "UTF-8"); + return body; + } + + private ArgumentCaptor prepareMimetypePostTest(String requestCt, boolean theXml) throws IOException, ClientProtocolException { + final IParser p = theXml ? ourCtx.newXmlParser() : ourCtx.newJsonParser(); + + final Patient resp1 = new Patient(); + resp1.getText().setDivAsString("FINAL VALUE"); + + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); + when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer() { + @Override + public Header[] answer(InvocationOnMock theInvocation) throws Throwable { + return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") }; + } + }); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", requestCt + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp1)), Charset.forName("UTF-8")); + } + }); + return capt; + } + + @AfterClass + public static void afterClassClearContext() { + TestUtil.clearAllStaticFieldsForUnitTest(); + } + + @BeforeClass + public static void beforeClass() { + ourCtx = FhirContext.forDstu3(); + } + +} diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java index 43e04dcdfb3..7a600e2ce34 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu3Test.java @@ -20,8 +20,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; -import java.util.Locale; -import java.util.TimeZone; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.ReaderInputStream; @@ -1445,7 +1443,7 @@ public class GenericClientDstu3Test { validateUserAgent(capt); assertEquals("application/foo", capt.getAllValues().get(0).getHeaders("Content-Type")[0].getValue()); - assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue()); + assertEquals(Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON_NON_LEGACY, capt.getAllValues().get(0).getHeaders("Accept")[0].getValue()); assertArrayEquals(new byte[] { 0, 1, 2, 3, 4 }, extractBodyAsByteArray(capt)); } diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/RequestValidatingInterceptorDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/RequestValidatingInterceptorDstu3Test.java index e38a7cac1ca..b1b6c4c7695 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/RequestValidatingInterceptorDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/RequestValidatingInterceptorDstu3Test.java @@ -136,7 +136,7 @@ public class RequestValidatingInterceptorDstu3Test { assertEquals(422, status.getStatusLine().getStatusCode()); assertThat(status.toString(), containsString("X-FHIR-Request-Validation")); - assertThat(responseContent, containsString("")); + assertThat(responseContent, containsString("\"severity\":\"error\"")); } @Test diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeDstu3Test.java new file mode 100644 index 00000000000..899b178109a --- /dev/null +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerMimetypeDstu3Test.java @@ -0,0 +1,345 @@ +package ca.uhn.fhir.rest.server; + +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.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.hl7.fhir.dstu3.model.DateType; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.OperationOutcome; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.annotation.Create; +import ca.uhn.fhir.rest.annotation.IdParam; +import ca.uhn.fhir.rest.annotation.Read; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Search; +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; + +public class ServerMimetypeDstu3Test { + private static CloseableHttpClient ourClient; + + private static FhirContext ourCtx = FhirContext.forDstu3(); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerMimetypeDstu3Test.class); + private static int ourPort; + private static Server ourServer; + + @Test + public void testCreateWithXmlLegacyNoAcceptHeader() throws Exception { + Patient p = new Patient(); + p.addName().addFamily("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); + + String responseContent = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + + ourLog.info("Response was:\n{}", responseContent); + + assertEquals(201, status.getStatusLine().getStatusCode()); + assertEquals(Constants.CT_FHIR_XML, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); + assertEquals("", responseContent); + } + + @Test + public void testCreateWithXmlNewNoAcceptHeader() throws Exception { + Patient p = new Patient(); + p.addName().addFamily("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()); + 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("", responseContent); + } + + @Test + public void testCreateWithXmlNewWithAcceptHeader() throws Exception { + Patient p = new Patient(); + p.addName().addFamily("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()); + 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("", responseContent); + } + + @Test + public void testCreateWithJsonLegacyNoAcceptHeader() throws Exception { + Patient p = new Patient(); + p.addName().addFamily("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()); + 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().addFamily("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()); + 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().addFamily("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()); + 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"); + HttpResponse status = ourClient.execute(httpGet); + + String responseContent = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + + ourLog.info("Response was:\n{}", responseContent); + + assertEquals(200, status.getStatusLine().getStatusCode()); + assertThat(responseContent, containsString("")); + assertThat(responseContent, not(containsString("http://hl7.org/fhir/"))); + assertEquals(Constants.CT_FHIR_XML, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); + } + + @Test + public void testSearchWithFormatXmlLegacy() throws Exception { + + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=" + Constants.CT_FHIR_XML); + HttpResponse status = ourClient.execute(httpGet); + + String responseContent = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + + ourLog.info("Response was:\n{}", responseContent); + + assertEquals(200, status.getStatusLine().getStatusCode()); + assertThat(responseContent, containsString("")); + assertThat(responseContent, not(containsString("http://hl7.org/fhir/"))); + assertEquals(Constants.CT_FHIR_XML, status.getFirstHeader("content-type").getValue().replaceAll(";.*", "")); + } + + @Test + public void testSearchWithFormatXmlNew() throws Exception { + + HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=" + Constants.CT_FHIR_XML_NEW); + HttpResponse status = ourClient.execute(httpGet); + + String responseContent = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + + ourLog.info("Response was:\n{}", responseContent); + + assertEquals(200, status.getStatusLine().getStatusCode()); + assertThat(responseContent, containsString("")); + assertThat(responseContent, not(containsString("http://hl7.org/fhir/"))); + assertEquals(Constants.CT_FHIR_XML, 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()); + 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 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()); + 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()); + 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(";.*", "")); + } + + @AfterClass + public static void afterClassClearContext() throws Exception { + ourServer.stop(); + TestUtil.clearAllStaticFieldsForUnitTest(); + } + + @BeforeClass + public static void beforeClass() throws Exception { + ourPort = PortUtil.findFreePort(); + ourServer = new Server(ourPort); + + PatientProvider patientProvider = new PatientProvider(); + + ServletHandler proxyHandler = new ServletHandler(); + RestfulServer servlet = new RestfulServer(ourCtx); + + servlet.setResourceProviders(patientProvider); + ServletHolder servletHolder = new ServletHolder(servlet); + proxyHandler.addServletWithMapping(servletHolder, "/*"); + ourServer.setHandler(proxyHandler); + ourServer.start(); + + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS); + HttpClientBuilder builder = HttpClientBuilder.create(); + builder.setConnectionManager(connectionManager); + ourClient = builder.build(); + + } + + public static class PatientProvider implements IResourceProvider { + + @Create() + public MethodOutcome create(@ResourceParam Patient theIdParam) { + OperationOutcome oo = new OperationOutcome(); + oo.addIssue().setDiagnostics(theIdParam.getNameFirstRep().getFamilyAsSingleString()); + return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(oo); + } + + @Override + public Class getResourceType() { + return Patient.class; + } + + @Read() + public MyPatientWithExtensions read(@IdParam IdType theIdParam) { + MyPatientWithExtensions p0 = new MyPatientWithExtensions(); + p0.setId(theIdParam); + p0.setDateExt(new DateType("2011-01-01")); + return p0; + } + + @Search + public List search() { + ArrayList retVal = new ArrayList(); + + MyPatientWithExtensions p0 = new MyPatientWithExtensions(); + p0.setId(new IdType("Patient/0")); + p0.setDateExt(new DateType("2011-01-01")); + retVal.add(p0); + + Patient p1 = new Patient(); + p1.setId(new IdType("Patient/1")); + p1.addName().addFamily("The Family"); + retVal.add(p1); + + return retVal; + } + + } + +} diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Hl7OrgTest.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Hl7OrgTest.java index 75330edc1f0..2337e815bac 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Hl7OrgTest.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Hl7OrgTest.java @@ -670,7 +670,7 @@ public class GenericClientDstu2Hl7OrgTest { .execute(); //@formatter:on - assertEquals("http://example.com/fhir?_format=json", capt.getValue().getURI().toString()); + assertEquals("http://example.com/fhir", capt.getValue().getURI().toString()); assertEquals(2, response.size()); String requestString = IOUtils.toString(((HttpEntityEnclosingRequest) capt.getValue()).getEntity().getContent()); @@ -723,7 +723,7 @@ public class GenericClientDstu2Hl7OrgTest { .execute(); //@formatter:on - assertEquals("http://example.com/fhir?_format=json", capt.getValue().getURI().toString()); + assertEquals("http://example.com/fhir", capt.getValue().getURI().toString()); assertEquals(2, response.getEntry().size()); assertEquals("Patient/1/_history/1", response.getEntry().get(0).getResponse().getLocation()); diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/server/TransactionWithBundleResourceParamHl7OrgDstu2Test.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/server/TransactionWithBundleResourceParamHl7OrgDstu2Test.java index 7d87fa2c977..232e130b76d 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/server/TransactionWithBundleResourceParamHl7OrgDstu2Test.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/server/TransactionWithBundleResourceParamHl7OrgDstu2Test.java @@ -37,9 +37,6 @@ import ca.uhn.fhir.rest.client.IGenericClient; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.util.PortUtil; -/** - * Created by dsotnikov on 2/25/2014. - */ public class TransactionWithBundleResourceParamHl7OrgDstu2Test { @Test @@ -157,7 +154,7 @@ public class TransactionWithBundleResourceParamHl7OrgDstu2Test { ourLog.info(responseContent); - Bundle bundle = ourCtx.newXmlParser().parseResource(Bundle.class, responseContent); + Bundle bundle = ourCtx.newJsonParser().parseResource(Bundle.class, responseContent); assertEquals(3, bundle.getEntry().size()); BundleEntryComponent entry0 = bundle.getEntry().get(0); diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 51f2cbd36f2..521d64f5064 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -26,10 +26,26 @@ Gson (it was ignored by the Glassfish parser we were previously using even though it was invalid) - ]]> + + Both client and server now support the new Content Types decided in + FHIR #10199
]]>. +
]]> + This means that the server now supports + application/fhir+xml
and application/fhir+json]]> + in addition to the older style + application/xml+fhir and application/json+fhir]]>. + In order to facilitate migration by implementors, the old style remains the default + for now, but the server will respond using the new style if the request contains it. The + client now uses an Accept]]> header value which requests both + styles with a preference given to the new style when running in DSTU3 mode. +
]]> + As a part of this change, the server has also been enhanced so that if a request + contains a Content-Type header but no Accept header, the response will prefer the + encoding specified by the Content-Type header. + Fix issue in DSTU1 Bundle parsing where unexpected elements in the bundle resulted in a failure to parse.