Document interceptor framework
This commit is contained in:
parent
9bb10a5968
commit
794db6a141
|
@ -0,0 +1,80 @@
|
||||||
|
package example;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||||
|
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||||
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
|
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||||
|
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
|
||||||
|
public class ServerInterceptors {
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static void main(String[] args) throws DataFormatException, IOException {
|
||||||
|
|
||||||
|
|
||||||
|
// START SNIPPET: resourceExtension
|
||||||
|
// Create an example patient
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addIdentifier(IdentifierUseEnum.OFFICIAL, "urn:example", "7000135", null);
|
||||||
|
|
||||||
|
// Create an extension
|
||||||
|
ExtensionDt ext = new ExtensionDt();
|
||||||
|
ext.setModifier(false);
|
||||||
|
ext.setUrl("http://example.com/extensions#someext");
|
||||||
|
ext.setValue(new DateTimeDt("2011-01-02T11:13:15"));
|
||||||
|
|
||||||
|
// Add the extension to the resource
|
||||||
|
patient.addUndeclaredExtension(ext);
|
||||||
|
//END SNIPPET: resourceExtension
|
||||||
|
|
||||||
|
|
||||||
|
//START SNIPPET: resourceStringExtension
|
||||||
|
HumanNameDt name = patient.addName();
|
||||||
|
name.addFamily().setValue("Shmoe");
|
||||||
|
StringDt given = name.addGiven();
|
||||||
|
given.setValue("Joe");
|
||||||
|
ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#moreext", new StringDt("Hello"));
|
||||||
|
given.addUndeclaredExtension(ext2);
|
||||||
|
//END SNIPPET: resourceStringExtension
|
||||||
|
|
||||||
|
String output = new FhirContext().newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
|
||||||
|
System.out.println(output);
|
||||||
|
|
||||||
|
|
||||||
|
//START SNIPPET: parseExtension
|
||||||
|
// Get all extensions (modifier or not) for a given URL
|
||||||
|
List<ExtensionDt> resourceExts = patient.getUndeclaredExtensionsByUrl("http://fooextensions.com#exts");
|
||||||
|
|
||||||
|
// Get all non-modifier extensions regardless of URL
|
||||||
|
List<ExtensionDt> nonModExts = patient.getUndeclaredExtensions();
|
||||||
|
|
||||||
|
//Get all non-modifier extensions regardless of URL
|
||||||
|
List<ExtensionDt> modExts = patient.getUndeclaredModifierExtensions();
|
||||||
|
//END SNIPPET: parseExtension
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void foo() {
|
||||||
|
//START SNIPPET: subExtension
|
||||||
|
Patient patient = new Patient();
|
||||||
|
|
||||||
|
ExtensionDt parent = new ExtensionDt(false, "http://example.com#parent");
|
||||||
|
patient.addUndeclaredExtension(parent);
|
||||||
|
|
||||||
|
ExtensionDt child1 = new ExtensionDt(false, "http://example.com#childOne", new StringDt("value1"));
|
||||||
|
parent.addUndeclaredExtension(child1);
|
||||||
|
|
||||||
|
ExtensionDt child2 = new ExtensionDt(false, "http://example.com#childTwo", new StringDt("value1"));
|
||||||
|
parent.addUndeclaredExtension(child2);
|
||||||
|
//END SNIPPET: subExtension
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -12,6 +12,13 @@
|
||||||
Allow generic client ... OAUTH
|
Allow generic client ... OAUTH
|
||||||
</action>
|
</action>
|
||||||
-->
|
-->
|
||||||
|
<action type="add">
|
||||||
|
Add server interceptor framework, and new interceptor for logging incoming
|
||||||
|
requests.
|
||||||
|
</action>
|
||||||
|
<action type="add">
|
||||||
|
Add server validation framework for validating resources against the FHIR schemas and schematrons
|
||||||
|
</action>
|
||||||
<action type="fix">
|
<action type="fix">
|
||||||
Tester UI created double _format and _pretty param entries in searches. Thanks to Gered King of University
|
Tester UI created double _format and _pretty param entries in searches. Thanks to Gered King of University
|
||||||
Health Network for reporting!
|
Health Network for reporting!
|
||||||
|
|
|
@ -176,7 +176,8 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
|
||||||
}
|
}
|
||||||
invokeServerMethod(params);
|
invokeServerMethod(params);
|
||||||
|
|
||||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||||
|
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||||
boolean continueProcessing = next.outgoingResponse(theRequest, theRequest.getServletRequest(), theRequest.getServletResponse());
|
boolean continueProcessing = next.outgoingResponse(theRequest, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||||
if (!continueProcessing) {
|
if (!continueProcessing) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -149,7 +149,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
||||||
}
|
}
|
||||||
|
|
||||||
OperationOutcome outcome = response != null ? response.getOperationOutcome():null;
|
OperationOutcome outcome = response != null ? response.getOperationOutcome():null;
|
||||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||||
|
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||||
boolean continueProcessing = next.outgoingResponse(theRequest, outcome, theRequest.getServletRequest(), theRequest.getServletResponse());
|
boolean continueProcessing = next.outgoingResponse(theRequest, outcome, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||||
if (!continueProcessing) {
|
if (!continueProcessing) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -231,7 +231,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
||||||
|
|
||||||
Bundle bundle = RestfulServer.createBundleFromBundleProvider(theServer, response, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode, 0, count, null);
|
Bundle bundle = RestfulServer.createBundleFromBundleProvider(theServer, response, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode, 0, count, null);
|
||||||
|
|
||||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||||
|
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||||
boolean continueProcessing = next.outgoingResponse(theRequest, bundle, theRequest.getServletRequest(), theRequest.getServletResponse());
|
boolean continueProcessing = next.outgoingResponse(theRequest, bundle, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||||
if (!continueProcessing) {
|
if (!continueProcessing) {
|
||||||
return;
|
return;
|
||||||
|
@ -249,7 +250,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
|
||||||
|
|
||||||
IResource resource = result.getResources(0, 1).get(0);
|
IResource resource = result.getResources(0, 1).get(0);
|
||||||
|
|
||||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||||
|
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||||
boolean continueProcessing = next.outgoingResponse(theRequest, resource, theRequest.getServletRequest(), theRequest.getServletResponse());
|
boolean continueProcessing = next.outgoingResponse(theRequest, resource, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||||
if (!continueProcessing) {
|
if (!continueProcessing) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -156,7 +156,8 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
||||||
|
|
||||||
TagList resp = (TagList) invokeServerMethod(params);
|
TagList resp = (TagList) invokeServerMethod(params);
|
||||||
|
|
||||||
for (IServerInterceptor next : theServer.getInterceptors()) {
|
for (int i = theServer.getInterceptors().size() - 1; i >= 0; i--) {
|
||||||
|
IServerInterceptor next = theServer.getInterceptors().get(i);
|
||||||
boolean continueProcessing = next.outgoingResponse(theRequest, resp, theRequest.getServletRequest(), theRequest.getServletResponse());
|
boolean continueProcessing = next.outgoingResponse(theRequest, resp, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||||
if (!continueProcessing) {
|
if (!continueProcessing) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -8,7 +8,9 @@ public enum OtherOperationTypeEnum {
|
||||||
|
|
||||||
DELETE_TAGS("delete-tags"),
|
DELETE_TAGS("delete-tags"),
|
||||||
|
|
||||||
GET_TAGS("get-tags");
|
GET_TAGS("get-tags"),
|
||||||
|
|
||||||
|
GET_PAGE("get-page");
|
||||||
|
|
||||||
private String myCode;
|
private String myCode;
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ import ca.uhn.fhir.parser.IParser;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.method.ConformanceMethodBinding;
|
import ca.uhn.fhir.rest.method.ConformanceMethodBinding;
|
||||||
|
import ca.uhn.fhir.rest.method.OtherOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.method.Request;
|
import ca.uhn.fhir.rest.method.Request;
|
||||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||||
|
@ -420,7 +421,8 @@ public class RestfulServer extends HttpServlet {
|
||||||
|
|
||||||
Bundle bundle = createBundleFromBundleProvider(this, theResponse, resultList, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode, start, count, thePagingAction);
|
Bundle bundle = createBundleFromBundleProvider(this, theResponse, resultList, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode, start, count, thePagingAction);
|
||||||
|
|
||||||
for (IServerInterceptor next : getInterceptors()) {
|
for (int i = getInterceptors().size() - 1; i >= 0; i--) {
|
||||||
|
IServerInterceptor next = getInterceptors().get(i);
|
||||||
boolean continueProcessing = next.outgoingResponse(theRequest, bundle, theRequest.getServletRequest(), theRequest.getServletResponse());
|
boolean continueProcessing = next.outgoingResponse(theRequest, bundle, theRequest.getServletRequest(), theRequest.getServletResponse());
|
||||||
if (!continueProcessing) {
|
if (!continueProcessing) {
|
||||||
return;
|
return;
|
||||||
|
@ -433,7 +435,7 @@ public class RestfulServer extends HttpServlet {
|
||||||
|
|
||||||
protected void handleRequest(SearchMethodBinding.RequestType theRequestType, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
|
protected void handleRequest(SearchMethodBinding.RequestType theRequestType, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
|
||||||
for (IServerInterceptor next : myInterceptors) {
|
for (IServerInterceptor next : myInterceptors) {
|
||||||
boolean continueProcessing = next.incomingRequest(theRequest, theResponse);
|
boolean continueProcessing = next.incomingRequestPreProcessed(theRequest, theResponse);
|
||||||
if (!continueProcessing) {
|
if (!continueProcessing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -583,6 +585,7 @@ public class RestfulServer extends HttpServlet {
|
||||||
|
|
||||||
String pagingAction = theRequest.getParameter(Constants.PARAM_PAGINGACTION);
|
String pagingAction = theRequest.getParameter(Constants.PARAM_PAGINGACTION);
|
||||||
if (getPagingProvider() != null && isNotBlank(pagingAction)) {
|
if (getPagingProvider() != null && isNotBlank(pagingAction)) {
|
||||||
|
r.setOtherOperationType(OtherOperationTypeEnum.GET_PAGE);
|
||||||
handlePagingRequest(r, theResponse, pagingAction);
|
handlePagingRequest(r, theResponse, pagingAction);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -608,7 +611,7 @@ public class RestfulServer extends HttpServlet {
|
||||||
requestDetails.setOtherOperationType(resourceMethod.getOtherOperationType());
|
requestDetails.setOtherOperationType(resourceMethod.getOtherOperationType());
|
||||||
|
|
||||||
for (IServerInterceptor next : myInterceptors) {
|
for (IServerInterceptor next : myInterceptors) {
|
||||||
boolean continueProcessing = next.incomingRequest(requestDetails, theRequest, theResponse);
|
boolean continueProcessing = next.incomingRequestPostProcessed(requestDetails, theRequest, theResponse);
|
||||||
if (!continueProcessing) {
|
if (!continueProcessing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -781,6 +784,19 @@ public class RestfulServer extends HttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets (or clears) the list of interceptors
|
||||||
|
*
|
||||||
|
* @param theList
|
||||||
|
* The list of interceptors (may be null)
|
||||||
|
*/
|
||||||
|
public void setInterceptors(IServerInterceptor... theList) {
|
||||||
|
myInterceptors.clear();
|
||||||
|
if (theList != null) {
|
||||||
|
myInterceptors.addAll(Arrays.asList(theList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the paging provider to use, or <code>null</code> to use no paging (which is the default)
|
* Sets the paging provider to use, or <code>null</code> to use no paging (which is the default)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -26,12 +26,12 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.TagList;
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
import ca.uhn.fhir.rest.method.Request;
|
|
||||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides methods to intercept requests and responses
|
* Provides methods to intercept requests and responses. Note that implementations of this interface may wish
|
||||||
|
* to use {@link InterceptorAdapter} in order to not need to implement every method.
|
||||||
*/
|
*/
|
||||||
public interface IServerInterceptor {
|
public interface IServerInterceptor {
|
||||||
|
|
||||||
|
@ -46,16 +46,19 @@ public interface IServerInterceptor {
|
||||||
* The incoming request
|
* The incoming request
|
||||||
* @param theResponse
|
* @param theResponse
|
||||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||||
* interceptors will be called.
|
* interceptors will be called.
|
||||||
*/
|
*/
|
||||||
public boolean incomingRequest(HttpServletRequest theRequest, HttpServletResponse theResponse);
|
public boolean incomingRequestPreProcessed(HttpServletRequest theRequest, HttpServletResponse theResponse);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called just before the actual implementing server method is invoked
|
* This method is called just before the actual implementing server method is invoked.
|
||||||
|
* <p>
|
||||||
|
* Note about exceptions:
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theRequestDetails
|
* @param theRequestDetails
|
||||||
* A bean containing details about the request that is about to be processed, including
|
* A bean containing details about the request that is about to be processed, including
|
||||||
|
@ -63,16 +66,16 @@ public interface IServerInterceptor {
|
||||||
* The incoming request
|
* The incoming request
|
||||||
* @param theResponse
|
* @param theResponse
|
||||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||||
* interceptors will be called.
|
* interceptors will be called.
|
||||||
* @throws AuthenticationException
|
* @throws AuthenticationException
|
||||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||||
* attempt
|
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||||
*/
|
*/
|
||||||
public boolean incomingRequest(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException;
|
public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called after the server implementation method has been called, but before any attempt to stream
|
* This method is called after the server implementation method has been called, but before any attempt to stream
|
||||||
|
@ -86,14 +89,14 @@ public interface IServerInterceptor {
|
||||||
* The incoming request
|
* The incoming request
|
||||||
* @param theResponse
|
* @param theResponse
|
||||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||||
* interceptors will be called.
|
* interceptors will be called.
|
||||||
* @throws AuthenticationException
|
* @throws AuthenticationException
|
||||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||||
* attempt
|
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||||
*/
|
*/
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||||
|
|
||||||
|
@ -110,14 +113,14 @@ public interface IServerInterceptor {
|
||||||
* The incoming request
|
* The incoming request
|
||||||
* @param theResponse
|
* @param theResponse
|
||||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||||
* interceptors will be called.
|
* interceptors will be called.
|
||||||
* @throws AuthenticationException
|
* @throws AuthenticationException
|
||||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||||
* attempt
|
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||||
*/
|
*/
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||||
|
|
||||||
|
@ -133,14 +136,14 @@ public interface IServerInterceptor {
|
||||||
* The incoming request
|
* The incoming request
|
||||||
* @param theResponse
|
* @param theResponse
|
||||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||||
* interceptors will be called.
|
* interceptors will be called.
|
||||||
* @throws AuthenticationException
|
* @throws AuthenticationException
|
||||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||||
* attempt
|
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||||
*/
|
*/
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
public boolean outgoingResponse(RequestDetails theRequestDetails, IResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||||
|
|
||||||
|
@ -156,14 +159,14 @@ public interface IServerInterceptor {
|
||||||
* The incoming request
|
* The incoming request
|
||||||
* @param theResponse
|
* @param theResponse
|
||||||
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
* The response. Note that interceptors may choose to provide a response (i.e. by calling
|
||||||
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>true</code>
|
* {@link HttpServletResponse#getWriter()}) but in that case it is important to return <code>false</code>
|
||||||
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
* @return Return <code>true</code> if processing should continue normally. This is generally the right thing to do.
|
||||||
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
* If your interceptor is providing a response rather than letting HAPI handle the response normally, you
|
||||||
* must return <code>false</code>. In this case, no further processing will occur and no further
|
* must return <code>false</code>. In this case, no further processing will occur and no further
|
||||||
* interceptors will be called.
|
* interceptors will be called.
|
||||||
* @throws AuthenticationException
|
* @throws AuthenticationException
|
||||||
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
* This exception may be thrown to indicate that the interceptor has detected an unauthorized access
|
||||||
* attempt
|
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||||
*/
|
*/
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
public boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,12 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
public class InterceptorAdapter implements IServerInterceptor {
|
public class InterceptorAdapter implements IServerInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean incomingRequest(HttpServletRequest theRequest, HttpServletResponse theResponse) {
|
public boolean incomingRequestPreProcessed(HttpServletRequest theRequest, HttpServletResponse theResponse) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean incomingRequest(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,10 +55,10 @@ public class LoggingInterceptor extends InterceptorAdapter {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(LoggingInterceptor.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(LoggingInterceptor.class);
|
||||||
|
|
||||||
private Logger myLogger = ourLog;
|
private Logger myLogger = ourLog;
|
||||||
|
|
||||||
private String myMessageFormat = "${operationType} - ${idOrResourceName}";
|
private String myMessageFormat = "${operationType} - ${idOrResourceName}";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean incomingRequest(final RequestDetails theRequestDetails, final HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
public boolean incomingRequestPostProcessed(final RequestDetails theRequestDetails, final HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
||||||
|
|
||||||
// Perform any string substitutions from the message format
|
// Perform any string substitutions from the message format
|
||||||
StrLookup<?> lookup = new MyLookup(theRequest, theRequestDetails);
|
StrLookup<?> lookup = new MyLookup(theRequest, theRequestDetails);
|
||||||
|
|
|
@ -123,3 +123,11 @@ dfn {
|
||||||
a,a.externalLink,a:active,a:hover,a:link,a:visited {
|
a,a.externalLink,a:active,a:hover,a:link,a:visited {
|
||||||
color: #993300;
|
color: #993300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DIV.sidebar-nav UL LI UL LI {
|
||||||
|
/*
|
||||||
|
list-style: initial;
|
||||||
|
list-style-type: circle;
|
||||||
|
*/
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 7.6 KiB |
|
@ -64,11 +64,14 @@
|
||||||
<item name="Tags" href="./doc_tags.html" />
|
<item name="Tags" href="./doc_tags.html" />
|
||||||
<item name="Validation" href="./doc_validation.html" />
|
<item name="Validation" href="./doc_validation.html" />
|
||||||
</item>
|
</item>
|
||||||
<item name="RESTful Client" href="./doc_rest_client.html" />
|
<item name="RESTful Client" href="./doc_rest_client.html" >
|
||||||
|
<item name="Interceptors (client)" href="./doc_rest_client_interceptor.html"/>
|
||||||
|
</item>
|
||||||
<item name="RESTful Server" href="./doc_rest_server.html" >
|
<item name="RESTful Server" href="./doc_rest_server.html" >
|
||||||
<item name="RESTful Operations" href="./doc_rest_operations.html" />
|
<item name="RESTful Operations" href="./doc_rest_operations.html" />
|
||||||
<item name="Narrative Generator" href="./doc_narrative.html" />
|
<item name="Narrative Generator" href="./doc_narrative.html" />
|
||||||
<item name="CORS Support" href="./doc_cors.html" />
|
<item name="CORS Support" href="./doc_cors.html" />
|
||||||
|
<item name="Interceptors (server)" href="./doc_rest_server_interceptor.html" />
|
||||||
<item name="Web Testing UI" href="./doc_server_tester.html" />
|
<item name="Web Testing UI" href="./doc_server_tester.html" />
|
||||||
</item>
|
</item>
|
||||||
<item name="Logging" href="./doc_logging.html" />
|
<item name="Logging" href="./doc_logging.html" />
|
||||||
|
@ -90,7 +93,7 @@
|
||||||
<item name="Unit Test Report" href="surefire-report.html" />
|
<item name="Unit Test Report" href="surefire-report.html" />
|
||||||
<item name="FindBugs" href="findbugs.html" />
|
<item name="FindBugs" href="findbugs.html" />
|
||||||
<item name="License" href="license.html" />
|
<item name="License" href="license.html" />
|
||||||
<item name="Source Code" href="http://sourceforge.net/p/hl7api/fhircode/ci/master/tree/" />
|
<item name="Source Code" href="https://github.com/jamesagnew/hapi-fhir" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -371,7 +371,7 @@
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section name="Configuring the Client">
|
<section name="Configuring the HTTP Client">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
RESTful clients (both Generic and Annotation-Driven) use
|
RESTful clients (both Generic and Annotation-Driven) use
|
||||||
|
@ -393,66 +393,11 @@
|
||||||
class from the FhirContext.
|
class from the FhirContext.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<subsection name="Interceptors">
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Both generic clients and annotation-driven clients support
|
Note that individual requests and responses
|
||||||
<a href="./apidocs/ca/uhn/fhir/rest/client/IClientInterceptor.html">Client Interceptors</a>,
|
can be tweaked using <a href="./doc_rest_client_interceptor.html">interceptors</a>.
|
||||||
which may be registered in order to provide specific behaviour to each
|
|
||||||
client request.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
|
||||||
The following section shows some sample interceptors which may be used.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</subsection>
|
|
||||||
|
|
||||||
<subsection name="HTTP Basic Authorization">
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The following example shows how to configure your client to
|
|
||||||
use a specific username and password in every request.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<macro name="snippet">
|
|
||||||
<param name="id" value="security" />
|
|
||||||
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
</subsection>
|
|
||||||
|
|
||||||
<a name="req_resp_logging"/>
|
|
||||||
<subsection name="Logging Requests and Responses">
|
|
||||||
|
|
||||||
<p>
|
|
||||||
An interceptor is provided with HAPI FHIR which can be used to
|
|
||||||
log every transaction. The interceptor can be configured to be extremely
|
|
||||||
verbose (logging entire transactions including HTTP headers and payload bodies)
|
|
||||||
or simply to log request URLs.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<macro name="snippet">
|
|
||||||
<param name="id" value="logging" />
|
|
||||||
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
</subsection>
|
|
||||||
|
|
||||||
<subsection name="Configuring an HTTP Proxy">
|
|
||||||
|
|
||||||
<p>
|
|
||||||
An HTTP proxy may be configured directly on the
|
|
||||||
restful client factory, as shown below.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<macro name="snippet">
|
|
||||||
<param name="id" value="logging" />
|
|
||||||
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
</subsection>
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<title>RESTful Client - HAPI FHIR</title>
|
||||||
|
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<section name="Client Interceptors">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Both generic clients and annotation-driven clients support
|
||||||
|
<a href="./apidocs/ca/uhn/fhir/rest/client/IClientInterceptor.html">Client Interceptors</a>,
|
||||||
|
which may be registered in order to provide specific behaviour to each
|
||||||
|
client request.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The following section shows some sample interceptors which may be used.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<subsection name="HTTP Basic Authorization">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The following example shows how to configure your client to
|
||||||
|
use a specific username and password in every request.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="security" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
</subsection>
|
||||||
|
|
||||||
|
<a name="req_resp_logging"/>
|
||||||
|
<subsection name="Logging Requests and Responses">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
An interceptor is provided with HAPI FHIR which can be used to
|
||||||
|
log every transaction. The interceptor can be configured to be extremely
|
||||||
|
verbose (logging entire transactions including HTTP headers and payload bodies)
|
||||||
|
or simply to log request URLs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="logging" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
</subsection>
|
||||||
|
|
||||||
|
<subsection name="Configuring an HTTP Proxy">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
An HTTP proxy may be configured directly on the
|
||||||
|
restful client factory, as shown below.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<macro name="snippet">
|
||||||
|
<param name="id" value="logging" />
|
||||||
|
<param name="file" value="examples/src/main/java/example/ClientExamples.java" />
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
</subsection>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</document>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<title>Server Interceptors - HAPI FHIR</title>
|
||||||
|
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- The body of the document contains a number of sections -->
|
||||||
|
<section name="Server Interceptors">
|
||||||
|
|
||||||
|
<macro name="toc">
|
||||||
|
</macro>
|
||||||
|
|
||||||
|
<img src="svg/restful-server-interceptors.svg" alt="Interceptors" align="right"/>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The RESTful server provides a powerful mechanism for adding cross-cutting behaviour
|
||||||
|
to each incoming request that it processes. This mechanism consists of defining one or
|
||||||
|
more <b>interceptors</b> that will
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Interceptors must implement the
|
||||||
|
<a href="./apidocs/ca/uhn/fhir/rest/server/interceptor/IServerInterceptor.html">IServerInterceptor</a>
|
||||||
|
interface (or extend the convenience
|
||||||
|
<a href="./apidocs/ca/uhn/fhir/rest/server/interceptor/InterceptorAdapter.html">InterceptorAdapter</a>
|
||||||
|
class provided). The RESTful server will normally invoke the interceptor at three
|
||||||
|
points in the execution of the client request.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Before any processing at all is performed on the request,
|
||||||
|
<b>incomingRequestPreProcessed</b> will be invoked. This can be useful
|
||||||
|
if you wish to handle some requests completely outside of HAPI's processing
|
||||||
|
mechanism. If you are handling a request in your interceptor, you may
|
||||||
|
return <code>false</code> from your implementation method to signal to
|
||||||
|
HAPI that processing of the request should stop immediately.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Once the request is parsed (but before it is handled),
|
||||||
|
<b>incomingRequestPostProcessed</b> will be invoked. This method has
|
||||||
|
an additional parameter, the
|
||||||
|
<a href="./apidocs/ca/uhn/fhir/rest/method/RequestDetails.html">RequestDetails</a>
|
||||||
|
object which contains details about what operation is about to be
|
||||||
|
called, and what request parameters were receievd with that request.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
After the operation is handled (by invoking the corresponding ResourceProvider or PlainProvider method),
|
||||||
|
but before the actual response is returned to the client,
|
||||||
|
the <b>outgoingResponse</b> method is invoked.
|
||||||
|
This method also has details about the request in its parameters, but also
|
||||||
|
receives a copy of the response that is about to be returned. Note that
|
||||||
|
there are three implementations of <b>outgoingResponse</b>: The server
|
||||||
|
will invoke the one which corresponds to the response type
|
||||||
|
of the operation being invoked (resource, bundle, etc.)
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<br clear="all"/>
|
||||||
|
<subsection name="Registering Interceptors">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To register an interceptor to the server, simply call
|
||||||
|
either <code>registerInterceptor</code> or <code>setInterceptors</code>
|
||||||
|
on your RestfulServer instance.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note that order is important: The server will invoke
|
||||||
|
<code>incomingRequestPreProcessed</code> and <code>incomingRequestPostProcessed</code>
|
||||||
|
in the same order that they are registered to the server. The server will
|
||||||
|
invoke <code>outgoingResponse</code> in the <b>reverse</b> order to the
|
||||||
|
order in which the interceptors were registered. This means that interceptors
|
||||||
|
can be thought of as "wrapping" the request.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</subsection>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section name="Built In Interceptors">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
HAPI also provides built-in interceptors which may be useful.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<a name="Logging"/>
|
||||||
|
<subsection name="Logging Server Requests">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The
|
||||||
|
<a href="./apidocs/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptor.html">LoggingInterceptor</a>
|
||||||
|
can be used to generate a new log line (via SLF4j) for each incoming request. LoggingInterceptor
|
||||||
|
provides a flexible message format that can be used to provide a customized level
|
||||||
|
of detail about each incoming request.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</subsection>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</document>
|
|
@ -25,6 +25,7 @@ import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||||
|
@ -51,22 +52,32 @@ public class InterceptorTest {
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
private static RestfulServer servlet;
|
private static RestfulServer servlet;
|
||||||
private IServerInterceptor myInterceptor;
|
private IServerInterceptor myInterceptor1;
|
||||||
|
private IServerInterceptor myInterceptor2;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInterceptorFires() throws Exception {
|
public void testInterceptorFires() throws Exception {
|
||||||
when(myInterceptor.incomingRequest(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
when(myInterceptor1.incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
when(myInterceptor.incomingRequest(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
when(myInterceptor1.incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
when(myInterceptor.outgoingResponse(any(RequestDetails.class), any(IResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
when(myInterceptor1.outgoingResponse(any(RequestDetails.class), any(IResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(myInterceptor2.incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(myInterceptor2.incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
when(myInterceptor2.outgoingResponse(any(RequestDetails.class), any(IResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class))).thenReturn(true);
|
||||||
|
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
verify(myInterceptor, times(1)).incomingRequest(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
InOrder order = inOrder(myInterceptor1, myInterceptor2);
|
||||||
verify(myInterceptor, times(1)).incomingRequest(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
order.verify(myInterceptor1, times(1)).incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
verify(myInterceptor, times(1)).outgoingResponse(any(RequestDetails.class), any(IResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
order.verify(myInterceptor2, times(1)).incomingRequestPreProcessed(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
verifyNoMoreInteractions(myInterceptor);
|
order.verify(myInterceptor1, times(1)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
|
order.verify(myInterceptor2, times(1)).incomingRequestPostProcessed(any(RequestDetails.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
|
|
||||||
|
order.verify(myInterceptor2, times(1)).outgoingResponse(any(RequestDetails.class), any(IResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
|
order.verify(myInterceptor1, times(1)).outgoingResponse(any(RequestDetails.class), any(IResource.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
|
verifyNoMoreInteractions(myInterceptor1);
|
||||||
|
verifyNoMoreInteractions(myInterceptor2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,8 +88,9 @@ public class InterceptorTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
myInterceptor = mock(IServerInterceptor.class);
|
myInterceptor1 = mock(IServerInterceptor.class);
|
||||||
servlet.setInterceptors(Collections.singletonList(myInterceptor));
|
myInterceptor2 = mock(IServerInterceptor.class);
|
||||||
|
servlet.setInterceptors(myInterceptor1, myInterceptor2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@
|
||||||
if (this.id) {
|
if (this.id) {
|
||||||
if (this.id.substring(0,4) == 'inc_') {
|
if (this.id.substring(0,4) == 'inc_') {
|
||||||
this.name = '_include';
|
this.name = '_include';
|
||||||
} else {
|
} else if (this.id.indexOf('autogen') == -1) {
|
||||||
this.name = this.id;
|
this.name = this.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<meta name="description" content="" />
|
<meta name="description" content="" />
|
||||||
<meta name="author" content="" />
|
<meta name="author" content="" />
|
||||||
<script src="js/jquery-2.1.0.min.js"></script>
|
<script src="js/jquery-2.1.0.min.js"></script>
|
||||||
|
<!-- <script src="js/jquery-2.1.1.js"></script>-->
|
||||||
<script src="js/bootstrap.min.js"></script>
|
<script src="js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
|
@ -32,7 +32,7 @@ function generateHapiSearch(json, container) {
|
||||||
var paramLine = null;
|
var paramLine = null;
|
||||||
if (nextParam.type == 'string') {
|
if (nextParam.type == 'string') {
|
||||||
paramLine = '.where(new StringClientParam("' + nextParam.name + '")';
|
paramLine = '.where(new StringClientParam("' + nextParam.name + '")';
|
||||||
paramLine += nextParam.qualifier = ':exact' ? '.matchesExactly()' : '.matches()';
|
paramLine += nextParam.qualifier == ':exact' ? '.matchesExactly()' : '.matches()';
|
||||||
paramLine += '.value("' + nextParam.value + '"))';
|
paramLine += '.value("' + nextParam.value + '"))';
|
||||||
} else if (nextParam.type == 'id') {
|
} else if (nextParam.type == 'id') {
|
||||||
paramLine = '.where(new StringClientParam("' + nextParam.name + '")';
|
paramLine = '.where(new StringClientParam("' + nextParam.name + '")';
|
||||||
|
|
|
@ -98,12 +98,12 @@ function addSearchControls(theConformance, theSearchParamType, theSearchParamNam
|
||||||
var qualifierDropdown = $('<ul />', {'class':'dropdown-menu', role:'menu'});
|
var qualifierDropdown = $('<ul />', {'class':'dropdown-menu', role:'menu'});
|
||||||
for (var i = 0; i < qualifiers.length; i++) {
|
for (var i = 0; i < qualifiers.length; i++) {
|
||||||
var nextLink = $('<a>' + qualifiers[i].name+'</a>');
|
var nextLink = $('<a>' + qualifiers[i].name+'</a>');
|
||||||
var theSearchParamName = qualifiers[i].name;
|
var qualName = qualifiers[i].name;
|
||||||
var nextValue = qualifiers[i].value;
|
var nextValue = qualifiers[i].value;
|
||||||
qualifierDropdown.append($('<li />').append(nextLink));
|
qualifierDropdown.append($('<li />').append(nextLink));
|
||||||
nextLink.click(function(){
|
nextLink.click(function(){
|
||||||
qualifierInput.val(nextValue);
|
qualifierInput.val(nextValue);
|
||||||
matchesLabel.text(theSearchParamName);
|
matchesLabel.text(qualName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue