Allow interceptors to modify request contents
This commit is contained in:
parent
0369b7fd70
commit
377bae8c16
|
@ -27,9 +27,6 @@ import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
// @RunWith(SpringJUnit4ClassRunner.class)
|
|
||||||
// @ContextConfiguration(classes= {TestR4WithoutLuceneConfig.class})
|
|
||||||
// @SuppressWarnings("unchecked")
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(classes = { TestR4WithoutLuceneConfig.class })
|
@ContextConfiguration(classes = { TestR4WithoutLuceneConfig.class })
|
||||||
public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
||||||
|
@ -79,62 +76,8 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
private FhirContext myFhirCtx;
|
private FhirContext myFhirCtx;
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myImmunizationDaoR4")
|
|
||||||
private IFhirResourceDao<Immunization> myImmunizationDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myLocationDaoR4")
|
|
||||||
private IFhirResourceDao<Location> myLocationDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myMediaDaoR4")
|
|
||||||
private IFhirResourceDao<Media> myMediaDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myMedicationDaoR4")
|
|
||||||
private IFhirResourceDao<Medication> myMedicationDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myMedicationRequestDaoR4")
|
|
||||||
private IFhirResourceDao<MedicationRequest> myMedicationRequestDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myNamingSystemDaoR4")
|
|
||||||
private IFhirResourceDao<NamingSystem> myNamingSystemDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myObservationDaoR4")
|
|
||||||
private IFhirResourceDao<Observation> myObservationDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myOperationDefinitionDaoR4")
|
|
||||||
private IFhirResourceDao<OperationDefinition> myOperationDefinitionDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myOrganizationDaoR4")
|
@Qualifier("myOrganizationDaoR4")
|
||||||
private IFhirResourceDao<Organization> myOrganizationDao;
|
private IFhirResourceDao<Organization> myOrganizationDao;
|
||||||
@Autowired
|
|
||||||
@Qualifier("myPatientDaoR4")
|
|
||||||
private IFhirResourceDaoPatient<Patient> myPatientDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myPractitionerDaoR4")
|
|
||||||
private IFhirResourceDao<Practitioner> myPractitionerDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myQuestionnaireDaoR4")
|
|
||||||
private IFhirResourceDao<Questionnaire> myQuestionnaireDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myQuestionnaireResponseDaoR4")
|
|
||||||
private IFhirResourceDao<QuestionnaireResponse> myQuestionnaireResponseDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myResourceProvidersR4")
|
|
||||||
private Object myResourceProviders;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("myStructureDefinitionDaoR4")
|
|
||||||
private IFhirResourceDao<StructureDefinition> myStructureDefinitionDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("mySubscriptionDaoR4")
|
|
||||||
private IFhirResourceDaoSubscription<Subscription> mySubscriptionDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("mySubstanceDaoR4")
|
|
||||||
private IFhirResourceDao<Substance> mySubstanceDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("mySystemDaoR4")
|
|
||||||
private IFhirSystemDao<Bundle, Meta> mySystemDao;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("mySystemProviderR4")
|
|
||||||
private JpaSystemProviderR4 mySystemProvider;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected PlatformTransactionManager myTxManager;
|
protected PlatformTransactionManager myTxManager;
|
||||||
|
@ -169,7 +112,7 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithRegularParam() throws Exception {
|
public void testSearchWithRegularParam() {
|
||||||
String methodName = "testEverythingIncludesBackReferences";
|
String methodName = "testEverythingIncludesBackReferences";
|
||||||
|
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
|
@ -183,7 +126,7 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithContent() throws Exception {
|
public void testSearchWithContent() {
|
||||||
String methodName = "testEverythingIncludesBackReferences";
|
String methodName = "testEverythingIncludesBackReferences";
|
||||||
|
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
|
@ -201,7 +144,7 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithText() throws Exception {
|
public void testSearchWithText() {
|
||||||
String methodName = "testEverythingIncludesBackReferences";
|
String methodName = "testEverythingIncludesBackReferences";
|
||||||
|
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
|
|
|
@ -10,6 +10,8 @@ import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
@ -348,6 +350,21 @@ public abstract class RequestDetails {
|
||||||
return myRequestContents;
|
return myRequestContents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method may be used to modify the contents of the incoming
|
||||||
|
* request by hardcoding a value which will be used instead of the
|
||||||
|
* value received by the client.
|
||||||
|
* <p>
|
||||||
|
* This method is useful for modifying the request body prior
|
||||||
|
* to parsing within interceptors. It generally only has an
|
||||||
|
* impact when called in the {@link IServerInterceptor#incomingRequestPostProcessed(RequestDetails, HttpServletRequest, HttpServletResponse)}
|
||||||
|
* method
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public void setRequestContents(byte[] theRequestContents) {
|
||||||
|
myRequestContents = theRequestContents;
|
||||||
|
}
|
||||||
|
|
||||||
private class RequestOperationCallback implements IRequestOperationCallback {
|
private class RequestOperationCallback implements IRequestOperationCallback {
|
||||||
|
|
||||||
private List<IServerInterceptor> getInterceptors() {
|
private List<IServerInterceptor> getInterceptors() {
|
||||||
|
|
|
@ -19,32 +19,40 @@ package ca.uhn.fhir.rest.server.method;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.api.Include;
|
||||||
|
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
||||||
|
import ca.uhn.fhir.parser.IParser;
|
||||||
|
import ca.uhn.fhir.rest.annotation.*;
|
||||||
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
import ca.uhn.fhir.rest.api.server.IRestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
||||||
|
import ca.uhn.fhir.rest.server.BundleProviders;
|
||||||
|
import ca.uhn.fhir.rest.server.IDynamicSearchResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.*;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import java.io.IOException;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import java.io.Reader;
|
||||||
import ca.uhn.fhir.model.api.*;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
|
import java.lang.reflect.Method;
|
||||||
import ca.uhn.fhir.parser.IParser;
|
import java.util.*;
|
||||||
import ca.uhn.fhir.rest.annotation.*;
|
|
||||||
import ca.uhn.fhir.rest.api.*;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import ca.uhn.fhir.rest.api.server.*;
|
|
||||||
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
|
||||||
import ca.uhn.fhir.rest.server.*;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.*;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
|
||||||
|
|
||||||
public abstract class BaseMethodBinding<T> {
|
public abstract class BaseMethodBinding<T> {
|
||||||
|
|
||||||
|
@ -460,14 +468,7 @@ public abstract class BaseMethodBinding<T> {
|
||||||
}
|
}
|
||||||
returnType = returnTypeFromAnnotation;
|
returnType = returnTypeFromAnnotation;
|
||||||
} else {
|
} else {
|
||||||
// if (IRestfulClient.class.isAssignableFrom(theMethod.getDeclaringClass())) {
|
|
||||||
// Clients don't define their methods in resource specific types, so they can
|
|
||||||
// infer their resource type from the method return type.
|
|
||||||
returnType = (Class<? extends IBaseResource>) returnTypeFromMethod;
|
returnType = (Class<? extends IBaseResource>) returnTypeFromMethod;
|
||||||
// } else {
|
|
||||||
// This is a plain provider method returning a resource, so it should be
|
|
||||||
// an operation or global search presumably
|
|
||||||
// returnType = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,26 +506,6 @@ public abstract class BaseMethodBinding<T> {
|
||||||
throw new ConfigurationException("Did not detect any FHIR annotations on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
throw new ConfigurationException("Did not detect any FHIR annotations on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// // each operation name must have a request type annotation and be
|
|
||||||
// unique
|
|
||||||
// if (null != read) {
|
|
||||||
// return rm;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// SearchMethodBinding sm = new SearchMethodBinding();
|
|
||||||
// if (null != search) {
|
|
||||||
// sm.setRequestType(SearchMethodBinding.RequestType.GET);
|
|
||||||
// } else if (null != theMethod.getAnnotation(PUT.class)) {
|
|
||||||
// sm.setRequestType(SearchMethodBinding.RequestType.PUT);
|
|
||||||
// } else if (null != theMethod.getAnnotation(POST.class)) {
|
|
||||||
// sm.setRequestType(SearchMethodBinding.RequestType.POST);
|
|
||||||
// } else if (null != theMethod.getAnnotation(DELETE.class)) {
|
|
||||||
// sm.setRequestType(SearchMethodBinding.RequestType.DELETE);
|
|
||||||
// } else {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return sm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isResourceInterface(Class<?> theReturnTypeFromMethod) {
|
private static boolean isResourceInterface(Class<?> theReturnTypeFromMethod) {
|
||||||
|
@ -555,8 +536,6 @@ public abstract class BaseMethodBinding<T> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
// boolean retVal = Modifier.isAbstract(theReturnType.getModifiers()) == false;
|
|
||||||
// return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean verifyMethodHasZeroOrOneOperationAnnotation(Method theNextMethod, Object... theAnnotations) {
|
public static boolean verifyMethodHasZeroOrOneOperationAnnotation(Method theNextMethod, Object... theAnnotations) {
|
||||||
|
@ -574,39 +553,8 @@ public abstract class BaseMethodBinding<T> {
|
||||||
}
|
}
|
||||||
if (obj1 == null) {
|
if (obj1 == null) {
|
||||||
return false;
|
return false;
|
||||||
// throw new ConfigurationException("Method '" +
|
|
||||||
// theNextMethod.getName() + "' on type '" +
|
|
||||||
// theNextMethod.getDeclaringClass().getSimpleName() +
|
|
||||||
// " has no FHIR method annotations.");
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ServletRequestDetails#getByteStreamRequestContents()
|
|
||||||
*/
|
|
||||||
public static class ActiveRequestReader implements IRequestReader {
|
|
||||||
@Override
|
|
||||||
public InputStream getInputStream(RequestDetails theRequestDetails) throws IOException {
|
|
||||||
return theRequestDetails.getInputStream();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ServletRequestDetails#getByteStreamRequestContents()
|
|
||||||
*/
|
|
||||||
public static class InactiveRequestReader implements IRequestReader {
|
|
||||||
@Override
|
|
||||||
public InputStream getInputStream(RequestDetails theRequestDetails) {
|
|
||||||
throw new IllegalStateException("The servlet-api JAR is not found on the classpath. Please check that this library is available.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ServletRequestDetails#getByteStreamRequestContents()
|
|
||||||
*/
|
|
||||||
public static interface IRequestReader {
|
|
||||||
InputStream getInputStream(RequestDetails theRequestDetails) throws IOException;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,38 +19,35 @@ package ca.uhn.fhir.rest.server.servlet;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.zip.GZIPInputStream;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
|
import org.apache.commons.io.IOUtils;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseMethodBinding.IRequestReader;
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
public class ServletRequestDetails extends RequestDetails {
|
public class ServletRequestDetails extends RequestDetails {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServletRequestDetails.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServletRequestDetails.class);
|
||||||
/**
|
|
||||||
* @see BaseMethodBinding#loadRequestContents(RequestDetails)
|
|
||||||
*/
|
|
||||||
private static volatile IRequestReader ourRequestReader;
|
|
||||||
private RestfulServer myServer;
|
private RestfulServer myServer;
|
||||||
private HttpServletRequest myServletRequest;
|
private HttpServletRequest myServletRequest;
|
||||||
private HttpServletResponse myServletResponse;
|
private HttpServletResponse myServletResponse;
|
||||||
private byte[] requestContents;
|
|
||||||
|
|
||||||
public ServletRequestDetails() {
|
public ServletRequestDetails() {
|
||||||
super();
|
super();
|
||||||
|
@ -59,36 +56,9 @@ public class ServletRequestDetails extends RequestDetails {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] getByteStreamRequestContents() {
|
protected byte[] getByteStreamRequestContents() {
|
||||||
/*
|
|
||||||
* This is weird, but this class is used both in clients and in servers, and we want to avoid needing to depend on
|
|
||||||
* servlet-api in clients since there is no point. So we dynamically load a class that does the servlet processing
|
|
||||||
* in servers. Down the road it may make sense to just split the method binding classes into server and client
|
|
||||||
* versions, but this isn't actually a huge deal I don't think.
|
|
||||||
*/
|
|
||||||
IRequestReader reader = ourRequestReader;
|
|
||||||
if (reader == null) {
|
|
||||||
try {
|
try {
|
||||||
Class.forName("javax.servlet.ServletInputStream");
|
InputStream inputStream = getInputStream();
|
||||||
String className = BaseMethodBinding.class.getName() + "$" + "ActiveRequestReader";
|
byte[] requestContents = IOUtils.toByteArray(inputStream);
|
||||||
try {
|
|
||||||
reader = (IRequestReader) Class.forName(className).newInstance();
|
|
||||||
} catch (Exception e1) {
|
|
||||||
throw new ConfigurationException("Failed to instantiate class " + className, e1);
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
String className = BaseMethodBinding.class.getName() + "$" + "InactiveRequestReader";
|
|
||||||
try {
|
|
||||||
reader = (IRequestReader) Class.forName(className).newInstance();
|
|
||||||
} catch (Exception e1) {
|
|
||||||
throw new ConfigurationException("Failed to instantiate class " + className, e1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ourRequestReader = reader;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
InputStream inputStream = reader.getInputStream(this);
|
|
||||||
requestContents = IOUtils.toByteArray(inputStream);
|
|
||||||
|
|
||||||
if (myServer.isUncompressIncomingContents()) {
|
if (myServer.isUncompressIncomingContents()) {
|
||||||
String contentEncoding = myServletRequest.getHeader(Constants.HEADER_CONTENT_ENCODING);
|
String contentEncoding = myServletRequest.getHeader(Constants.HEADER_CONTENT_ENCODING);
|
||||||
|
@ -100,7 +70,6 @@ public class ServletRequestDetails extends RequestDetails {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME resource leak
|
|
||||||
return requestContents;
|
return requestContents;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
ourLog.error("Could not load request resource", e);
|
ourLog.error("Could not load request resource", e);
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import static org.hamcrest.Matchers.contains;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.mockito.Matchers.any;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
import ca.uhn.fhir.rest.annotation.Create;
|
||||||
|
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Validate;
|
||||||
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
|
||||||
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
@ -26,6 +28,7 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hamcrest.core.StringContains;
|
||||||
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
||||||
import org.hl7.fhir.dstu3.model.Patient;
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
@ -33,18 +36,14 @@ import org.junit.*;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
import java.util.ArrayList;
|
||||||
import ca.uhn.fhir.rest.annotation.Validate;
|
import java.util.concurrent.TimeUnit;
|
||||||
import ca.uhn.fhir.rest.api.*;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import static org.junit.Assert.*;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import static org.mockito.Matchers.any;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
import static org.mockito.Mockito.*;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
|
|
||||||
public class InterceptorDstu3Test {
|
public class InterceptorDstu3Test {
|
||||||
|
|
||||||
|
@ -53,6 +52,7 @@ public class InterceptorDstu3Test {
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
private static RestfulServer ourServlet;
|
private static RestfulServer ourServlet;
|
||||||
|
private static Patient ourLastPatient;
|
||||||
private IServerInterceptor myInterceptor1;
|
private IServerInterceptor myInterceptor1;
|
||||||
private IServerInterceptor myInterceptor2;
|
private IServerInterceptor myInterceptor2;
|
||||||
|
|
||||||
|
@ -69,79 +69,18 @@ public class InterceptorDstu3Test {
|
||||||
myInterceptor2 = mock(IServerInterceptor.class);
|
myInterceptor2 = mock(IServerInterceptor.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
private String createInput() {
|
||||||
@Test
|
return "{\n" +
|
||||||
public void testServerOperationInterceptorAdapterMethods() {
|
" \"resourceType\":\"Patient\",\n" +
|
||||||
ServerOperationInterceptorAdapter i = new ServerOperationInterceptorAdapter();
|
" \"id\":\"1855669\",\n" +
|
||||||
i.resourceCreated(null, null);
|
" \"meta\":{\n" +
|
||||||
i.resourceDeleted(null, null);
|
" \"versionId\":\"1\",\n" +
|
||||||
i.resourceUpdated(null, null);
|
" \"lastUpdated\":\"2016-02-18T07:41:35.953-05:00\"\n" +
|
||||||
i.resourceUpdated(null, null, null);
|
" },\n" +
|
||||||
|
" \"active\":true\n" +
|
||||||
|
"}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testResponseWithOperationOutcome() throws Exception {
|
|
||||||
ourServlet.setInterceptors(myInterceptor1);
|
|
||||||
|
|
||||||
when(myInterceptor1.incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
|
||||||
when(myInterceptor1.incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
|
||||||
when(myInterceptor1.outgoingResponse(any(RequestDetails.class), any(IResource.class))).thenReturn(true);
|
|
||||||
|
|
||||||
String input = createInput();
|
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$validate");
|
|
||||||
httpPost.setEntity(new StringEntity(input, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
|
|
||||||
InOrder order = inOrder(myInterceptor1);
|
|
||||||
order.verify(myInterceptor1, times(1)).incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
|
||||||
order.verify(myInterceptor1, times(1)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
|
||||||
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
|
||||||
ArgumentCaptor<ActionRequestDetails> arTypeCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
|
||||||
ArgumentCaptor<IBaseResource> resourceCapt = ArgumentCaptor.forClass(IBaseResource.class);
|
|
||||||
order.verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
|
||||||
order.verify(myInterceptor1, times(1)).outgoingResponse(any(RequestDetails.class), resourceCapt.capture());
|
|
||||||
|
|
||||||
assertEquals(1, resourceCapt.getAllValues().size());
|
|
||||||
assertEquals(OperationOutcome.class, resourceCapt.getAllValues().get(0).getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testResponseWithNothing() throws Exception {
|
|
||||||
ourServlet.setInterceptors(myInterceptor1);
|
|
||||||
|
|
||||||
when(myInterceptor1.incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
|
||||||
when(myInterceptor1.incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
|
||||||
when(myInterceptor1.outgoingResponse(any(RequestDetails.class), any(IResource.class))).thenReturn(true);
|
|
||||||
|
|
||||||
String input = createInput();
|
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
|
||||||
httpPost.setEntity(new StringEntity(input, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
|
||||||
try {
|
|
||||||
assertEquals(201, status.getStatusLine().getStatusCode());
|
|
||||||
} finally {
|
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
}
|
|
||||||
|
|
||||||
InOrder order = inOrder(myInterceptor1);
|
|
||||||
verify(myInterceptor1, times(1)).incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
|
||||||
verify(myInterceptor1, times(1)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
|
||||||
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
|
||||||
ArgumentCaptor<ActionRequestDetails> arTypeCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
|
||||||
ArgumentCaptor<RequestDetails> rdCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
|
||||||
ArgumentCaptor<IBaseResource> resourceCapt = ArgumentCaptor.forClass(IBaseResource.class);
|
|
||||||
verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
|
||||||
verify(myInterceptor1, times(1)).outgoingResponse(any(RequestDetails.class), resourceCapt.capture());
|
|
||||||
|
|
||||||
assertEquals(1, resourceCapt.getAllValues().size());
|
|
||||||
assertEquals(null, resourceCapt.getAllValues().get(0));
|
|
||||||
// assertEquals("", rdCapt.getAllValues().get(0).get)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResourceResponseIncluded() throws Exception {
|
public void testResourceResponseIncluded() throws Exception {
|
||||||
ourServlet.setInterceptors(myInterceptor1, myInterceptor2);
|
ourServlet.setInterceptors(myInterceptor1, myInterceptor2);
|
||||||
|
@ -184,16 +123,91 @@ public class InterceptorDstu3Test {
|
||||||
assertNotNull(arTypeCapt.getValue().getResource());
|
assertNotNull(arTypeCapt.getValue().getResource());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createInput() {
|
public void testModifyResponse() {
|
||||||
return "{\n" +
|
InterceptorAdapter interceptor = new InterceptorAdapter(){
|
||||||
" \"resourceType\":\"Patient\",\n" +
|
@Override
|
||||||
" \"id\":\"1855669\",\n" +
|
public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
||||||
" \"meta\":{\n" +
|
ServletRequestDetails srd = (ServletRequestDetails)theRequestDetails;
|
||||||
" \"versionId\":\"1\",\n" +
|
String input = new String(srd.loadRequestContents(), Constants.CHARSET_UTF8);
|
||||||
" \"lastUpdated\":\"2016-02-18T07:41:35.953-05:00\"\n" +
|
assertThat(input, StringContains.containsString("\"active\":true"));
|
||||||
" },\n" +
|
|
||||||
" \"active\":true\n" +
|
String newInput = createInput().replace("true", "false");
|
||||||
"}";
|
srd.setRequestContents(newInput.getBytes(Constants.CHARSET_UTF8));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResponseWithNothing() throws Exception {
|
||||||
|
ourServlet.setInterceptors(myInterceptor1);
|
||||||
|
|
||||||
|
when(myInterceptor1.incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(myInterceptor1.incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(myInterceptor1.outgoingResponse(any(RequestDetails.class), any(IResource.class))).thenReturn(true);
|
||||||
|
|
||||||
|
String input = createInput();
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
|
httpPost.setEntity(new StringEntity(input, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||||
|
HttpResponse status = ourClient.execute(httpPost);
|
||||||
|
try {
|
||||||
|
assertEquals(201, status.getStatusLine().getStatusCode());
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
InOrder order = inOrder(myInterceptor1);
|
||||||
|
verify(myInterceptor1, times(1)).incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
|
verify(myInterceptor1, times(1)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
|
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
||||||
|
ArgumentCaptor<ActionRequestDetails> arTypeCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||||
|
ArgumentCaptor<RequestDetails> rdCapt = ArgumentCaptor.forClass(RequestDetails.class);
|
||||||
|
ArgumentCaptor<IBaseResource> resourceCapt = ArgumentCaptor.forClass(IBaseResource.class);
|
||||||
|
verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
||||||
|
verify(myInterceptor1, times(1)).outgoingResponse(any(RequestDetails.class), resourceCapt.capture());
|
||||||
|
|
||||||
|
assertEquals(1, resourceCapt.getAllValues().size());
|
||||||
|
assertEquals(null, resourceCapt.getAllValues().get(0));
|
||||||
|
// assertEquals("", rdCapt.getAllValues().get(0).get)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResponseWithOperationOutcome() throws Exception {
|
||||||
|
ourServlet.setInterceptors(myInterceptor1);
|
||||||
|
|
||||||
|
when(myInterceptor1.incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(myInterceptor1.incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(myInterceptor1.outgoingResponse(any(RequestDetails.class), any(IResource.class))).thenReturn(true);
|
||||||
|
|
||||||
|
String input = createInput();
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$validate");
|
||||||
|
httpPost.setEntity(new StringEntity(input, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8")));
|
||||||
|
HttpResponse status = ourClient.execute(httpPost);
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
InOrder order = inOrder(myInterceptor1);
|
||||||
|
order.verify(myInterceptor1, times(1)).incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
|
order.verify(myInterceptor1, times(1)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
|
ArgumentCaptor<RestOperationTypeEnum> opTypeCapt = ArgumentCaptor.forClass(RestOperationTypeEnum.class);
|
||||||
|
ArgumentCaptor<ActionRequestDetails> arTypeCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
|
||||||
|
ArgumentCaptor<IBaseResource> resourceCapt = ArgumentCaptor.forClass(IBaseResource.class);
|
||||||
|
order.verify(myInterceptor1, times(1)).incomingRequestPreHandled(opTypeCapt.capture(), arTypeCapt.capture());
|
||||||
|
order.verify(myInterceptor1, times(1)).outgoingResponse(any(RequestDetails.class), resourceCapt.capture());
|
||||||
|
|
||||||
|
assertEquals(1, resourceCapt.getAllValues().size());
|
||||||
|
assertEquals(OperationOutcome.class, resourceCapt.getAllValues().get(0).getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Test
|
||||||
|
public void testServerOperationInterceptorAdapterMethods() {
|
||||||
|
ServerOperationInterceptorAdapter i = new ServerOperationInterceptorAdapter();
|
||||||
|
i.resourceCreated(null, null);
|
||||||
|
i.resourceDeleted(null, null);
|
||||||
|
i.resourceUpdated(null, null);
|
||||||
|
i.resourceUpdated(null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
@ -226,6 +240,13 @@ public class InterceptorDstu3Test {
|
||||||
|
|
||||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
|
||||||
|
@Create()
|
||||||
|
public MethodOutcome create(@ResourceParam Patient theResource) {
|
||||||
|
ourLastPatient = theResource;
|
||||||
|
return new MethodOutcome();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<Patient> getResourceType() {
|
public Class<Patient> getResourceType() {
|
||||||
return Patient.class;
|
return Patient.class;
|
||||||
|
@ -236,11 +257,6 @@ public class InterceptorDstu3Test {
|
||||||
return new MethodOutcome();
|
return new MethodOutcome();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Create()
|
|
||||||
public MethodOutcome create(@ResourceParam Patient theResource) {
|
|
||||||
return new MethodOutcome();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import static org.hamcrest.Matchers.not;
|
import ca.uhn.fhir.rest.annotation.*;
|
||||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
import static org.junit.Assert.assertEquals;
|
import ca.uhn.fhir.rest.client.MyPatientWithExtensions;
|
||||||
import static org.junit.Assert.assertThat;
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
@ -25,31 +20,57 @@ import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.*;
|
import org.hl7.fhir.r4.model.DateType;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
|
import org.hl7.fhir.r4.model.OperationOutcome;
|
||||||
import org.hl7.fhir.r4.model.OperationOutcome.OperationOutcomeIssueComponent;
|
import org.hl7.fhir.r4.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||||
import org.junit.*;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import java.nio.charset.StandardCharsets;
|
||||||
import ca.uhn.fhir.rest.annotation.*;
|
import java.util.ArrayList;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import java.util.List;
|
||||||
import ca.uhn.fhir.rest.client.MyPatientWithExtensions;
|
import java.util.concurrent.TimeUnit;
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class CreateR4Test {
|
public class CreateR4Test {
|
||||||
private static CloseableHttpClient ourClient;
|
|
||||||
|
|
||||||
private static FhirContext ourCtx = FhirContext.forR4();
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CreateR4Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CreateR4Test.class);
|
||||||
|
public static IBaseOperationOutcome ourReturnOo;
|
||||||
|
private static CloseableHttpClient ourClient;
|
||||||
|
private static FhirContext ourCtx = FhirContext.forR4();
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
public static IBaseOperationOutcome ourReturnOo;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
ourReturnOo = null;
|
ourReturnOo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateIgnoresIdInResourceBody() throws Exception {
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
|
httpPost.setEntity(new StringEntity("{\"resourceType\":\"Patient\", \"id\":\"999\", \"status\":\"active\"}", ContentType.parse("application/fhir+json; charset=utf-8")));
|
||||||
|
HttpResponse status = ourClient.execute(httpPost);
|
||||||
|
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(201, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertEquals(1, status.getHeaders("Location").length);
|
||||||
|
assertEquals(0, status.getHeaders("Content-Location").length);
|
||||||
|
assertEquals("http://localhost:" + ourPort + "/Patient/1", status.getFirstHeader("Location").getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* #472
|
* #472
|
||||||
*/
|
*/
|
||||||
|
@ -91,28 +112,6 @@ public class CreateR4Test {
|
||||||
assertThat(responseContent, containsString("DIAG"));
|
assertThat(responseContent, containsString("DIAG"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* #342
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testCreateWithInvalidContent() throws Exception {
|
|
||||||
|
|
||||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
|
||||||
httpPost.setEntity(new StringEntity("FOO", ContentType.parse("application/xml+fhir; charset=utf-8")));
|
|
||||||
HttpResponse status = ourClient.execute(httpPost);
|
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
|
||||||
|
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
|
||||||
|
|
||||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
|
||||||
|
|
||||||
assertThat(responseContent, containsString("<OperationOutcome xmlns=\"http://hl7.org/fhir\"><issue><severity value=\"error\"/><code value=\"processing\"/><diagnostics value=\""));
|
|
||||||
assertThat(responseContent, containsString("Failed to parse request body as XML resource. Error was: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character 'F'"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWithIncorrectContent1() throws Exception {
|
public void testCreateWithIncorrectContent1() throws Exception {
|
||||||
|
|
||||||
|
@ -169,6 +168,28 @@ public class CreateR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #342
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCreateWithInvalidContent() throws Exception {
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
|
||||||
|
httpPost.setEntity(new StringEntity("FOO", ContentType.parse("application/xml+fhir; charset=utf-8")));
|
||||||
|
HttpResponse status = ourClient.execute(httpPost);
|
||||||
|
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertThat(responseContent, containsString("<OperationOutcome xmlns=\"http://hl7.org/fhir\"><issue><severity value=\"error\"/><code value=\"processing\"/><diagnostics value=\""));
|
||||||
|
assertThat(responseContent, containsString("Failed to parse request body as XML resource. Error was: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character 'F'"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearch() throws Exception {
|
public void testSearch() throws Exception {
|
||||||
|
|
||||||
|
@ -231,6 +252,7 @@ public class CreateR4Test {
|
||||||
|
|
||||||
@Create()
|
@Create()
|
||||||
public MethodOutcome create(@ResourceParam Patient theIdParam) {
|
public MethodOutcome create(@ResourceParam Patient theIdParam) {
|
||||||
|
assertNull(theIdParam.getIdElement().getIdPart());
|
||||||
return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(ourReturnOo);
|
return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(ourReturnOo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,12 @@
|
||||||
can be useful in order to allow interceptors to
|
can be useful in order to allow interceptors to
|
||||||
change payload contents being saved.
|
change payload contents being saved.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="add">
|
||||||
|
A new method has been added to RequestDetails called
|
||||||
|
<![CDATA[<code>setRequestContents()]]> which can be used
|
||||||
|
by interceptors to modify the request body before it
|
||||||
|
is parsed by the server.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="3.1.0" date="2017-11-23">
|
<release version="3.1.0" date="2017-11-23">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
Loading…
Reference in New Issue