Use new style mimetypes but keep supportuing the old ones as well

This commit is contained in:
jamesagnew 2016-07-17 18:35:06 -04:00
parent ee0e3bda82
commit 196c11bfa2
31 changed files with 829 additions and 240 deletions

View File

@ -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 <code>this</code> 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 <code>this</code> 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 <code>null</code> (which is the default) if none.
* @return Returns a reference to <code>this</code> 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.
* </p>
* @return Returns a reference to <code>this</code> for easy method chaining
*/
public void setResource(IBaseResource theResource) {
public MethodOutcome setResource(IBaseResource theResource) {
myResource = theResource;
return this;
}
}

View File

@ -214,11 +214,13 @@ public abstract class BaseClient implements IRestfulClient {
try {
Map<String, List<String>> params = createExtraParams();
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()));

View File

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

View File

@ -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<A extends IParam> implements ICriterion<A>, ICriterionInte
@Override
public String getParameterValue(FhirContext theContext) {
if (isBlank(myValue)) {
return "";
}
if (myPrefix != null) {
return myPrefix.getValueForContext(theContext) + myValue;
}

View File

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

View File

@ -62,6 +62,7 @@ public class HttpPostClientInvocation extends BaseHttpClientInvocationWithConten
super(theContext, theParams, theUrlExtension);
}
@Override
protected RequestTypeEnum getRequestType() {
return RequestTypeEnum.POST;
}

View File

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

View File

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

View File

@ -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<String> FORMAT_VAL_JSON;
public static final Map<String, EncodingEnum> FORMAT_VAL_TO_ENCODING;
public static final Set<String> 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<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();
HashSet<String> valXml = new HashSet<String>();
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<String> valJson = new HashSet<String>();
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<Integer, String> statusNames = new HashMap<Integer, String>();

View File

@ -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<String, EncodingEnum> ourContentTypeToEncoding;
private static Map<String, EncodingEnum> ourContentTypeToEncodingNonLegacy;
private static Map<String, EncodingEnum> ourContentTypeToEncodingStrict;
static {
ourContentTypeToEncoding = new HashMap<String, EncodingEnum>();
ourContentTypeToEncodingNonLegacy = new HashMap<String, EncodingEnum>();
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<String, EncodingEnum>(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 <code>null</code> 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 <code>null</code> if no encoding
* 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 Map<String, EncodingEnum> getContentTypeToEncodingStrict() {
return ourContentTypeToEncodingStrict;
public static boolean isNonLegacy(String theFormat) {
return ourContentTypeToEncodingNonLegacy.containsKey(theFormat);
}
public String getFormatContentType() {
return myFormatContentType;
}
}

View File

@ -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<Servlet
addContentLocationHeaders(theRequest, servletResponse, response, resourceName);
}
if (outcome != null) {
EncodingEnum encoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequest);
ResponseEncoding encoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequest);
servletResponse.setContentType(encoding.getResourceContentType());
Writer writer = servletResponse.getWriter();
IParser parser = encoding.newParser(getFhirContext());
IParser parser = encoding.getEncoding().newParser(getFhirContext());
parser.setPrettyPrint(RestfulServerUtils.prettyPrintResponse(this, theRequest));
try {
outcome.execute(parser, writer);

View File

@ -61,6 +61,8 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.PreferReturnEnum;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.client.apache.ApacheHttpRequest;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.method.ElementsParameter;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.method.SummaryEnumParameter;
@ -169,6 +171,9 @@ public class RestfulServerUtils {
}
}
/**
* @TODO: this method is only called from one place and should be removed anyway
*/
public static EncodingEnum determineRequestEncoding(RequestDetails theReq) {
EncodingEnum retVal = determineRequestEncodingNoDefault(theReq);
if (retVal != null) {
@ -178,7 +183,15 @@ public class RestfulServerUtils {
}
public static EncodingEnum determineRequestEncodingNoDefault(RequestDetails theReq) {
EncodingEnum retVal = null;
ResponseEncoding retVal = determineRequestEncodingNoDefaultReturnRE(theReq);
if (retVal == null) {
return null;
}
return retVal.getEncoding();
}
private static ResponseEncoding determineRequestEncodingNoDefaultReturnRE(RequestDetails theReq) {
ResponseEncoding retVal = null;
Iterator<String> 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<String, EncodingEnum> 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<String> 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;
// }
// }
//
}
}
/*
* 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;
}
return null;
}
/**
* Determine whether a response should be given in JSON or XML format based on the incoming HttpServletRequest's
* <code>"_format"</code> parameter and <code>"Accept:"</code> 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<Date> extractLastUpdatedFromResource(IBaseResource theResource) {
IPrimitiveType<Date> 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();
@ -551,16 +576,16 @@ public class RestfulServerUtils {
return theRequestDetails.getResponse().sendWriterResponse(status, contentType, charset, writer);
}
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set<SummaryEnum> 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<SummaryEnum> theSummaryMode, int theStausCode, String theStatusMessage, boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType<Date> 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,7 +625,9 @@ 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,29 +696,18 @@ 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();
public static Integer tryToExtractNamedParameter(RequestDetails theRequest, String theParamName) {
String[] retVal = theRequest.getParameters().get(theParamName);
if (retVal == null) {
return null;
}
if (isNotBlank(resName)) {
retVal = theResourceId.withServerBase(theServerBase, resName);
try {
return Integer.parseInt(retVal[0]);
} catch (NumberFormatException e) {
ourLog.debug("Failed to parse {} value '{}': {}", new Object[] { theParamName, retVal[0], e });
return null;
}
}
return retVal;
}
public static IPrimitiveType<Date> extractLastUpdatedFromResource(IBaseResource theResource) {
IPrimitiveType<Date> 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;
}
// static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
// String countString = theRequest.getParameter(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<? extends IBaseResource> 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);
}
}
}

View File

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

View File

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

View File

@ -104,7 +104,7 @@ public class JaxRsResponse extends RestfulResponse<JaxRsRequest> {
}
protected String getParserType() {
EncodingEnum encodingEnum = RestfulServerUtils.determineResponseEncodingWithDefault(getRequestDetails());
EncodingEnum encodingEnum = RestfulServerUtils.determineResponseEncodingWithDefault(getRequestDetails()).getEncoding();
return encodingEnum == EncodingEnum.JSON ? MediaType.APPLICATION_JSON : MediaType.APPLICATION_XML;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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: '&lt;' (must be '{')"));
assertThat(responseContent, containsString("Content does not appear to be FHIR JSON, first non-whitespace character was: '<' (must be '{')"));
}
@Test

View File

@ -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("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>", 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("<Parameters xmlns=\"http://hl7.org/fhir\"><parameter><name value=\"resource\"/><resource><Patient xmlns=\"http://hl7.org/fhir\"><name><given value=\"GIVEN\"/></name></Patient></resource></parameter></Parameters>", 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());

View File

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

View File

@ -75,7 +75,7 @@ import ca.uhn.fhir.util.TestUtil;
public class AuthorizationInterceptorDstu2Test {
private static final String ERR403 = "<OperationOutcome xmlns=\"http://hl7.org/fhir\"><issue><severity value=\"error\"/><code value=\"processing\"/><diagnostics value=\"Access denied by default policy (no applicable rules)\"/></issue></OperationOutcome>";
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;

View File

@ -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<HttpUriRequest> 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("<div xmlns=\"http://www.w3.org/1999/xhtml\">FINAL VALUE</div>", ((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("<Patient xmlns=\"http://hl7.org/fhir\"><text><div xmlns=\"http://www.w3.org/1999/xhtml\">A PATIENT</div></text></Patient>", extractBodyAsString(capt));
}
@Test
public void testMimetypeXmlLegacy() throws Exception {
String requestCt = Constants.CT_FHIR_XML;
ArgumentCaptor<HttpUriRequest> 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("<div xmlns=\"http://www.w3.org/1999/xhtml\">FINAL VALUE</div>", ((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("<Patient xmlns=\"http://hl7.org/fhir\"><text><div xmlns=\"http://www.w3.org/1999/xhtml\">A PATIENT</div></text></Patient>", extractBodyAsString(capt));
}
@Test
public void testMimetypeJsonNew() throws Exception {
String requestCt = Constants.CT_FHIR_JSON_NEW;
ArgumentCaptor<HttpUriRequest> 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("<div xmlns=\"http://www.w3.org/1999/xhtml\">FINAL VALUE</div>", ((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\":\"<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">A PATIENT</div>\"}}", extractBodyAsString(capt));
}
@Test
public void testMimetypeJsonLegacy() throws Exception {
String requestCt = Constants.CT_FHIR_JSON;
ArgumentCaptor<HttpUriRequest> 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("<div xmlns=\"http://www.w3.org/1999/xhtml\">FINAL VALUE</div>", ((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\":\"<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">A PATIENT</div>\"}}", extractBodyAsString(capt));
}
private String extractBodyAsString(ArgumentCaptor<HttpUriRequest> capt) throws IOException {
String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent(), "UTF-8");
return body;
}
private ArgumentCaptor<HttpUriRequest> 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<HttpUriRequest> 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<Header[]>() {
@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<ReaderInputStream>() {
@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();
}
}

View File

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

View File

@ -136,7 +136,7 @@ public class RequestValidatingInterceptorDstu3Test {
assertEquals(422, status.getStatusLine().getStatusCode());
assertThat(status.toString(), containsString("X-FHIR-Request-Validation"));
assertThat(responseContent, containsString("<severity value=\"error\"/>"));
assertThat(responseContent, containsString("\"severity\":\"error\""));
}
@Test

View File

@ -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("<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().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("<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().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("<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().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("<Patient xmlns=\"http://hl7.org/fhir\">"));
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("<Patient xmlns=\"http://hl7.org/fhir\">"));
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("<Patient xmlns=\"http://hl7.org/fhir\">"));
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<Patient> 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<IBaseResource> search() {
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
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;
}
}
}

View File

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

View File

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

View File

@ -26,10 +26,26 @@
Gson (it was ignored by the Glassfish parser we were previously
using even though it was invalid)
</ul>
</ul>
]]>
</action>
<action type="add">
Both client and server now support the new Content Types decided in
<![CDATA[<a href="http://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_id=677&tracker_item_id=10199">FHIR #10199</a>]]>.
<![CDATA[<br/><br/>]]>
This means that the server now supports
<![CDATA[<code>application/fhir+xml</code> and <code>application/fhir+json</code>]]>
in addition to the older style
<![CDATA[<code>application/xml+fhir</code> and <code>application/json+fhir</code>]]>.
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 <![CDATA[<code>Accept</code>]]> header value which requests both
styles with a preference given to the new style when running in DSTU3 mode.
<![CDATA[<br/><br/>]]>
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.
</action>
<action type="fix">
Fix issue in DSTU1 Bundle parsing where unexpected elements in the bundle resulted in a failure
to parse.