mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-03-09 14:33:32 +00:00
Add interceptor method on server which will be called after all other
processing
This commit is contained in:
parent
fec032464a
commit
ae97165a0a
@ -29,15 +29,8 @@ import java.lang.annotation.Annotation;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.jar.Manifest;
|
import java.util.jar.Manifest;
|
||||||
@ -78,14 +71,16 @@ import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
|||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.CoverageIgnore;
|
import ca.uhn.fhir.util.*;
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
|
||||||
import ca.uhn.fhir.util.UrlPathTokenizer;
|
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
|
||||||
import ca.uhn.fhir.util.VersionUtil;
|
|
||||||
|
|
||||||
public class RestfulServer extends HttpServlet implements IRestfulServer<ServletRequestDetails> {
|
public class RestfulServer extends HttpServlet implements IRestfulServer<ServletRequestDetails> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All incoming requests will have an attribute added to {@link HttpServletRequest#getAttribute(String)}
|
||||||
|
* with this key. The value will be a Java {@link Date} with the time that request processing began.
|
||||||
|
*/
|
||||||
|
public static final String REQUEST_START_TIME = RestfulServer.class.getName() + "REQUEST_START_TIME";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default setting for {@link #setETagSupport(ETagSupportEnum) ETag Support}: {@link ETagSupportEnum#ENABLED}
|
* Default setting for {@link #setETagSupport(ETagSupportEnum) ETag Support}: {@link ETagSupportEnum#ENABLED}
|
||||||
*/
|
*/
|
||||||
@ -658,6 +653,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||||||
*/
|
*/
|
||||||
resourceMethod.invokeServer(this, requestDetails);
|
resourceMethod.invokeServer(this, requestDetails);
|
||||||
|
|
||||||
|
for (IServerInterceptor next : myInterceptors) {
|
||||||
|
next.processingCompletedNormally(requestDetails);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (NotModifiedException e) {
|
} catch (NotModifiedException e) {
|
||||||
|
|
||||||
for (int i = getInterceptors().size() - 1; i >= 0; i--) {
|
for (int i = getInterceptors().size() - 1; i >= 0; i--) {
|
||||||
@ -1163,6 +1162,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void service(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
|
protected void service(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
|
||||||
|
theReq.setAttribute(REQUEST_START_TIME, new Date());
|
||||||
|
|
||||||
RequestTypeEnum method;
|
RequestTypeEnum method;
|
||||||
try {
|
try {
|
||||||
method = RequestTypeEnum.valueOf(theReq.getMethod());
|
method = RequestTypeEnum.valueOf(theReq.getMethod());
|
||||||
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.server.interceptor;
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -41,8 +41,10 @@ import ca.uhn.fhir.rest.annotation.Search;
|
|||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
|
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides methods to intercept requests and responses. Note that implementations of this interface may wish to use
|
* Provides methods to intercept requests and responses. Note that implementations of this interface may wish to use
|
||||||
@ -88,7 +90,8 @@ public interface IServerInterceptor {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
* If this exception is thrown, it will be re-thrown up to the container for handling.
|
* If this exception is thrown, it will be re-thrown up to the container for handling.
|
||||||
*/
|
*/
|
||||||
boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws ServletException, IOException;
|
boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||||
|
throws ServletException, IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@ -118,10 +121,10 @@ public interface IServerInterceptor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked before an incoming request is processed. Note that this method is called
|
* Invoked before an incoming request is processed. Note that this method is called
|
||||||
* after the server has begin preparing the response to the incoming client request.
|
* after the server has begin preparing the response to the incoming client request.
|
||||||
* As such, it is not able to supply a response to the incoming request in the way that
|
* As such, it is not able to supply a response to the incoming request in the way that
|
||||||
* {@link #incomingRequestPreHandled(RestOperationTypeEnum, ActionRequestDetails)} and
|
* {@link #incomingRequestPreHandled(RestOperationTypeEnum, ActionRequestDetails)} and
|
||||||
* {@link #incomingRequestPostProcessed(RequestDetails, HttpServletRequest, HttpServletResponse)}
|
* {@link #incomingRequestPostProcessed(RequestDetails, HttpServletRequest, HttpServletResponse)}
|
||||||
* are.
|
* are.
|
||||||
* <p>
|
* <p>
|
||||||
* This method may however throw a subclass of {@link BaseServerResponseException}, and processing
|
* This method may however throw a subclass of {@link BaseServerResponseException}, and processing
|
||||||
@ -292,7 +295,8 @@ public interface IServerInterceptor {
|
|||||||
* 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. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
* attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
|
||||||
*/
|
*/
|
||||||
boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
|
boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||||
|
throws AuthenticationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
* This method is called after the server implementation method has been called, but before any attempt to stream the
|
||||||
@ -364,6 +368,15 @@ public interface IServerInterceptor {
|
|||||||
*/
|
*/
|
||||||
BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException;
|
BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called after all processing is completed for a request, but only if the
|
||||||
|
* request completes normally (i.e. no exception is thrown).
|
||||||
|
*
|
||||||
|
* @param theRequestDetails
|
||||||
|
* The request itself
|
||||||
|
*/
|
||||||
|
void processingCompletedNormally(ServletRequestDetails theRequestDetails);
|
||||||
|
|
||||||
public static class ActionRequestDetails {
|
public static class ActionRequestDetails {
|
||||||
private final FhirContext myContext;
|
private final FhirContext myContext;
|
||||||
private final IIdType myId;
|
private final IIdType myId;
|
||||||
@ -400,20 +413,22 @@ public interface IServerInterceptor {
|
|||||||
myResource = theResource;
|
myResource = theResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionRequestDetails(RequestDetails theRequestDetails, String theResourceType, IIdType theId) {
|
|
||||||
this(theRequestDetails, theRequestDetails.getServer().getFhirContext(), theResourceType, theId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param theRequestDetails The request details to wrap
|
* @param theRequestDetails
|
||||||
* @param theId The ID of the resource being created (note that the ID should have the resource type populated)
|
* The request details to wrap
|
||||||
|
* @param theId
|
||||||
|
* The ID of the resource being created (note that the ID should have the resource type populated)
|
||||||
*/
|
*/
|
||||||
public ActionRequestDetails(RequestDetails theRequestDetails, IIdType theId) {
|
public ActionRequestDetails(RequestDetails theRequestDetails, IIdType theId) {
|
||||||
this(theRequestDetails, theId.getResourceType(), theId);
|
this(theRequestDetails, theId.getResourceType(), theId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ActionRequestDetails(RequestDetails theRequestDetails, String theResourceType, IIdType theId) {
|
||||||
|
this(theRequestDetails, theRequestDetails.getServer().getFhirContext(), theResourceType, theId);
|
||||||
|
}
|
||||||
|
|
||||||
public FhirContext getContext() {
|
public FhirContext getContext() {
|
||||||
return myContext;
|
return myContext;
|
||||||
}
|
}
|
||||||
@ -454,14 +469,14 @@ public interface IServerInterceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the same map which was
|
* Returns the same map which was
|
||||||
*/
|
*/
|
||||||
public Map<Object, Object> getUserData() {
|
public Map<Object, Object> getUserData() {
|
||||||
return myRequestDetails.getUserData();
|
return myRequestDetails.getUserData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method may be invoked by user code to notify interceptors that a nested
|
* This method may be invoked by user code to notify interceptors that a nested
|
||||||
* operation is being invoked which is denoted by this request details.
|
* operation is being invoked which is denoted by this request details.
|
||||||
*/
|
*/
|
||||||
public void notifyIncomingRequestPreHandled(RestOperationTypeEnum theOperationType) {
|
public void notifyIncomingRequestPreHandled(RestOperationTypeEnum theOperationType) {
|
||||||
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.server.interceptor;
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -38,13 +38,13 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for {@link IServerInterceptor} implementations. Provides a No-op implementation
|
* Base class for {@link IServerInterceptor} implementations. Provides a No-op implementation
|
||||||
* of all methods, always returning <code>true</code>
|
* of all methods, always returning <code>true</code>
|
||||||
*/
|
*/
|
||||||
public class InterceptorAdapter implements IServerInterceptor {
|
public class InterceptorAdapter implements IServerInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws ServletException,
|
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||||
IOException {
|
throws ServletException, IOException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,52 +64,60 @@ public class InterceptorAdapter implements IServerInterceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
public boolean outgoingResponse(RequestDetails theRequestDetails) {
|
||||||
|
ServletRequestDetails details = (ServletRequestDetails) theRequestDetails;
|
||||||
|
return outgoingResponse(theRequestDetails, details.getServletRequest(), details.getServletResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle bundle) {
|
||||||
|
ServletRequestDetails details = (ServletRequestDetails) theRequestDetails;
|
||||||
|
return outgoingResponse(details, bundle, details.getServletRequest(), details.getServletResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||||
|
throws AuthenticationException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle bundle) {
|
|
||||||
ServletRequestDetails details = (ServletRequestDetails) theRequestDetails;
|
|
||||||
return outgoingResponse(details, bundle, details.getServletRequest(), details.getServletResponse());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
public boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails) {
|
|
||||||
ServletRequestDetails details = (ServletRequestDetails) theRequestDetails;
|
|
||||||
return outgoingResponse(theRequestDetails, details.getServletRequest(), details.getServletResponse());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) {
|
||||||
return true;
|
ServletRequestDetails details = (ServletRequestDetails) theRequestDetails;
|
||||||
|
return outgoingResponse(details, theResponseObject, details.getServletRequest(), details.getServletResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) {
|
|
||||||
ServletRequestDetails details = (ServletRequestDetails) theRequestDetails;
|
|
||||||
return outgoingResponse(details, theResponseObject, details.getServletRequest(), details.getServletResponse());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
|
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||||
|
throws AuthenticationException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject) {
|
||||||
|
ServletRequestDetails details = (ServletRequestDetails) theRequestDetails;
|
||||||
|
return outgoingResponse(details, theResponseObject, details.getServletRequest(), details.getServletResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||||
|
throws AuthenticationException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject) {
|
|
||||||
ServletRequestDetails details = (ServletRequestDetails) theRequestDetails;
|
|
||||||
return outgoingResponse(details, theResponseObject, details.getServletRequest(), details.getServletResponse());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException {
|
public BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processingCompletedNormally(ServletRequestDetails theRequestDetails) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
@ -41,11 +42,14 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding;
|
import ca.uhn.fhir.rest.server.RestfulServerUtils.ResponseEncoding;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server interceptor which logs each request using a defined format
|
* Server interceptor which logs each request using a defined format
|
||||||
@ -74,7 +78,7 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
|||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td>${remoteAddr}</td>
|
* <td>${remoteAddr}</td>
|
||||||
* <td>The originaring IP of the request</td>
|
* <td>The originating IP of the request</td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td>${requestHeader.XXXX}</td>
|
* <td>${requestHeader.XXXX}</td>
|
||||||
@ -115,6 +119,15 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
|||||||
* </tr>
|
* </tr>
|
||||||
* </table>
|
* </table>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: implement this, but it needs the logging to happen at the end
|
||||||
|
* <tr>
|
||||||
|
* <td>${processingTimeMillis}</td>
|
||||||
|
* <td>The number of milliseconds spent processing this request</td>
|
||||||
|
* </tr>
|
||||||
|
|
||||||
|
*/
|
||||||
public class LoggingInterceptor extends InterceptorAdapter {
|
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);
|
||||||
@ -146,18 +159,16 @@ public class LoggingInterceptor extends InterceptorAdapter {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean incomingRequestPostProcessed(final RequestDetails theRequestDetails, final HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processingCompletedNormally(ServletRequestDetails theRequestDetails) {
|
||||||
// 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(theRequestDetails.getServletRequest(), theRequestDetails);
|
||||||
StrSubstitutor subs = new StrSubstitutor(lookup, "${", "}", '\\');
|
StrSubstitutor subs = new StrSubstitutor(lookup, "${", "}", '\\');
|
||||||
|
|
||||||
// Actuall log the line
|
// Actuall log the line
|
||||||
String line = subs.replace(myMessageFormat);
|
String line = subs.replace(myMessageFormat);
|
||||||
myLogger.info(line);
|
myLogger.info(line);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -308,10 +319,16 @@ public class LoggingInterceptor extends InterceptorAdapter {
|
|||||||
EncodingEnum encoding = EncodingEnum.forContentType(contentType);
|
EncodingEnum encoding = EncodingEnum.forContentType(contentType);
|
||||||
if (encoding != null) {
|
if (encoding != null) {
|
||||||
byte[] requestContents = myRequestDetails.loadRequestContents();
|
byte[] requestContents = myRequestDetails.loadRequestContents();
|
||||||
return new String(requestContents, Charsets.UTF_8);
|
return new String(requestContents, Constants.CHARSET_UTF8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
|
} else if ("processingTimeMillis".equals(theKey)) {
|
||||||
|
Date startTime = (Date) myRequest.getAttribute(RestfulServer.REQUEST_START_TIME);
|
||||||
|
if (startTime != null) {
|
||||||
|
long time = System.currentTimeMillis() - startTime.getTime();
|
||||||
|
return Long.toString(time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "!VAL!";
|
return "!VAL!";
|
||||||
|
@ -24,10 +24,12 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
@ -39,6 +41,7 @@ import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
|||||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
import ca.uhn.fhir.rest.method.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
import ca.uhn.fhir.rest.server.RestfulServerUtils;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
@ -206,7 +209,7 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
|||||||
return super.handleException(theRequestDetails, theException, theServletRequest, theServletResponse);
|
return super.handleException(theRequestDetails, theException, theServletRequest, theServletResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
streamResponse(theRequestDetails, theServletResponse, theException.getOperationOutcome());
|
streamResponse(theRequestDetails, theServletResponse, theException.getOperationOutcome(), theServletRequest);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -276,12 +279,12 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
|||||||
return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse);
|
return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
streamResponse(theRequestDetails, theServletResponse, theResponseObject);
|
streamResponse(theRequestDetails, theServletResponse, theResponseObject, theServletRequest);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void streamResponse(RequestDetails theRequestDetails, HttpServletResponse theServletResponse, IBaseResource resource) {
|
private void streamResponse(RequestDetails theRequestDetails, HttpServletResponse theServletResponse, IBaseResource resource, ServletRequest theServletRequest) {
|
||||||
IParser p;
|
IParser p;
|
||||||
Map<String, String[]> parameters = theRequestDetails.getParameters();
|
Map<String, String[]> parameters = theRequestDetails.getParameters();
|
||||||
if (parameters.containsKey(Constants.PARAM_FORMAT)) {
|
if (parameters.containsKey(Constants.PARAM_FORMAT)) {
|
||||||
@ -360,6 +363,16 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
|
|||||||
b.append("<a href=\"");
|
b.append("<a href=\"");
|
||||||
b.append(createLinkHref(parameters, Constants.FORMATS_HTML_XML));
|
b.append(createLinkHref(parameters, Constants.FORMATS_HTML_XML));
|
||||||
b.append("\">HTML XML</a>.");
|
b.append("\">HTML XML</a>.");
|
||||||
|
|
||||||
|
Date startTime = (Date) theServletRequest.getAttribute(RestfulServer.REQUEST_START_TIME);
|
||||||
|
if (startTime != null) {
|
||||||
|
long time = System.currentTimeMillis() - startTime.getTime();
|
||||||
|
b.append(" Response generated in ");
|
||||||
|
b.append(time);
|
||||||
|
b.append("ms.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
b.append("</p>");
|
b.append("</p>");
|
||||||
|
|
||||||
b.append("\n");
|
b.append("\n");
|
||||||
|
Binary file not shown.
@ -3,18 +3,17 @@ package ca.uhn.fhir.rest.client;
|
|||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.mockito.Matchers.argThat;
|
import static org.mockito.Matchers.argThat;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.junit.After;
|
import org.junit.*;
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.mockito.ArgumentMatcher;
|
import org.mockito.ArgumentMatcher;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -29,18 +28,13 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
|
|||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import ch.qos.logback.classic.BasicConfigurator;
|
|
||||||
import ch.qos.logback.classic.Logger;
|
import ch.qos.logback.classic.Logger;
|
||||||
import ch.qos.logback.classic.LoggerContext;
|
import ch.qos.logback.classic.LoggerContext;
|
||||||
import ch.qos.logback.classic.joran.JoranConfigurator;
|
import ch.qos.logback.classic.joran.JoranConfigurator;
|
||||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
import ch.qos.logback.classic.spi.LoggingEvent;
|
import ch.qos.logback.classic.spi.LoggingEvent;
|
||||||
import ch.qos.logback.classic.util.LogbackMDCAdapter;
|
|
||||||
import ch.qos.logback.core.Appender;
|
import ch.qos.logback.core.Appender;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by dsotnikov on 2/25/2014.
|
|
||||||
*/
|
|
||||||
public class LoggingInterceptorTest {
|
public class LoggingInterceptorTest {
|
||||||
|
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu1();
|
private static FhirContext ourCtx = FhirContext.forDstu1();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ca.uhn.fhir.rest.server.interceptor;
|
package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.matchesPattern;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@ -59,9 +60,6 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||||||
import ca.uhn.fhir.util.PortUtil;
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by dsotnikov on 2/25/2014.
|
|
||||||
*/
|
|
||||||
public class LoggingInterceptorDstu2Test {
|
public class LoggingInterceptorDstu2Test {
|
||||||
|
|
||||||
private static CloseableHttpClient ourClient;
|
private static CloseableHttpClient ourClient;
|
||||||
@ -70,6 +68,7 @@ public class LoggingInterceptorDstu2Test {
|
|||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
private static RestfulServer servlet;
|
private static RestfulServer servlet;
|
||||||
private IServerInterceptor myInterceptor;
|
private IServerInterceptor myInterceptor;
|
||||||
|
private static int ourDelayMs;
|
||||||
private static Exception ourThrowException;
|
private static Exception ourThrowException;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@ -77,6 +76,7 @@ public class LoggingInterceptorDstu2Test {
|
|||||||
myInterceptor = mock(IServerInterceptor.class);
|
myInterceptor = mock(IServerInterceptor.class);
|
||||||
servlet.setInterceptors(Collections.singletonList(myInterceptor));
|
servlet.setInterceptors(Collections.singletonList(myInterceptor));
|
||||||
ourThrowException = null;
|
ourThrowException = null;
|
||||||
|
ourDelayMs=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -160,6 +160,27 @@ public class LoggingInterceptorDstu2Test {
|
|||||||
assertEquals("read - - Patient/1 - ", captor.getValue());
|
assertEquals("read - - Patient/1 - ", captor.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcessingTime() throws Exception {
|
||||||
|
ourDelayMs = 110;
|
||||||
|
|
||||||
|
LoggingInterceptor interceptor = new LoggingInterceptor();
|
||||||
|
interceptor.setMessageFormat("${processingTimeMillis}");
|
||||||
|
servlet.setInterceptors(Collections.singletonList((IServerInterceptor) interceptor));
|
||||||
|
|
||||||
|
Logger logger = mock(Logger.class);
|
||||||
|
interceptor.setLogger(logger);
|
||||||
|
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
||||||
|
|
||||||
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(logger, times(1)).info(captor.capture());
|
||||||
|
assertThat(captor.getValue(), matchesPattern("[0-9]{3}"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRequestBodyReadWithContentTypeHeader() throws Exception {
|
public void testRequestBodyReadWithContentTypeHeader() throws Exception {
|
||||||
|
|
||||||
@ -386,7 +407,11 @@ public class LoggingInterceptorDstu2Test {
|
|||||||
* @return The resource
|
* @return The resource
|
||||||
*/
|
*/
|
||||||
@Read()
|
@Read()
|
||||||
public Patient getResourceById(@IdParam IdDt theId) {
|
public Patient getResourceById(@IdParam IdDt theId) throws InterruptedException {
|
||||||
|
if (ourDelayMs>0) {
|
||||||
|
Thread.sleep(ourDelayMs);
|
||||||
|
}
|
||||||
|
|
||||||
if (theId.getIdPart().equals("EX")) {
|
if (theId.getIdPart().equals("EX")) {
|
||||||
throw new InvalidRequestException("FOO");
|
throw new InvalidRequestException("FOO");
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ca.uhn.fhir.rest.server.interceptor;
|
package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.matchesPattern;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
@ -14,6 +15,7 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -87,12 +89,26 @@ public class ResponseHighlightingInterceptorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testForceResponseTime() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=html/json");
|
||||||
|
|
||||||
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertEquals("text/html;charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
||||||
|
assertThat(responseContent.replace('\n', ' ').replace('\r', ' '), matchesPattern(".*Response generated in [0-9]+ms.*"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetInvalidResource() throws Exception {
|
public void testGetInvalidResource() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Foobar/123");
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Foobar/123");
|
||||||
httpGet.addHeader("Accept", "text/html");
|
httpGet.addHeader("Accept", "text/html");
|
||||||
CloseableHttpResponse status = ourClient.execute(httpGet);
|
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
ourLog.info("Resp: {}", responseContent);
|
ourLog.info("Resp: {}", responseContent);
|
||||||
@ -457,7 +473,7 @@ public class ResponseHighlightingInterceptorTest {
|
|||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_query=searchWithWildcardRetVal&_summary=count");
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_query=searchWithWildcardRetVal&_summary=count");
|
||||||
httpGet.addHeader("Accept", "html");
|
httpGet.addHeader("Accept", "html");
|
||||||
CloseableHttpResponse status = ourClient.execute(httpGet);
|
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
ourLog.info("Resp: {}", responseContent);
|
ourLog.info("Resp: {}", responseContent);
|
||||||
@ -501,7 +517,7 @@ public class ResponseHighlightingInterceptorTest {
|
|||||||
httpGet.addHeader("Accept", Constants.CT_FHIR_JSON);
|
httpGet.addHeader("Accept", Constants.CT_FHIR_JSON);
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
||||||
@ -515,7 +531,7 @@ public class ResponseHighlightingInterceptorTest {
|
|||||||
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
||||||
@ -527,7 +543,7 @@ public class ResponseHighlightingInterceptorTest {
|
|||||||
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
||||||
@ -539,7 +555,7 @@ public class ResponseHighlightingInterceptorTest {
|
|||||||
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
||||||
@ -552,7 +568,7 @@ public class ResponseHighlightingInterceptorTest {
|
|||||||
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
assertEquals(Constants.CT_FHIR_JSON + ";charset=utf-8", status.getFirstHeader("content-type").getValue().replace(" ", "").toLowerCase());
|
||||||
@ -567,7 +583,7 @@ public class ResponseHighlightingInterceptorTest {
|
|||||||
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpGet);
|
HttpResponse status = ourClient.execute(httpGet);
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
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());
|
||||||
|
@ -62,7 +62,7 @@ public class PatchClientDstu3Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testJsonPatch() throws Exception {
|
public void testJsonPatchAnnotation() throws Exception {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = prepareResponse();
|
ArgumentCaptor<HttpUriRequest> capt = prepareResponse();
|
||||||
|
|
||||||
IClientType client = ourCtx.newRestfulClient(IClientType.class, "http://example.com/fhir");
|
IClientType client = ourCtx.newRestfulClient(IClientType.class, "http://example.com/fhir");
|
||||||
@ -79,6 +79,26 @@ public class PatchClientDstu3Test {
|
|||||||
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">OK</div>", ((OperationOutcome) outcome.getOperationOutcome()).getText().getDivAsString());
|
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">OK</div>", ((OperationOutcome) outcome.getOperationOutcome()).getText().getDivAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJsonPatchFluent() throws Exception {
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = prepareResponse();
|
||||||
|
|
||||||
|
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||||
|
|
||||||
|
Patient pt = new Patient();
|
||||||
|
pt.getText().setDivAsString("A PATIENT");
|
||||||
|
|
||||||
|
MethodOutcome outcome = client.patch().resource("").
|
||||||
|
|
||||||
|
patch(new IdType("Patient/123"), "{}", PatchTypeEnum.JSON_PATCH);
|
||||||
|
|
||||||
|
assertEquals("PATCH", capt.getAllValues().get(0).getMethod());
|
||||||
|
assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(0).getURI().toASCIIString());
|
||||||
|
assertEquals(Constants.CT_JSON_PATCH, capt.getAllValues().get(0).getFirstHeader("content-type").getValue().replaceAll(";.*", ""));
|
||||||
|
assertEquals("{}", extractBodyAsString(capt));
|
||||||
|
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">OK</div>", ((OperationOutcome) outcome.getOperationOutcome()).getText().getDivAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private String extractBodyAsString(ArgumentCaptor<HttpUriRequest> capt) throws IOException {
|
private String extractBodyAsString(ArgumentCaptor<HttpUriRequest> capt) throws IOException {
|
||||||
String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent(), "UTF-8");
|
String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(0)).getEntity().getContent(), "UTF-8");
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
<action type="fix">
|
<action type="fix">
|
||||||
Server history operation did not populate the Bundle.entry.request.url
|
Server history operation did not populate the Bundle.entry.request.url
|
||||||
field, which is required in order for the bundle to pass validation.
|
field, which is required in order for the bundle to pass validation.
|
||||||
Thanks to Richard Kavanaugh for spotting this!
|
Thanks to Richard Ettema for spotting this!
|
||||||
</action>
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="2.0" date="2016-08-30">
|
<release version="2.0" date="2016-08-30">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user