Add request ID
This commit is contained in:
parent
1faf7785c4
commit
56aaef641c
|
@ -50,7 +50,7 @@ public class ConsentInterceptors {
|
||||||
* Modify resources that are being shown to the user
|
* Modify resources that are being shown to the user
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ConsentOutcome seeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
public ConsentOutcome willSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
// Don't return the subject for Observation resources
|
// Don't return the subject for Observation resources
|
||||||
if (theResource instanceof Observation) {
|
if (theResource instanceof Observation) {
|
||||||
Observation obs = (Observation)theResource;
|
Observation obs = (Observation)theResource;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.*;
|
||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
|
|
||||||
|
public static final String HEADER_REQUEST_ID = "X-Request-ID";
|
||||||
public static final String CACHE_CONTROL_MAX_RESULTS = "max-results";
|
public static final String CACHE_CONTROL_MAX_RESULTS = "max-results";
|
||||||
public static final String CACHE_CONTROL_NO_CACHE = "no-cache";
|
public static final String CACHE_CONTROL_NO_CACHE = "no-cache";
|
||||||
public static final String CACHE_CONTROL_NO_STORE = "no-store";
|
public static final String CACHE_CONTROL_NO_STORE = "no-store";
|
||||||
|
|
|
@ -469,7 +469,7 @@ public class ConsentInterceptorResourceProviderR4Test extends BaseResourceProvid
|
||||||
}
|
}
|
||||||
return ConsentOutcome.PROCEED;
|
return ConsentOutcome.PROCEED;
|
||||||
});
|
});
|
||||||
when(svc.seeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(svc.willSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
|
|
||||||
consentService.setTarget(svc);
|
consentService.setTarget(svc);
|
||||||
String query = "{ name { family, given }, managingOrganization { reference, resource {name} } }";
|
String query = "{ name { family, given }, managingOrganization { reference, resource {name} } }";
|
||||||
|
@ -502,7 +502,7 @@ public class ConsentInterceptorResourceProviderR4Test extends BaseResourceProvid
|
||||||
IConsentService svc = mock(IConsentService.class);
|
IConsentService svc = mock(IConsentService.class);
|
||||||
when(svc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(svc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(svc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(svc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(svc.seeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t -> {
|
when(svc.willSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t -> {
|
||||||
IBaseResource resource = t.getArgument(1, IBaseResource.class);
|
IBaseResource resource = t.getArgument(1, IBaseResource.class);
|
||||||
if (resource instanceof Organization) {
|
if (resource instanceof Organization) {
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
|
@ -598,7 +598,7 @@ public class ConsentInterceptorResourceProviderR4Test extends BaseResourceProvid
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConsentOutcome seeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
public ConsentOutcome willSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
mySeeCount++;
|
mySeeCount++;
|
||||||
String resourceId = theResource.getIdElement().toUnqualifiedVersionless().getValue();
|
String resourceId = theResource.getIdElement().toUnqualifiedVersionless().getValue();
|
||||||
ourLog.info("** SEE: {}", resourceId);
|
ourLog.info("** SEE: {}", resourceId);
|
||||||
|
@ -640,7 +640,7 @@ public class ConsentInterceptorResourceProviderR4Test extends BaseResourceProvid
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConsentOutcome seeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
public ConsentOutcome willSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
return ConsentOutcome.PROCEED;
|
return ConsentOutcome.PROCEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,7 +674,7 @@ public class ConsentInterceptorResourceProviderR4Test extends BaseResourceProvid
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConsentOutcome seeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
public ConsentOutcome willSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
return ConsentOutcome.PROCEED;
|
return ConsentOutcome.PROCEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +710,7 @@ public class ConsentInterceptorResourceProviderR4Test extends BaseResourceProvid
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConsentOutcome seeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
public ConsentOutcome willSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
return ConsentOutcome.PROCEED;
|
return ConsentOutcome.PROCEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,7 +740,7 @@ public class ConsentInterceptorResourceProviderR4Test extends BaseResourceProvid
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConsentOutcome seeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
public ConsentOutcome willSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
return ConsentOutcome.PROCEED;
|
return ConsentOutcome.PROCEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ package ca.uhn.fhir.rest.api.server;
|
||||||
*/
|
*/
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hl7.fhir.instance.model.api.*;
|
import org.hl7.fhir.instance.model.api.*;
|
||||||
|
@ -48,6 +50,8 @@ public interface IRestfulResponse {
|
||||||
|
|
||||||
void setOperationResourceLastUpdated(IPrimitiveType<Date> theOperationResourceLastUpdated);
|
void setOperationResourceLastUpdated(IPrimitiveType<Date> theOperationResourceLastUpdated);
|
||||||
|
|
||||||
|
Map<String, List<String>> getHeaders();
|
||||||
|
|
||||||
void setOperationResourceId(IIdType theOperationResourceId);
|
void setOperationResourceId(IIdType theOperationResourceId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@ public abstract class RequestDetails {
|
||||||
private Map<String, List<String>> myUnqualifiedToQualifiedNames;
|
private Map<String, List<String>> myUnqualifiedToQualifiedNames;
|
||||||
private Map<Object, Object> myUserData;
|
private Map<Object, Object> myUserData;
|
||||||
private IBaseResource myResource;
|
private IBaseResource myResource;
|
||||||
|
private String myRequestId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -80,6 +81,14 @@ public abstract class RequestDetails {
|
||||||
myInterceptorBroadcaster = theInterceptorBroadcaster;
|
myInterceptorBroadcaster = theInterceptorBroadcaster;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRequestId() {
|
||||||
|
return myRequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequestId(String theRequestId) {
|
||||||
|
myRequestId = theRequestId;
|
||||||
|
}
|
||||||
|
|
||||||
public StopWatch getRequestStopwatch() {
|
public StopWatch getRequestStopwatch() {
|
||||||
return myRequestStopwatch;
|
return myRequestStopwatch;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ public abstract class RestfulResponse<T extends RequestDetails> implements IRest
|
||||||
* Get the http headers
|
* Get the http headers
|
||||||
* @return the headers
|
* @return the headers
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Map<String, List<String>> getHeaders() {
|
public Map<String, List<String>> getHeaders() {
|
||||||
return theHeaders;
|
return theHeaders;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,8 +77,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.jar.Manifest;
|
import java.util.jar.Manifest;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.*;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public class RestfulServer extends HttpServlet implements IRestfulServer<ServletRequestDetails> {
|
public class RestfulServer extends HttpServlet implements IRestfulServer<ServletRequestDetails> {
|
||||||
|
@ -105,6 +104,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
private static final ExceptionHandlingInterceptor DEFAULT_EXCEPTION_HANDLER = new ExceptionHandlingInterceptor();
|
private static final ExceptionHandlingInterceptor DEFAULT_EXCEPTION_HANDLER = new ExceptionHandlingInterceptor();
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(RestfulServer.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(RestfulServer.class);
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Random RANDOM = new Random();
|
||||||
private final List<Object> myPlainProviders = new ArrayList<>();
|
private final List<Object> myPlainProviders = new ArrayList<>();
|
||||||
private final List<IResourceProvider> myResourceProviders = new ArrayList<>();
|
private final List<IResourceProvider> myResourceProviders = new ArrayList<>();
|
||||||
private IInterceptorService myInterceptorService;
|
private IInterceptorService myInterceptorService;
|
||||||
|
@ -171,6 +171,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
if (isNotBlank(poweredByHeader)) {
|
if (isNotBlank(poweredByHeader)) {
|
||||||
theHttpResponse.addHeader(Constants.POWERED_BY_HEADER, poweredByHeader);
|
theHttpResponse.addHeader(Constants.POWERED_BY_HEADER, poweredByHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addLocationHeader(RequestDetails theRequest, HttpServletResponse theResponse, MethodOutcome response, String headerLocation, String resourceName) {
|
private void addLocationHeader(RequestDetails theRequest, HttpServletResponse theResponse, MethodOutcome response, String headerLocation, String resourceName) {
|
||||||
|
@ -561,6 +563,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all registered server interceptors
|
* Returns a list of all registered server interceptors
|
||||||
|
*
|
||||||
* @deprecated As of HAPI FHIR 3.8.0, use {@link #getInterceptorService()} to access the interceptor service. You can register and unregister interceptors using this service.
|
* @deprecated As of HAPI FHIR 3.8.0, use {@link #getInterceptorService()} to access the interceptor service. You can register and unregister interceptors using this service.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -577,6 +580,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the interceptor registry for this service. Use this registry to register and unregister
|
* Returns the interceptor registry for this service. Use this registry to register and unregister
|
||||||
|
*
|
||||||
* @since 3.8.0
|
* @since 3.8.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -850,6 +854,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
requestDetails.setServletRequest(theRequest);
|
requestDetails.setServletRequest(theRequest);
|
||||||
requestDetails.setServletResponse(theResponse);
|
requestDetails.setServletResponse(theResponse);
|
||||||
|
|
||||||
|
String requestId = getOrCreateRequestId(theRequest);
|
||||||
|
requestDetails.setRequestId(requestId);
|
||||||
|
addRequestIdToResponse(requestDetails, requestId);
|
||||||
|
|
||||||
theRequest.setAttribute(SERVLET_CONTEXT_ATTRIBUTE, getServletContext());
|
theRequest.setAttribute(SERVLET_CONTEXT_ATTRIBUTE, getServletContext());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -1066,6 +1074,40 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void addRequestIdToResponse(ServletRequestDetails theRequestDetails, String theRequestId) {
|
||||||
|
theRequestDetails.getResponse().addHeader(Constants.HEADER_REQUEST_ID, theRequestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a requet ID from the request headers via the {@link Constants#HEADER_REQUEST_ID}
|
||||||
|
* header, or generates one if none is supplied.
|
||||||
|
* <p>
|
||||||
|
* Note that the generated request ID is a random 64-bit long integer encoded as
|
||||||
|
* hexadecimal. It is not generated using any cryptographic algorithms or a secure
|
||||||
|
* PRNG, so it should not be used for anything other than troubleshooting purposes.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
protected String getOrCreateRequestId(HttpServletRequest theRequest) {
|
||||||
|
String requestId = theRequest.getHeader(Constants.HEADER_REQUEST_ID);
|
||||||
|
if (isNotBlank(requestId)) {
|
||||||
|
for (char nextChar : requestId.toCharArray()) {
|
||||||
|
if (!Character.isLetterOrDigit(nextChar)) {
|
||||||
|
if (nextChar != '.' && nextChar != '-' && nextChar != '_' && nextChar != ' ') {
|
||||||
|
requestId = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBlank(requestId)) {
|
||||||
|
requestId = Long.toHexString(RANDOM.nextLong());
|
||||||
|
requestId = leftPad(requestId, 16, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestId;
|
||||||
|
}
|
||||||
|
|
||||||
protected void validateRequest(ServletRequestDetails theRequestDetails) {
|
protected void validateRequest(ServletRequestDetails theRequestDetails) {
|
||||||
String[] elements = theRequestDetails.getParameters().get(Constants.PARAM_ELEMENTS);
|
String[] elements = theRequestDetails.getParameters().get(Constants.PARAM_ELEMENTS);
|
||||||
if (elements != null) {
|
if (elements != null) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ca.uhn.fhir.parser.IParser;
|
||||||
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;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.server.IRestfulResponse;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.ResponseDetails;
|
import ca.uhn.fhir.rest.api.server.ResponseDetails;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
@ -31,10 +32,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.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Date;
|
import java.util.*;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.*;
|
import static org.apache.commons.lang3.StringUtils.*;
|
||||||
|
|
||||||
|
@ -402,10 +400,7 @@ public class ResponseHighlighterInterceptor {
|
||||||
Enumeration<String> headerValuesEnum = sr.getHeaders(nextHeaderName);
|
Enumeration<String> headerValuesEnum = sr.getHeaders(nextHeaderName);
|
||||||
while (headerValuesEnum.hasMoreElements()) {
|
while (headerValuesEnum.hasMoreElements()) {
|
||||||
String nextHeaderValue = headerValuesEnum.nextElement();
|
String nextHeaderValue = headerValuesEnum.nextElement();
|
||||||
b.append("<div class=\"headersRow\">");
|
appendHeader(b, nextHeaderName, nextHeaderValue);
|
||||||
b.append("<span class=\"headerName\">").append(nextHeaderName).append(": ").append("</span>");
|
|
||||||
b.append("<span class=\"headerValue\">").append(nextHeaderValue).append("</span>");
|
|
||||||
b.append("</div>");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.append("</div>");
|
b.append("</div>");
|
||||||
|
@ -701,14 +696,26 @@ public class ResponseHighlighterInterceptor {
|
||||||
nextHeaderValue = responseEncoding.getResourceContentType() + ";charset=utf-8";
|
nextHeaderValue = responseEncoding.getResourceContentType() + ";charset=utf-8";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.append("<div class=\"headersRow\">");
|
appendHeader(b, nextHeaderName, nextHeaderValue);
|
||||||
b.append("<span class=\"headerName\">").append(nextHeaderName).append(": ").append("</span>");
|
|
||||||
b.append("<span class=\"headerValue\">").append(nextHeaderValue).append("</span>");
|
|
||||||
b.append("</div>");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
IRestfulResponse response = theRequestDetails.getResponse();
|
||||||
|
for (Map.Entry<String, List<String>> next : response.getHeaders().entrySet()) {
|
||||||
|
String name = next.getKey();
|
||||||
|
for (String nextValue : next.getValue()) {
|
||||||
|
appendHeader(b, name, nextValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
b.append("</div>");
|
b.append("</div>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void appendHeader(StringBuilder theBuilder, String theHeaderName, String theHeaderValue) {
|
||||||
|
theBuilder.append("<div class=\"headersRow\">");
|
||||||
|
theBuilder.append("<span class=\"headerName\">").append(theHeaderName).append(": ").append("</span>");
|
||||||
|
theBuilder.append("<span class=\"headerValue\">").append(theHeaderValue).append("</span>");
|
||||||
|
theBuilder.append("</div>");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ public class ConsentInterceptor {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsentOutcome nextOutcome = myConsentService.seeResource(theRequestDetails, nextResource, myContextConsentServices);
|
ConsentOutcome nextOutcome = myConsentService.willSeeResource(theRequestDetails, nextResource, myContextConsentServices);
|
||||||
switch (nextOutcome.getStatus()) {
|
switch (nextOutcome.getStatus()) {
|
||||||
case PROCEED:
|
case PROCEED:
|
||||||
if (nextOutcome.getResource() != null) {
|
if (nextOutcome.getResource() != null) {
|
||||||
|
@ -203,7 +203,7 @@ public class ConsentInterceptor {
|
||||||
|
|
||||||
// See outer resource
|
// See outer resource
|
||||||
if (alreadySeenResources.putIfAbsent(theResource.getResponseResource(), Boolean.TRUE) == null) {
|
if (alreadySeenResources.putIfAbsent(theResource.getResponseResource(), Boolean.TRUE) == null) {
|
||||||
final ConsentOutcome outcome = myConsentService.seeResource(theRequestDetails, theResource.getResponseResource(), myContextConsentServices);
|
final ConsentOutcome outcome = myConsentService.willSeeResource(theRequestDetails, theResource.getResponseResource(), myContextConsentServices);
|
||||||
if (outcome.getResource() != null) {
|
if (outcome.getResource() != null) {
|
||||||
theResource.setResponseResource(outcome.getResource());
|
theResource.setResponseResource(outcome.getResource());
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ public class ConsentInterceptor {
|
||||||
if (alreadySeenResources.putIfAbsent((IBaseResource) theElement, Boolean.TRUE) != null) {
|
if (alreadySeenResources.putIfAbsent((IBaseResource) theElement, Boolean.TRUE) != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ConsentOutcome childOutcome = myConsentService.seeResource(theRequestDetails, (IBaseResource) theElement, myContextConsentServices);
|
ConsentOutcome childOutcome = myConsentService.willSeeResource(theRequestDetails, (IBaseResource) theElement, myContextConsentServices);
|
||||||
|
|
||||||
IBaseResource replacementResource = null;
|
IBaseResource replacementResource = null;
|
||||||
boolean shouldReplaceResource = false;
|
boolean shouldReplaceResource = false;
|
||||||
|
|
|
@ -44,8 +44,8 @@ public class DelegatingConsentService implements IConsentService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConsentOutcome seeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
public ConsentOutcome willSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
return myTarget.seeResource(theRequestDetails, theResource ,theContextServices);
|
return myTarget.willSeeResource(theRequestDetails, theResource ,theContextServices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -51,7 +51,7 @@ public interface IConsentService {
|
||||||
* <p>
|
* <p>
|
||||||
* Implementations should make no attempt to modify the returned result within
|
* Implementations should make no attempt to modify the returned result within
|
||||||
* this method. For modification use cases (e.g. masking for consent rules) the
|
* this method. For modification use cases (e.g. masking for consent rules) the
|
||||||
* user should use the {@link #seeResource(RequestDetails, IBaseResource, IConsentContextServices)}
|
* user should use the {@link #willSeeResource(RequestDetails, IBaseResource, IConsentContextServices)}
|
||||||
* method to actually make changes. This method is intended to only
|
* method to actually make changes. This method is intended to only
|
||||||
* to make decisions.
|
* to make decisions.
|
||||||
* </p>
|
* </p>
|
||||||
|
@ -76,7 +76,7 @@ public interface IConsentService {
|
||||||
ConsentOutcome canSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices);
|
ConsentOutcome canSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called if a user may potentially see a resource, either completely
|
* This method is called if a user is about to see a resource, either completely
|
||||||
* or partially. In other words, if the user is going to see any part of this resource
|
* or partially. In other words, if the user is going to see any part of this resource
|
||||||
* via READ operations, SEARCH operations, etc., this method is
|
* via READ operations, SEARCH operations, etc., this method is
|
||||||
* called. This method may modify the resource in order to filter/mask aspects of
|
* called. This method may modify the resource in order to filter/mask aspects of
|
||||||
|
@ -92,7 +92,7 @@ public interface IConsentService {
|
||||||
* </p>
|
* </p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link ConsentOperationStatusEnum#AUTHORIZED}: The resource will be returned to the client.</li>
|
* <li>{@link ConsentOperationStatusEnum#AUTHORIZED}: The resource will be returned to the client.</li>
|
||||||
* <li>{@link ConsentOperationStatusEnum#PROCEED}: The resource will be returned to the client. Any embedded resources contained within the resource will also be checked by {@link #seeResource(RequestDetails, IBaseResource, IConsentContextServices)}.</li>
|
* <li>{@link ConsentOperationStatusEnum#PROCEED}: The resource will be returned to the client. Any embedded resources contained within the resource will also be checked by {@link #willSeeResource(RequestDetails, IBaseResource, IConsentContextServices)}.</li>
|
||||||
* <li>{@link ConsentOperationStatusEnum#REJECT}: The resource will not be returned to the client. If the resource supplied to the </li>
|
* <li>{@link ConsentOperationStatusEnum#REJECT}: The resource will not be returned to the client. If the resource supplied to the </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
@ -108,7 +108,7 @@ public interface IConsentService {
|
||||||
* consent directives.
|
* consent directives.
|
||||||
* @return An outcome object. See method documentation for a description.
|
* @return An outcome object. See method documentation for a description.
|
||||||
*/
|
*/
|
||||||
ConsentOutcome seeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices);
|
ConsentOutcome willSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called when an operation is complete. It can be used to perform
|
* This method is called when an operation is complete. It can be used to perform
|
||||||
|
|
|
@ -40,6 +40,9 @@ import ca.uhn.fhir.rest.server.RestfulResponse;
|
||||||
|
|
||||||
public class ServletRestfulResponse extends RestfulResponse<ServletRequestDetails> {
|
public class ServletRestfulResponse extends RestfulResponse<ServletRequestDetails> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
public ServletRestfulResponse(ServletRequestDetails servletRequestDetails) {
|
public ServletRestfulResponse(ServletRequestDetails servletRequestDetails) {
|
||||||
super(servletRequestDetails);
|
super(servletRequestDetails);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ 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.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.*;
|
import org.hl7.fhir.r4.model.*;
|
||||||
import org.hl7.fhir.r4.utils.IResourceValidator;
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
@ -45,8 +44,7 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.hamcrest.Matchers.not;
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||||
|
@ -364,6 +362,38 @@ public class SearchR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestIdGeneratedAndReturned() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=foo%7Cbar&_pretty=true");
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
String requestId = status.getFirstHeader(Constants.HEADER_REQUEST_ID).getValue();
|
||||||
|
assertThat(requestId, matchesPattern("[a-z0-9]{16}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestIdSuppliedAndReturned() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=foo%7Cbar&_pretty=true");
|
||||||
|
httpGet.addHeader(Constants.HEADER_REQUEST_ID, "help im a bug");
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
String requestId = status.getFirstHeader(Constants.HEADER_REQUEST_ID).getValue();
|
||||||
|
assertThat(requestId, matchesPattern("help im a bug"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestIdSuppliedAndReturned_Invalid() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=foo%7Cbar&_pretty=true");
|
||||||
|
httpGet.addHeader(Constants.HEADER_REQUEST_ID, "help i'm a bug");
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
String requestId = status.getFirstHeader(Constants.HEADER_REQUEST_ID).getValue();
|
||||||
|
assertThat(requestId, matchesPattern("[a-z0-9]{16}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithInvalidChain() throws Exception {
|
public void testSearchWithInvalidChain() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier.chain=foo%7Cbar");
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier.chain=foo%7Cbar");
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.seeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.willSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
|
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.seeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.willSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
|
|
||||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_total=accurate");
|
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_total=accurate");
|
||||||
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
@ -159,7 +159,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.canSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t-> ConsentOutcome.PROCEED);
|
when(myConsentSvc.canSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t-> ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.seeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t-> ConsentOutcome.AUTHORIZED);
|
when(myConsentSvc.willSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t-> ConsentOutcome.AUTHORIZED);
|
||||||
|
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
||||||
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(3)).seeResource(any(), any(), any());
|
verify(myConsentSvc, times(3)).willSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
||||||
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
||||||
verifyNoMoreInteractions(myConsentSvc);
|
verifyNoMoreInteractions(myConsentSvc);
|
||||||
|
@ -186,7 +186,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.seeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t->{
|
when(myConsentSvc.willSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t->{
|
||||||
OperationOutcome oo = new OperationOutcome();
|
OperationOutcome oo = new OperationOutcome();
|
||||||
oo.addIssue().setDiagnostics("A DIAG");
|
oo.addIssue().setDiagnostics("A DIAG");
|
||||||
return new ConsentOutcome(ConsentOperationStatusEnum.REJECT, oo);
|
return new ConsentOutcome(ConsentOperationStatusEnum.REJECT, oo);
|
||||||
|
@ -203,7 +203,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
||||||
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(3)).seeResource(any(), any(), any());
|
verify(myConsentSvc, times(3)).willSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
||||||
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
||||||
verifyNoMoreInteractions(myConsentSvc);
|
verifyNoMoreInteractions(myConsentSvc);
|
||||||
|
@ -216,7 +216,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.canSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t-> ConsentOutcome.PROCEED);
|
when(myConsentSvc.canSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t-> ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.seeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t-> {
|
when(myConsentSvc.willSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t-> {
|
||||||
return ConsentOutcome.REJECT;
|
return ConsentOutcome.REJECT;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
||||||
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(3)).seeResource(any(), any(), any()); // the two patients + the bundle
|
verify(myConsentSvc, times(3)).willSeeResource(any(), any(), any()); // the two patients + the bundle
|
||||||
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
||||||
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
||||||
verifyNoMoreInteractions(myConsentSvc);
|
verifyNoMoreInteractions(myConsentSvc);
|
||||||
|
@ -243,7 +243,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.seeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t->{
|
when(myConsentSvc.willSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t->{
|
||||||
IBaseResource resource = (IBaseResource) t.getArguments()[1];
|
IBaseResource resource = (IBaseResource) t.getArguments()[1];
|
||||||
if ("PTA".equals(resource.getIdElement().getIdPart())) {
|
if ("PTA".equals(resource.getIdElement().getIdPart())) {
|
||||||
OperationOutcome oo = new OperationOutcome();
|
OperationOutcome oo = new OperationOutcome();
|
||||||
|
@ -268,7 +268,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
||||||
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(3)).seeResource(any(), any(), any());
|
verify(myConsentSvc, times(3)).willSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
||||||
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
||||||
verifyNoMoreInteractions(myConsentSvc);
|
verifyNoMoreInteractions(myConsentSvc);
|
||||||
|
@ -281,7 +281,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.seeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t->{
|
when(myConsentSvc.willSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t->{
|
||||||
IBaseResource resource = (IBaseResource) t.getArguments()[1];
|
IBaseResource resource = (IBaseResource) t.getArguments()[1];
|
||||||
if (resource.getIdElement().getIdPart().equals("PTA")) {
|
if (resource.getIdElement().getIdPart().equals("PTA")) {
|
||||||
Patient replacement = new Patient();
|
Patient replacement = new Patient();
|
||||||
|
@ -308,7 +308,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
||||||
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(4)).seeResource(any(), any(), any());
|
verify(myConsentSvc, times(4)).willSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
||||||
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
||||||
verifyNoMoreInteractions(myConsentSvc);
|
verifyNoMoreInteractions(myConsentSvc);
|
||||||
|
@ -321,7 +321,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||||
when(myConsentSvc.seeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t->{
|
when(myConsentSvc.willSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t->{
|
||||||
IBaseResource resource = (IBaseResource) t.getArguments()[1];
|
IBaseResource resource = (IBaseResource) t.getArguments()[1];
|
||||||
if (resource.getIdElement().getIdPart().equals("PTA")) {
|
if (resource.getIdElement().getIdPart().equals("PTA")) {
|
||||||
((Patient)resource).addIdentifier().setSystem("REPLACEMENT");
|
((Patient)resource).addIdentifier().setSystem("REPLACEMENT");
|
||||||
|
@ -345,7 +345,7 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
||||||
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(3)).seeResource(any(), any(), any());
|
verify(myConsentSvc, times(3)).willSeeResource(any(), any(), any());
|
||||||
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
||||||
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
||||||
verifyNoMoreInteractions(myConsentSvc);
|
verifyNoMoreInteractions(myConsentSvc);
|
||||||
|
|
|
@ -258,13 +258,15 @@ public class ResponseHighlightingInterceptorTest {
|
||||||
CloseableHttpResponse status = ourClient.execute(httpGet);
|
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
status.close();
|
status.close();
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
||||||
assertThat(responseContent, containsString("html"));
|
assertThat(responseContent, containsString("html"));
|
||||||
assertThat(responseContent, containsString(">{<"));
|
assertThat(responseContent, containsString(">{<"));
|
||||||
assertThat(responseContent, not(containsString("<")));
|
assertThat(responseContent, not(containsString("<")));
|
||||||
|
assertThat(responseContent, containsString(Constants.HEADER_REQUEST_ID));
|
||||||
|
|
||||||
ourLog.info(responseContent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -215,6 +215,11 @@
|
||||||
in the processing lifecycle if there is no chance they will be permitted
|
in the processing lifecycle if there is no chance they will be permitted
|
||||||
later (i.e. because the type is not authorized at all)
|
later (i.e. because the type is not authorized at all)
|
||||||
</action>
|
</action>
|
||||||
|
<action type="add">
|
||||||
|
The HAPI FHIR server will now generate a random transaction ID to every
|
||||||
|
request and add it to the response headers. Clients may supply the transaction
|
||||||
|
header via the <![CDATA[<code>X-Request-ID</code>]]> header.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="3.8.0" date="2019-05-30" description="Hippo">
|
<release version="3.8.0" date="2019-05-30" description="Hippo">
|
||||||
<action type="fix">
|
<action type="fix">
|
||||||
|
|
Loading…
Reference in New Issue