Ensure that parsed reesource is available to interceptors
This commit is contained in:
parent
10d969c514
commit
53b47ed580
|
@ -90,42 +90,6 @@ public abstract class BaseMethodBinding<T> {
|
||||||
myMethod.setAccessible(true);
|
myMethod.setAccessible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IParser createAppropriateParserForParsingResponse(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, List<Class<? extends IBaseResource>> thePreferTypes) {
|
|
||||||
EncodingEnum encoding = EncodingEnum.forContentType(theResponseMimeType);
|
|
||||||
if (encoding == null) {
|
|
||||||
NonFhirResponseException ex = NonFhirResponseException.newInstance(theResponseStatusCode, theResponseMimeType, theResponseReader);
|
|
||||||
populateException(ex, theResponseReader);
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
IParser parser = encoding.newParser(getContext());
|
|
||||||
|
|
||||||
parser.setPreferTypes(thePreferTypes);
|
|
||||||
|
|
||||||
return parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IParser createAppropriateParserForParsingServerRequest(RequestDetails theRequest) {
|
|
||||||
String contentTypeHeader = theRequest.getHeader(Constants.HEADER_CONTENT_TYPE);
|
|
||||||
EncodingEnum encoding;
|
|
||||||
if (isBlank(contentTypeHeader)) {
|
|
||||||
encoding = EncodingEnum.XML;
|
|
||||||
} else {
|
|
||||||
int semicolon = contentTypeHeader.indexOf(';');
|
|
||||||
if (semicolon != -1) {
|
|
||||||
contentTypeHeader = contentTypeHeader.substring(0, semicolon);
|
|
||||||
}
|
|
||||||
encoding = EncodingEnum.forContentType(contentTypeHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (encoding == null) {
|
|
||||||
throw new InvalidRequestException("Request contins non-FHIR conent-type header value: " + contentTypeHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
IParser parser = encoding.newParser(getContext());
|
|
||||||
return parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object[] createMethodParams(RequestDetails theRequest) {
|
protected Object[] createMethodParams(RequestDetails theRequest) {
|
||||||
Object[] params = new Object[getParameters().size()];
|
Object[] params = new Object[getParameters().size()];
|
||||||
for (int i = 0; i < getParameters().size(); i++) {
|
for (int i = 0; i < getParameters().size(); i++) {
|
||||||
|
|
|
@ -128,10 +128,16 @@ abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOu
|
||||||
/*
|
/*
|
||||||
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
|
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
|
||||||
*/
|
*/
|
||||||
|
IBaseResource resource;
|
||||||
if (myResourceParameterIndex != -1) {
|
if (myResourceParameterIndex != -1) {
|
||||||
theDetails.setResource((IBaseResource) theMethodParams[myResourceParameterIndex]);
|
resource = (IBaseResource) theMethodParams[myResourceParameterIndex];
|
||||||
} else {
|
} else {
|
||||||
theDetails.setResource(ResourceParameter.parseResourceFromRequest(theRequestDetails, this, myResourceType));
|
resource = ResourceParameter.parseResourceFromRequest(theRequestDetails, this, myResourceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
theRequestDetails.setResource(resource);
|
||||||
|
if (theDetails != null) {
|
||||||
|
theDetails.setResource(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,8 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
|
||||||
public IBaseResource doInvokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) {
|
public IBaseResource doInvokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) {
|
||||||
Object[] params = createMethodParams(theRequest);
|
Object[] params = createMethodParams(theRequest);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Object resultObj = invokeServer(theServer, theRequest, params);
|
Object resultObj = invokeServer(theServer, theRequest, params);
|
||||||
|
|
||||||
Integer count = RestfulServerUtils.extractCountParameter(theRequest);
|
Integer count = RestfulServerUtils.extractCountParameter(theRequest);
|
||||||
|
|
|
@ -285,6 +285,8 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
theMethodParams[myIdParamIndex] = theRequest.getId();
|
theMethodParams[myIdParamIndex] = theRequest.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// populateActionRequestDetailsForInterceptor(theRequest); AAAAAA
|
||||||
|
|
||||||
Object response = invokeServerMethod(theServer, theRequest, theMethodParams);
|
Object response = invokeServerMethod(theServer, theRequest, theMethodParams);
|
||||||
IBundleProvider retVal = toResourceList(response);
|
IBundleProvider retVal = toResourceList(response);
|
||||||
return retVal;
|
return retVal;
|
||||||
|
@ -309,7 +311,11 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
@Override
|
@Override
|
||||||
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
|
protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails, ActionRequestDetails theDetails, Object[] theMethodParams) {
|
||||||
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
|
super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);
|
||||||
theDetails.setResource((IBaseResource) theRequestDetails.getUserData().get(OperationParameter.REQUEST_CONTENTS_USERDATA_KEY));
|
IBaseResource resource = (IBaseResource) theRequestDetails.getUserData().get(OperationParameter.REQUEST_CONTENTS_USERDATA_KEY);
|
||||||
|
theRequestDetails.setResource(resource);
|
||||||
|
if (theDetails != null) {
|
||||||
|
theDetails.setResource(resource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ReturnType {
|
public static class ReturnType {
|
||||||
|
|
|
@ -167,11 +167,17 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
||||||
/*
|
/*
|
||||||
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
|
* If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
|
||||||
*/
|
*/
|
||||||
|
IBaseResource resource;
|
||||||
if (myTransactionParamIndex != -1) {
|
if (myTransactionParamIndex != -1) {
|
||||||
theDetails.setResource((IBaseResource) theMethodParams[myTransactionParamIndex]);
|
resource = (IBaseResource) theMethodParams[myTransactionParamIndex];
|
||||||
} else {
|
} else {
|
||||||
Class<? extends IBaseResource> resourceType = getContext().getResourceDefinition("Bundle").getImplementingClass();
|
Class<? extends IBaseResource> resourceType = getContext().getResourceDefinition("Bundle").getImplementingClass();
|
||||||
theDetails.setResource(ResourceParameter.parseResourceFromRequest(theRequestDetails, this, resourceType));
|
resource = ResourceParameter.parseResourceFromRequest(theRequestDetails, this, resourceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
theRequestDetails.setResource(resource);
|
||||||
|
if (theDetails != null) {
|
||||||
|
theDetails.setResource(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||||
|
import ca.uhn.fhir.interceptor.api.IAnonymousInterceptor;
|
||||||
|
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.rest.annotation.*;
|
import ca.uhn.fhir.rest.annotation.*;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
|
@ -28,9 +31,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.hl7.fhir.dstu3.model.IdType;
|
import org.hl7.fhir.dstu3.model.*;
|
||||||
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
|
||||||
import org.hl7.fhir.dstu3.model.Patient;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
@ -40,6 +41,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
@ -81,6 +83,38 @@ public class InterceptorDstu3Test {
|
||||||
"}";
|
"}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServerPreHandledOnOperationCapturesResource() throws IOException {
|
||||||
|
|
||||||
|
AtomicReference<IBaseResource> resource = new AtomicReference<>();
|
||||||
|
IAnonymousInterceptor interceptor = new IAnonymousInterceptor() {
|
||||||
|
@Override
|
||||||
|
public void invoke(Pointcut thePointcut, HookParams theArgs) {
|
||||||
|
RequestDetails requestDetails = theArgs.get(RequestDetails.class);
|
||||||
|
resource.set(requestDetails.getResource());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ourServlet.getInterceptorService().registerAnonymousInterceptor(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED, interceptor);
|
||||||
|
try {
|
||||||
|
Parameters p = new Parameters();
|
||||||
|
p.addParameter().setName("limit").setValue(new IntegerType(123));
|
||||||
|
String input = ourCtx.newJsonParser().encodeResourceToString(p);
|
||||||
|
|
||||||
|
HttpPost post = new HttpPost("http://localhost:" + ourPort + "/Patient/$postOperation");
|
||||||
|
post.setEntity(new StringEntity(input, ContentType.create("application/fhir+json", Constants.CHARSET_UTF8)));
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(post)) {
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
ourServlet.unregisterInterceptor(interceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(resource.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testModifyResponse() throws IOException {
|
public void testModifyResponse() throws IOException {
|
||||||
InterceptorAdapter interceptor = new InterceptorAdapter() {
|
InterceptorAdapter interceptor = new InterceptorAdapter() {
|
||||||
|
@ -271,6 +305,13 @@ public class InterceptorDstu3Test {
|
||||||
return new MethodOutcome();
|
return new MethodOutcome();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(name="$postOperation")
|
||||||
|
public Parameters postOperation(
|
||||||
|
@OperationParam(name = "limit") IntegerType theLimit
|
||||||
|
) {
|
||||||
|
return new Parameters();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<Patient> getResourceType() {
|
public Class<Patient> getResourceType() {
|
||||||
return Patient.class;
|
return Patient.class;
|
||||||
|
|
Loading…
Reference in New Issue