Merge branch 'jaxrs-client'
This commit is contained in:
commit
a818ba199c
|
@ -3,11 +3,11 @@ package example;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.IRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.apache.GZipContentInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.client.interceptor.BasicAuthInterceptor;
|
||||
import ca.uhn.fhir.rest.client.interceptor.BearerTokenAuthInterceptor;
|
||||
import ca.uhn.fhir.rest.client.interceptor.CookieInterceptor;
|
||||
import ca.uhn.fhir.rest.client.interceptor.GZipContentInterceptor;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ import ca.uhn.fhir.parser.LenientErrorHandler;
|
|||
import ca.uhn.fhir.parser.XmlParser;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.IRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.RestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||
|
@ -298,9 +298,22 @@ public class FhirContext {
|
|||
return myIdToResourceDefinition.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the restful client factory
|
||||
* @param theRestfulClientFactory
|
||||
*/
|
||||
public void setRestfulClientFactory(IRestfulClientFactory theRestfulClientFactory) {
|
||||
this.myRestfulClientFactory = theRestfulClientFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the restful client factory. If no factory has been set, this will be initialized with
|
||||
* a new ApacheRestfulClientFactory.
|
||||
* @return the factory used to create the restful clients
|
||||
*/
|
||||
public IRestfulClientFactory getRestfulClientFactory() {
|
||||
if (myRestfulClientFactory == null) {
|
||||
myRestfulClientFactory = new RestfulClientFactory(this);
|
||||
myRestfulClientFactory = new ApacheRestfulClientFactory(this);
|
||||
}
|
||||
return myRestfulClientFactory;
|
||||
}
|
||||
|
|
|
@ -25,10 +25,8 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -40,14 +38,6 @@ import java.util.Set;
|
|||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -62,6 +52,9 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
|||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
||||
|
@ -79,19 +72,19 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseClient.class);
|
||||
|
||||
private final HttpClient myClient;
|
||||
private final IHttpClient myClient;
|
||||
private boolean myDontValidateConformance;
|
||||
private EncodingEnum myEncoding = null; // default unspecified (will be XML)
|
||||
private final RestfulClientFactory myFactory;
|
||||
private List<IClientInterceptor> myInterceptors = new ArrayList<IClientInterceptor>();
|
||||
private boolean myKeepResponses = false;
|
||||
private HttpResponse myLastResponse;
|
||||
private IHttpResponse myLastResponse;
|
||||
private String myLastResponseBody;
|
||||
private Boolean myPrettyPrint = false;
|
||||
private SummaryEnum mySummary;
|
||||
private final String myUrlBase;
|
||||
|
||||
BaseClient(HttpClient theClient, String theUrlBase, RestfulClientFactory theFactory) {
|
||||
BaseClient(IHttpClient theClient, String theUrlBase, RestfulClientFactory theFactory) {
|
||||
super();
|
||||
myClient = theClient;
|
||||
myUrlBase = theUrlBase;
|
||||
|
@ -130,7 +123,7 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public HttpClient getHttpClient() {
|
||||
public IHttpClient getHttpClient() {
|
||||
return myClient;
|
||||
}
|
||||
|
||||
|
@ -141,7 +134,7 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public HttpResponse getLastResponse() {
|
||||
public IHttpResponse getLastResponse() {
|
||||
return myLastResponse;
|
||||
}
|
||||
|
||||
|
@ -193,8 +186,8 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
|
||||
// TODO: handle non 2xx status codes by throwing the correct exception,
|
||||
// and ensure it's passed upwards
|
||||
HttpRequestBase httpRequest;
|
||||
HttpResponse response;
|
||||
IHttpRequest httpRequest;
|
||||
IHttpResponse response = null;
|
||||
try {
|
||||
Map<String, List<String>> params = createExtraParams();
|
||||
|
||||
|
@ -227,12 +220,9 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
|
||||
if (theLogRequestAndResponse) {
|
||||
ourLog.info("Client invoking: {}", httpRequest);
|
||||
if (httpRequest instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntity entity = ((HttpEntityEnclosingRequest) httpRequest).getEntity();
|
||||
if (entity.isRepeatable()) {
|
||||
String content = IOUtils.toString(entity.getContent());
|
||||
ourLog.info("Client request body: {}", content);
|
||||
}
|
||||
String body = httpRequest.getRequestBodyFromStream();
|
||||
if(body != null) {
|
||||
ourLog.info("Client request body: {}", body);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,45 +230,26 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
nextInterceptor.interceptRequest(httpRequest);
|
||||
}
|
||||
|
||||
response = myClient.execute(httpRequest);
|
||||
response = httpRequest.execute();
|
||||
|
||||
for (IClientInterceptor nextInterceptor : myInterceptors) {
|
||||
nextInterceptor.interceptResponse(response);
|
||||
}
|
||||
|
||||
} catch (DataFormatException e) {
|
||||
throw new FhirClientConnectionException(e);
|
||||
} catch (IOException e) {
|
||||
throw new FhirClientConnectionException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
String mimeType;
|
||||
if (Constants.STATUS_HTTP_204_NO_CONTENT == response.getStatusLine().getStatusCode()) {
|
||||
if (Constants.STATUS_HTTP_204_NO_CONTENT == response.getStatus()) {
|
||||
mimeType = null;
|
||||
} else {
|
||||
ContentType ct = ContentType.get(response.getEntity());
|
||||
mimeType = ct != null ? ct.getMimeType() : null;
|
||||
mimeType = response.getMimeType();
|
||||
}
|
||||
|
||||
Map<String, List<String>> headers = new HashMap<String, List<String>>();
|
||||
if (response.getAllHeaders() != null) {
|
||||
for (Header next : response.getAllHeaders()) {
|
||||
String name = next.getName().toLowerCase();
|
||||
List<String> list = headers.get(name);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
headers.put(name, list);
|
||||
}
|
||||
list.add(next.getValue());
|
||||
}
|
||||
}
|
||||
Map<String, List<String>> headers = response.getAllHeaders();
|
||||
|
||||
if (response.getStatusLine().getStatusCode() < 200 || response.getStatusLine().getStatusCode() > 299) {
|
||||
if (response.getStatus() < 200 || response.getStatus() > 299) {
|
||||
String body = null;
|
||||
Reader reader = null;
|
||||
try {
|
||||
reader = createReaderFromResponse(response);
|
||||
reader = response.createReader();
|
||||
body = IOUtils.toString(reader);
|
||||
} catch (Exception e) {
|
||||
ourLog.debug("Failed to read input stream", e);
|
||||
|
@ -286,7 +257,7 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
IOUtils.closeQuietly(reader);
|
||||
}
|
||||
|
||||
String message = "HTTP " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase();
|
||||
String message = "HTTP " + response.getStatus() + " " + response.getStatusInfo();
|
||||
IBaseOperationOutcome oo = null;
|
||||
if (Constants.CT_TEXT.equals(mimeType)) {
|
||||
message = message + ": " + body;
|
||||
|
@ -309,7 +280,7 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
|
||||
keepResponseAndLogIt(theLogRequestAndResponse, response, body);
|
||||
|
||||
BaseServerResponseException exception = BaseServerResponseException.newInstance(response.getStatusLine().getStatusCode(), message);
|
||||
BaseServerResponseException exception = BaseServerResponseException.newInstance(response.getStatus(), message);
|
||||
exception.setOperationOutcome(oo);
|
||||
|
||||
if (body != null) {
|
||||
|
@ -321,7 +292,7 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
if (binding instanceof IClientResponseHandlerHandlesBinary) {
|
||||
IClientResponseHandlerHandlesBinary<T> handlesBinary = (IClientResponseHandlerHandlesBinary<T>) binding;
|
||||
if (handlesBinary.isBinary()) {
|
||||
InputStream reader = response.getEntity().getContent();
|
||||
InputStream reader = response.readEntity();
|
||||
try {
|
||||
|
||||
if (ourLog.isTraceEnabled() || myKeepResponses || theLogRequestAndResponse) {
|
||||
|
@ -330,7 +301,7 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
myLastResponse = response;
|
||||
myLastResponseBody = null;
|
||||
}
|
||||
String message = "HTTP " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase();
|
||||
String message = "HTTP " + response.getStatus() + " " + response.getStatusInfo();
|
||||
if (theLogRequestAndResponse) {
|
||||
ourLog.info("Client response: {} - {} bytes", message, responseBytes.length);
|
||||
} else {
|
||||
|
@ -339,14 +310,14 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
reader = new ByteArrayInputStream(responseBytes);
|
||||
}
|
||||
|
||||
return handlesBinary.invokeClient(mimeType, reader, response.getStatusLine().getStatusCode(), headers);
|
||||
return handlesBinary.invokeClient(mimeType, reader, response.getStatus(), headers);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reader reader = createReaderFromResponse(response);
|
||||
Reader reader = response.createReader();
|
||||
|
||||
if (ourLog.isTraceEnabled() || myKeepResponses || theLogRequestAndResponse) {
|
||||
String responseString = IOUtils.toString(reader);
|
||||
|
@ -355,22 +326,24 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
}
|
||||
|
||||
try {
|
||||
return binding.invokeClient(mimeType, reader, response.getStatusLine().getStatusCode(), headers);
|
||||
return binding.invokeClient(mimeType, reader, response.getStatus(), headers);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(reader);
|
||||
}
|
||||
|
||||
} catch (DataFormatException e) {
|
||||
throw new FhirClientConnectionException(e);
|
||||
} catch (IllegalStateException e) {
|
||||
throw new FhirClientConnectionException(e);
|
||||
} catch (IOException e) {
|
||||
throw new FhirClientConnectionException(e);
|
||||
} catch(RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new FhirClientConnectionException(e);
|
||||
} finally {
|
||||
if (response instanceof CloseableHttpResponse) {
|
||||
try {
|
||||
((CloseableHttpResponse) response).close();
|
||||
} catch (IOException e) {
|
||||
ourLog.debug("Failed to close response", e);
|
||||
}
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -391,13 +364,13 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
return Boolean.TRUE.equals(myPrettyPrint);
|
||||
}
|
||||
|
||||
private void keepResponseAndLogIt(boolean theLogRequestAndResponse, HttpResponse response, String responseString) {
|
||||
private void keepResponseAndLogIt(boolean theLogRequestAndResponse, IHttpResponse response, String responseString) {
|
||||
if (myKeepResponses) {
|
||||
myLastResponse = response;
|
||||
myLastResponseBody = responseString;
|
||||
}
|
||||
if (theLogRequestAndResponse) {
|
||||
String message = "HTTP " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase();
|
||||
String message = "HTTP " + response.getStatus() + " " + response.getStatusInfo();
|
||||
if (StringUtils.isNotBlank(responseString)) {
|
||||
ourLog.info("Client response: {}\n{}", message, responseString);
|
||||
} else {
|
||||
|
@ -444,7 +417,7 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public void setLastResponse(HttpResponse theLastResponse) {
|
||||
public void setLastResponse(IHttpResponse theLastResponse) {
|
||||
myLastResponse = theLastResponse;
|
||||
}
|
||||
|
||||
|
@ -477,30 +450,9 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
myInterceptors.remove(theInterceptor);
|
||||
}
|
||||
|
||||
public static Reader createReaderFromResponse(HttpResponse theResponse) throws IllegalStateException, IOException {
|
||||
HttpEntity entity = theResponse.getEntity();
|
||||
if (entity == null) {
|
||||
return new StringReader("");
|
||||
}
|
||||
Charset charset = null;
|
||||
if (entity.getContentType() != null && entity.getContentType().getElements() != null && entity.getContentType().getElements().length > 0) {
|
||||
ContentType ct = ContentType.get(entity);
|
||||
charset = ct.getCharset();
|
||||
}
|
||||
if (charset == null) {
|
||||
if (Constants.STATUS_HTTP_204_NO_CONTENT != theResponse.getStatusLine().getStatusCode()) {
|
||||
ourLog.warn("Response did not specify a charset.");
|
||||
}
|
||||
charset = Charset.forName("UTF-8");
|
||||
}
|
||||
|
||||
Reader reader = new InputStreamReader(theResponse.getEntity().getContent(), charset);
|
||||
return reader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResourceFromUrl(Class<T> theResourceType, String theUrl) {
|
||||
BaseHttpClientInvocation clientInvocation = new HttpGetClientInvocation(theUrl);
|
||||
BaseHttpClientInvocation clientInvocation = new HttpGetClientInvocation(getFhirContext(), theUrl);
|
||||
ResourceResponseHandler<T> binding = new ResourceResponseHandler<T>(theResourceType, null, false);
|
||||
return invokeClient(getFhirContext(), binding, clientInvocation, null, false, false, null, null);
|
||||
}
|
||||
|
|
|
@ -27,23 +27,25 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.api.Header;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.util.VersionUtil;
|
||||
|
||||
public abstract class BaseHttpClientInvocation {
|
||||
|
||||
private List<Header> myHeaders;
|
||||
private final List<Header> myHeaders;
|
||||
private final FhirContext myContext;
|
||||
|
||||
public BaseHttpClientInvocation(FhirContext myContext) {
|
||||
this.myContext = myContext;
|
||||
this.myHeaders = new ArrayList<Header>();
|
||||
}
|
||||
|
||||
public void addHeader(String theName, String theValue) {
|
||||
if (myHeaders == null) {
|
||||
myHeaders = new ArrayList<Header>();
|
||||
}
|
||||
myHeaders.add(new BasicHeader(theName, theValue));
|
||||
myHeaders.add(new Header(theName, theValue));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,15 +59,15 @@ public abstract class BaseHttpClientInvocation {
|
|||
* The encoding to use for any serialized content sent to the
|
||||
* server
|
||||
*/
|
||||
public abstract HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint);
|
||||
public abstract IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint);
|
||||
|
||||
protected static void appendExtraParamsWithQuestionMark(Map<String, List<String>> theExtraParams, StringBuilder theUrlBuilder, boolean theWithQuestionMark) {
|
||||
public static void appendExtraParamsWithQuestionMark(Map<String, List<String>> theExtraParams, StringBuilder theUrlBuilder, boolean theWithQuestionMark) {
|
||||
if (theExtraParams == null) {
|
||||
return;
|
||||
}
|
||||
boolean first = theWithQuestionMark;
|
||||
|
||||
if (theExtraParams != null && theExtraParams.isEmpty() == false) {
|
||||
if (theExtraParams.isEmpty() == false) {
|
||||
for (Entry<String, List<String>> next : theExtraParams.entrySet()) {
|
||||
for (String nextValue : next.getValue()) {
|
||||
if (first) {
|
||||
|
@ -86,25 +88,43 @@ public abstract class BaseHttpClientInvocation {
|
|||
}
|
||||
}
|
||||
|
||||
public void addHeadersToRequest(HttpRequestBase theHttpRequest, EncodingEnum theEncoding) {
|
||||
if (myHeaders != null) {
|
||||
for (Header next : myHeaders) {
|
||||
theHttpRequest.addHeader(next);
|
||||
}
|
||||
/**
|
||||
* Get the restfull client factory
|
||||
* @return
|
||||
*/
|
||||
public IRestfulClientFactory getRestfulClientFactory() {
|
||||
return myContext.getRestfulClientFactory();
|
||||
}
|
||||
|
||||
String versionString = VersionUtil.getVersion();
|
||||
theHttpRequest.addHeader("User-Agent", "HAPI-FHIR/" + versionString + " (FHIR Client)");
|
||||
theHttpRequest.addHeader("Accept-Charset", "utf-8");
|
||||
theHttpRequest.addHeader("Accept-Encoding", "gzip");
|
||||
|
||||
if (theEncoding == null) {
|
||||
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_XML_OR_JSON);
|
||||
} else if (theEncoding == EncodingEnum.JSON) {
|
||||
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON);
|
||||
} else if (theEncoding == EncodingEnum.XML) {
|
||||
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML);
|
||||
/**
|
||||
* Create an HTTP request for the given url, encoding and request-type
|
||||
*
|
||||
* @param theUrl
|
||||
* The complete FHIR url to which the http request will be sent
|
||||
* @param theEncoding
|
||||
* The encoding to use for any serialized content sent to the
|
||||
* server
|
||||
* @param theRequestType
|
||||
* the type of HTTP request (GET, DELETE, ..)
|
||||
*/
|
||||
protected IHttpRequest createHttpRequest(String theUrl, EncodingEnum theEncoding, RequestTypeEnum theRequestType) {
|
||||
IHttpClient httpClient = getRestfulClientFactory().getHttpClient(new StringBuilder(theUrl), null, null, theRequestType, myHeaders);
|
||||
return httpClient.createGetRequest(theEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the http headers to be sent with the request
|
||||
*/
|
||||
public List<Header> getHeaders() {
|
||||
return myHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FHIR context associated with this client
|
||||
* @return the myContext
|
||||
*/
|
||||
public FhirContext getFhirContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,20 +24,19 @@ import java.lang.reflect.InvocationHandler;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.client.ClientInvocationHandlerFactory.ILambda;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
|
||||
class ClientInvocationHandler extends BaseClient implements InvocationHandler {
|
||||
public class ClientInvocationHandler extends BaseClient implements InvocationHandler {
|
||||
|
||||
private final Map<Method, BaseMethodBinding<?>> myBindings;
|
||||
private final Map<Method, Object> myMethodToReturnValue;
|
||||
private FhirContext myContext;
|
||||
private Map<Method, ILambda> myMethodToLambda;
|
||||
|
||||
public ClientInvocationHandler(HttpClient theClient, FhirContext theContext, String theUrlBase, Map<Method, Object> theMethodToReturnValue, Map<Method, BaseMethodBinding<?>> theBindings, Map<Method, ILambda> theMethodToLambda, RestfulClientFactory theFactory) {
|
||||
public ClientInvocationHandler(IHttpClient theClient, FhirContext theContext, String theUrlBase, Map<Method, Object> theMethodToReturnValue, Map<Method, BaseMethodBinding<?>> theBindings, Map<Method, ILambda> theMethodToLambda, RestfulClientFactory theFactory) {
|
||||
super(theClient, theUrlBase, theFactory);
|
||||
|
||||
myContext = theContext;
|
||||
|
|
|
@ -24,26 +24,26 @@ import java.lang.reflect.Method;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
class ClientInvocationHandlerFactory {
|
||||
public class ClientInvocationHandlerFactory {
|
||||
|
||||
private final Map<Method, BaseMethodBinding<?>> myBindings = new HashMap<Method, BaseMethodBinding<?>>();
|
||||
private final HttpClient myClient;
|
||||
private final IHttpClient myClient;
|
||||
private final FhirContext myContext;
|
||||
private final Map<Method, ILambda> myMethodToLambda = new HashMap<Method, ILambda>();
|
||||
private final Map<Method, Object> myMethodToReturnValue = new HashMap<Method, Object>();
|
||||
private final String myUrlBase;
|
||||
|
||||
public ClientInvocationHandlerFactory(HttpClient theClient, FhirContext theContext, String theUrlBase, Class<? extends IRestfulClient> theClientType) {
|
||||
public ClientInvocationHandlerFactory(IHttpClient theClient, FhirContext theContext, String theUrlBase, Class<? extends IRestfulClient> theClientType) {
|
||||
myClient = theClient;
|
||||
myUrlBase = theUrlBase;
|
||||
myContext = theContext;
|
||||
|
@ -75,7 +75,7 @@ class ClientInvocationHandlerFactory {
|
|||
return new ClientInvocationHandler(myClient, myContext, myUrlBase, myMethodToReturnValue, myBindings, myMethodToLambda, theRestfulClientFactory);
|
||||
}
|
||||
|
||||
interface ILambda {
|
||||
public interface ILambda {
|
||||
Object handle(ClientInvocationHandler theTarget, Object[] theArgs);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,8 +38,6 @@ import java.util.Set;
|
|||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||
|
@ -72,6 +70,8 @@ import ca.uhn.fhir.parser.IParser;
|
|||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.PreferReturnEnum;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
||||
import ca.uhn.fhir.rest.gclient.IClientExecutable;
|
||||
import ca.uhn.fhir.rest.gclient.ICreate;
|
||||
|
@ -157,13 +157,13 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
private static final String I18N_NO_VERSION_ID_FOR_VREAD = "ca.uhn.fhir.rest.client.GenericClient.noVersionIdForVread";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(GenericClient.class);
|
||||
private FhirContext myContext;
|
||||
private HttpRequestBase myLastRequest;
|
||||
private IHttpRequest myLastRequest;
|
||||
private boolean myLogRequestAndResponse;
|
||||
|
||||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public GenericClient(FhirContext theContext, HttpClient theHttpClient, String theServerBase, RestfulClientFactory theFactory) {
|
||||
public GenericClient(FhirContext theContext, IHttpClient theHttpClient, String theServerBase, RestfulClientFactory theFactory) {
|
||||
super(theHttpClient, theServerBase, theFactory);
|
||||
myContext = theContext;
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
throw new IllegalArgumentException("Must call conformance(" + IBaseConformance.class.getSimpleName() + ") instead of conformance() for HL7.org structures");
|
||||
}
|
||||
|
||||
HttpGetClientInvocation invocation = MethodUtil.createConformanceInvocation();
|
||||
HttpGetClientInvocation invocation = MethodUtil.createConformanceInvocation(getFhirContext());
|
||||
if (isKeepResponses()) {
|
||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding(), isPrettyPrint());
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
@Override
|
||||
public MethodOutcome delete(final Class<? extends IBaseResource> theType, IdDt theId) {
|
||||
HttpDeleteClientInvocation invocation = DeleteMethodBinding.createDeleteInvocation(theId.withResourceType(toResourceName(theType)));
|
||||
HttpDeleteClientInvocation invocation = DeleteMethodBinding.createDeleteInvocation(getFhirContext(), theId.withResourceType(toResourceName(theType)));
|
||||
if (isKeepResponses()) {
|
||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding(), isPrettyPrint());
|
||||
}
|
||||
|
@ -243,15 +243,15 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
HttpGetClientInvocation invocation;
|
||||
if (id.hasBaseUrl()) {
|
||||
if (theVRead) {
|
||||
invocation = ReadMethodBinding.createAbsoluteVReadInvocation(id);
|
||||
invocation = ReadMethodBinding.createAbsoluteVReadInvocation(getFhirContext(), id);
|
||||
} else {
|
||||
invocation = ReadMethodBinding.createAbsoluteReadInvocation(id);
|
||||
invocation = ReadMethodBinding.createAbsoluteReadInvocation(getFhirContext(), id);
|
||||
}
|
||||
} else {
|
||||
if (theVRead) {
|
||||
invocation = ReadMethodBinding.createVReadInvocation(id, resName);
|
||||
invocation = ReadMethodBinding.createVReadInvocation(getFhirContext(), id, resName);
|
||||
} else {
|
||||
invocation = ReadMethodBinding.createReadInvocation(id, resName);
|
||||
invocation = ReadMethodBinding.createReadInvocation(getFhirContext(), id, resName);
|
||||
}
|
||||
}
|
||||
if (isKeepResponses()) {
|
||||
|
@ -305,7 +305,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
return myContext;
|
||||
}
|
||||
|
||||
public HttpRequestBase getLastRequest() {
|
||||
public IHttpRequest getLastRequest() {
|
||||
return myLastRequest;
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
public <T extends IBaseResource> Bundle history(final Class<T> theType, IdDt theIdDt, DateTimeDt theSince, Integer theLimit) {
|
||||
String resourceName = theType != null ? toResourceName(theType) : null;
|
||||
String id = theIdDt != null && theIdDt.isEmpty() == false ? theIdDt.getValue() : null;
|
||||
HttpGetClientInvocation invocation = HistoryMethodBinding.createHistoryInvocation(resourceName, id, theSince, theLimit);
|
||||
HttpGetClientInvocation invocation = HistoryMethodBinding.createHistoryInvocation(myContext, resourceName, id, theSince, theLimit);
|
||||
if (isKeepResponses()) {
|
||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding(), isPrettyPrint());
|
||||
}
|
||||
|
@ -468,7 +468,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
@Override
|
||||
public <T extends IBaseResource> Bundle search(final Class<T> theType, UriDt theUrl) {
|
||||
BaseHttpClientInvocation invocation = new HttpGetClientInvocation(theUrl.getValueAsString());
|
||||
BaseHttpClientInvocation invocation = new HttpGetClientInvocation(getFhirContext(), theUrl.getValueAsString());
|
||||
return invokeClient(myContext, new BundleResponseHandler(theType), invocation);
|
||||
}
|
||||
|
||||
|
@ -480,7 +480,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public void setLastRequest(HttpRequestBase theLastRequest) {
|
||||
public void setLastRequest(IHttpRequest theLastRequest) {
|
||||
myLastRequest = theLastRequest;
|
||||
}
|
||||
|
||||
|
@ -839,12 +839,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
public BaseOperationOutcome execute() {
|
||||
HttpDeleteClientInvocation invocation;
|
||||
if (myId != null) {
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(myId);
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(getFhirContext(), myId);
|
||||
} else if (myCriterionList != null) {
|
||||
Map<String, List<String>> params = myCriterionList.toParamList();
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(myResourceType, params);
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(getFhirContext(), myResourceType, params);
|
||||
} else {
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(mySearchUrl);
|
||||
invocation = DeleteMethodBinding.createDeleteInvocation(getFhirContext(), mySearchUrl);
|
||||
}
|
||||
OperationOutcomeResponseHandler binding = new OperationOutcomeResponseHandler();
|
||||
Map<String, List<String>> params = new HashMap<String, List<String>>();
|
||||
|
@ -926,7 +926,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
@Override
|
||||
public Object execute() {
|
||||
ResourceResponseHandler binding = new ResourceResponseHandler(myType.getImplementingClass(), null);
|
||||
HttpGetClientInvocation invocation = MethodUtil.createConformanceInvocation();
|
||||
HttpGetClientInvocation invocation = MethodUtil.createConformanceInvocation(getFhirContext());
|
||||
return super.invoke(null, binding, invocation);
|
||||
}
|
||||
|
||||
|
@ -965,7 +965,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
} else {
|
||||
binding = new ResourceResponseHandler(myBundleType, null);
|
||||
}
|
||||
HttpSimpleGetClientInvocation invocation = new HttpSimpleGetClientInvocation(myUrl);
|
||||
HttpSimpleGetClientInvocation invocation = new HttpSimpleGetClientInvocation(myContext, myUrl);
|
||||
|
||||
Map<String, List<String>> params = null;
|
||||
return invoke(params, binding, invocation);
|
||||
|
@ -1002,7 +1002,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
urlFragments.add(Constants.PARAM_TAGS);
|
||||
|
||||
HttpGetClientInvocation invocation = new HttpGetClientInvocation(params, urlFragments);
|
||||
HttpGetClientInvocation invocation = new HttpGetClientInvocation(myContext, params, urlFragments);
|
||||
|
||||
return invoke(params, binding, invocation);
|
||||
|
||||
|
@ -1083,7 +1083,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
id = null;
|
||||
}
|
||||
|
||||
HttpGetClientInvocation invocation = HistoryMethodBinding.createHistoryInvocation(resourceName, id, mySince, myCount);
|
||||
HttpGetClientInvocation invocation = HistoryMethodBinding.createHistoryInvocation(myContext, resourceName, id, mySince, myCount);
|
||||
|
||||
IClientResponseHandler handler;
|
||||
if (myReturnType != null) {
|
||||
|
@ -1813,7 +1813,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
|
||||
BaseHttpClientInvocation invocation;
|
||||
if (mySearchUrl != null) {
|
||||
invocation = SearchMethodBinding.createSearchInvocation(mySearchUrl, params);
|
||||
invocation = SearchMethodBinding.createSearchInvocation(myContext, mySearchUrl, params);
|
||||
} else {
|
||||
invocation = SearchMethodBinding.createSearchInvocation(myContext, myResourceName, params, resourceId, myCompartmentName, mySearchStyle);
|
||||
}
|
||||
|
|
|
@ -22,19 +22,19 @@ package ca.uhn.fhir.rest.client;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
|
||||
public interface IClientInterceptor {
|
||||
|
||||
/**
|
||||
* Fired by the client just before invoking the HTTP client request
|
||||
*/
|
||||
void interceptRequest(HttpRequestBase theRequest);
|
||||
void interceptRequest(IHttpRequest theRequest);
|
||||
|
||||
/**
|
||||
* Fired by the client upon receiving an HTTP response, prior to processing that response
|
||||
*/
|
||||
void interceptResponse(HttpResponse theResponse) throws IOException;
|
||||
void interceptResponse(IHttpResponse theResponse) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
@ -20,9 +20,13 @@ package ca.uhn.fhir.rest.client;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.api.Header;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
|
||||
public interface IRestfulClientFactory {
|
||||
|
@ -76,11 +80,20 @@ public interface IRestfulClientFactory {
|
|||
int getConnectTimeout();
|
||||
|
||||
/**
|
||||
* Returns the Apache HTTP client instance. This method will not return null.
|
||||
*
|
||||
* @see #setHttpClient(HttpClient)
|
||||
* Returns the HTTP client instance. This method will not return null.
|
||||
* @param theUrl
|
||||
* The complete FHIR url to which the http request will be sent
|
||||
* @param theIfNoneExistParams
|
||||
* The params for header "If-None-Exist" as a hashmap
|
||||
* @param theIfNoneExistString
|
||||
* The param for header "If-None-Exist" as a string
|
||||
* @param theRequestType
|
||||
* the type of HTTP request (GET, DELETE, ..)
|
||||
* @param theHeaders
|
||||
* the headers to be sent together with the http request
|
||||
* @return the HTTP client instance
|
||||
*/
|
||||
HttpClient getHttpClient();
|
||||
IHttpClient getHttpClient(StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams, String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getServerValidationMode()} instead
|
||||
|
@ -172,7 +185,7 @@ public interface IRestfulClientFactory {
|
|||
* @param theHttpClient
|
||||
* An HTTP client instance to use, or <code>null</code>
|
||||
*/
|
||||
void setHttpClient(HttpClient theHttpClient);
|
||||
<T> void setHttpClient(T theHttpClient);
|
||||
|
||||
/**
|
||||
* Sets the HTTP proxy to use for outgoing connections
|
||||
|
@ -234,4 +247,12 @@ public interface IRestfulClientFactory {
|
|||
* </p>
|
||||
*/
|
||||
void setPoolMaxPerRoute(int thePoolMaxPerRoute);
|
||||
|
||||
void validateServerBase(String theServerBase, IHttpClient theHttpClient, BaseClient theClient);
|
||||
|
||||
/**
|
||||
* This method is internal to HAPI - It may change in future versions, use with caution.
|
||||
*/
|
||||
void validateServerBaseIfConfiguredToDoSo(String theServerBase, IHttpClient theHttpClient, BaseClient theClient);
|
||||
|
||||
}
|
||||
|
|
|
@ -28,27 +28,16 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
|
||||
|
@ -56,18 +45,18 @@ import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
|||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public class RestfulClientFactory implements IRestfulClientFactory {
|
||||
public abstract class RestfulClientFactory implements IRestfulClientFactory {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulClientFactory.class);
|
||||
private int myConnectionRequestTimeout = DEFAULT_CONNECTION_REQUEST_TIMEOUT;
|
||||
private int myConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
||||
private FhirContext myContext;
|
||||
private HttpClient myHttpClient;
|
||||
private Map<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory> myInvocationHandlers = new HashMap<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory>();
|
||||
private HttpHost myProxy;
|
||||
private ServerValidationModeEnum myServerValidationMode = DEFAULT_SERVER_VALIDATION_MODE;
|
||||
private int mySocketTimeout = DEFAULT_SOCKET_TIMEOUT;
|
||||
private Set<String> myValidatedServerBaseUrls = Collections.synchronizedSet(new HashSet<String>());
|
||||
private String myProxyUsername;
|
||||
private String myProxyPassword;
|
||||
private int myPoolMaxTotal = DEFAULT_POOL_MAX;
|
||||
private int myPoolMaxPerRoute = DEFAULT_POOL_MAX_PER_ROUTE;
|
||||
|
||||
|
@ -97,46 +86,22 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
return myConnectTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized HttpClient getHttpClient() {
|
||||
if (myHttpClient == null) {
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
connectionManager.setMaxTotal(myPoolMaxTotal);
|
||||
connectionManager.setDefaultMaxPerRoute(myPoolMaxPerRoute);
|
||||
|
||||
//@formatter:off
|
||||
RequestConfig defaultRequestConfig = RequestConfig.custom()
|
||||
.setSocketTimeout(mySocketTimeout)
|
||||
.setConnectTimeout(myConnectTimeout)
|
||||
.setConnectionRequestTimeout(myConnectionRequestTimeout)
|
||||
.setStaleConnectionCheckEnabled(true)
|
||||
.setProxy(myProxy)
|
||||
.build();
|
||||
|
||||
HttpClientBuilder builder = HttpClients.custom()
|
||||
.setConnectionManager(connectionManager)
|
||||
.setDefaultRequestConfig(defaultRequestConfig)
|
||||
.disableCookieManagement();
|
||||
|
||||
if (myProxy != null && StringUtils.isNotBlank(myProxyUsername) && StringUtils.isNotBlank(myProxyPassword)) {
|
||||
CredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||
credsProvider.setCredentials(new AuthScope(myProxy.getHostName(), myProxy.getPort()), new UsernamePasswordCredentials(myProxyUsername, myProxyPassword));
|
||||
builder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());
|
||||
builder.setDefaultCredentialsProvider(credsProvider);
|
||||
/**
|
||||
* Return the proxy username to authenticate with the HTTP proxy
|
||||
* @param The proxy username
|
||||
*/
|
||||
protected String getProxyUsername() {
|
||||
return myProxyUsername;
|
||||
}
|
||||
|
||||
myHttpClient = builder.build();
|
||||
//@formatter:on
|
||||
|
||||
/**
|
||||
* Return the proxy password to authenticate with the HTTP proxy
|
||||
* @param The proxy password
|
||||
*/
|
||||
protected String getProxyPassword() {
|
||||
return myProxyPassword;
|
||||
}
|
||||
|
||||
return myHttpClient;
|
||||
}
|
||||
|
||||
private String myProxyUsername;
|
||||
private String myProxyPassword;
|
||||
|
||||
@Override
|
||||
public void setProxyCredentials(String theUsername, String thePassword) {
|
||||
myProxyUsername=theUsername;
|
||||
|
@ -189,7 +154,7 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
|
||||
ClientInvocationHandlerFactory invocationHandler = myInvocationHandlers.get(theClientType);
|
||||
if (invocationHandler == null) {
|
||||
HttpClient httpClient = getHttpClient();
|
||||
IHttpClient httpClient = getHttpClient(theServerBase);
|
||||
invocationHandler = new ClientInvocationHandlerFactory(httpClient, myContext, theServerBase, theClientType);
|
||||
for (Method nextMethod : theClientType.getMethods()) {
|
||||
BaseMethodBinding<?> binding = BaseMethodBinding.bindMethod(nextMethod, myContext, null);
|
||||
|
@ -205,14 +170,12 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
|
||||
@Override
|
||||
public synchronized IGenericClient newGenericClient(String theServerBase) {
|
||||
HttpClient httpClient = getHttpClient();
|
||||
IHttpClient httpClient = getHttpClient(theServerBase);
|
||||
return new GenericClient(myContext, httpClient, theServerBase, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is internal to HAPI - It may change in future versions, use with caution.
|
||||
*/
|
||||
public void validateServerBaseIfConfiguredToDoSo(String theServerBase, HttpClient theHttpClient, BaseClient theClient) {
|
||||
@Override
|
||||
public void validateServerBaseIfConfiguredToDoSo(String theServerBase, IHttpClient theHttpClient, BaseClient theClient) {
|
||||
String serverBase = normalizeBaseUrlForMap(theServerBase);
|
||||
|
||||
switch (myServerValidationMode) {
|
||||
|
@ -238,13 +201,13 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
@Override
|
||||
public synchronized void setConnectionRequestTimeout(int theConnectionRequestTimeout) {
|
||||
myConnectionRequestTimeout = theConnectionRequestTimeout;
|
||||
myHttpClient = null;
|
||||
resetHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setConnectTimeout(int theConnectTimeout) {
|
||||
myConnectTimeout = theConnectTimeout;
|
||||
myHttpClient = null;
|
||||
resetHttpClient();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,24 +221,11 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the Apache HTTP client instance to be used by any new restful clients created by this factory. If set to
|
||||
* <code>null</code>, which is the default, a new HTTP client with default settings will be created.
|
||||
*
|
||||
* @param theHttpClient
|
||||
* An HTTP client instance to use, or <code>null</code>
|
||||
* Return the fhir context
|
||||
* @return the fhir context
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setHttpClient(HttpClient theHttpClient) {
|
||||
myHttpClient = theHttpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProxy(String theHost, Integer thePort) {
|
||||
if (theHost != null) {
|
||||
myProxy = new HttpHost(theHost, thePort, "http");
|
||||
} else {
|
||||
myProxy = null;
|
||||
}
|
||||
public FhirContext getFhirContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -287,24 +237,39 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
@Override
|
||||
public synchronized void setSocketTimeout(int theSocketTimeout) {
|
||||
mySocketTimeout = theSocketTimeout;
|
||||
myHttpClient = null;
|
||||
resetHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setPoolMaxTotal(int thePoolMaxTotal) {
|
||||
myPoolMaxTotal = thePoolMaxTotal;
|
||||
myHttpClient = null;
|
||||
resetHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setPoolMaxPerRoute(int thePoolMaxPerRoute) {
|
||||
myPoolMaxPerRoute = thePoolMaxPerRoute;
|
||||
myHttpClient = null;
|
||||
resetHttpClient();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void validateServerBase(String theServerBase, HttpClient theHttpClient, BaseClient theClient) {
|
||||
/**
|
||||
* Instantiates a new client invocation handler
|
||||
* @param theClient
|
||||
* the client which will invoke the call
|
||||
* @param theUrlBase
|
||||
* the url base
|
||||
* @param theMethodToReturnValue
|
||||
* @param theBindings
|
||||
* @param theMethodToLambda
|
||||
* @return a newly created client invocation handler
|
||||
*/
|
||||
ClientInvocationHandler newInvocationHandler(IHttpClient theClient, String theUrlBase, Map<Method, Object> theMethodToReturnValue, Map<Method, BaseMethodBinding<?>> theBindings, Map<Method, ClientInvocationHandlerFactory.ILambda> theMethodToLambda) {
|
||||
return new ClientInvocationHandler(theClient, getFhirContext(), theUrlBase.toString(), theMethodToReturnValue,
|
||||
theBindings, theMethodToLambda, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateServerBase(String theServerBase, IHttpClient theHttpClient, BaseClient theClient) {
|
||||
GenericClient client = new GenericClient(myContext, theHttpClient, theServerBase, this);
|
||||
client.setEncoding(theClient.getEncoding());
|
||||
for (IClientInterceptor interceptor : theClient.getInterceptors()) {
|
||||
|
@ -364,4 +329,17 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
setServerValidationMode(theServerValidationMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the http client for the given server base
|
||||
* @param theServerBase the server base
|
||||
* @return the http client
|
||||
*/
|
||||
protected abstract IHttpClient getHttpClient(String theServerBase);
|
||||
|
||||
/**
|
||||
* Reset the http client. This method is used when parameters have been set and a
|
||||
* new http client needs to be created
|
||||
*/
|
||||
protected abstract void resetHttpClient();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
package ca.uhn.fhir.rest.client.apache;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpOptions;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.api.Header;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.util.VersionUtil;
|
||||
|
||||
/**
|
||||
* A Http Client based on Apache. This is an adapter around the class
|
||||
* {@link org.apache.http.client.HttpClient HttpClient}
|
||||
*
|
||||
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||
*/
|
||||
public class ApacheHttpClient implements IHttpClient {
|
||||
|
||||
private HttpClient myClient;
|
||||
private List<Header> myHeaders;
|
||||
private StringBuilder myUrl;
|
||||
private Map<String, List<String>> myIfNoneExistParams;
|
||||
private String myIfNoneExistString;
|
||||
private RequestTypeEnum myRequestType;
|
||||
|
||||
public ApacheHttpClient(HttpClient theClient, StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams,
|
||||
String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
this.myClient = theClient;
|
||||
this.myUrl = theUrl;
|
||||
this.myIfNoneExistParams = theIfNoneExistParams;
|
||||
this.myIfNoneExistString = theIfNoneExistString;
|
||||
this.myRequestType = theRequestType;
|
||||
this.myHeaders = theHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequest createByteRequest(String theContents, String theContentType, EncodingEnum theEncoding) {
|
||||
/*
|
||||
* We aren't using a StringEntity here because the constructors
|
||||
* supported by Android aren't available in non-Android, and vice versa.
|
||||
* Since we add the content type header manually, it makes no difference
|
||||
* which one we use anyhow.
|
||||
*/
|
||||
ByteArrayEntity entity = new ByteArrayEntity(theContents.getBytes(Constants.CHARSET_UTF8));
|
||||
ApacheHttpRequest retVal = createHttpRequest(entity);
|
||||
addHeadersToRequest(retVal, theEncoding);
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_TYPE, theContentType + Constants.HEADER_SUFFIX_CT_UTF_8);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequest createParamRequest(Map<String, List<String>> theParams, EncodingEnum theEncoding) {
|
||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
||||
for (Entry<String, List<String>> nextParam : theParams.entrySet()) {
|
||||
List<String> value = nextParam.getValue();
|
||||
for (String s : value) {
|
||||
parameters.add(new BasicNameValuePair(nextParam.getKey(), s));
|
||||
}
|
||||
}
|
||||
try {
|
||||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters, "UTF-8");
|
||||
return createHttpRequest(entity);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalErrorException("Server does not support UTF-8 (should not happen)", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequest createBinaryRequest(IBaseBinary theBinary) {
|
||||
/*
|
||||
* Note: Be careful about changing which constructor we use for
|
||||
* ByteArrayEntity, as Android's version of HTTPClient doesn't support
|
||||
* the newer ones for whatever reason.
|
||||
*/
|
||||
ByteArrayEntity entity = new ByteArrayEntity(theBinary.getContent());
|
||||
entity.setContentType(theBinary.getContentType());
|
||||
return createHttpRequest(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequest createGetRequest(EncodingEnum theEncoding) {
|
||||
ApacheHttpRequest retVal = createHttpRequest(null);
|
||||
addHeadersToRequest(retVal, theEncoding);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void addHeadersToRequest(ApacheHttpRequest theHttpRequest, EncodingEnum theEncoding) {
|
||||
if (myHeaders != null) {
|
||||
for (Header next : myHeaders) {
|
||||
theHttpRequest.addHeader(next.getName(), next.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
theHttpRequest.addHeader("User-Agent", "HAPI-FHIR/" + VersionUtil.getVersion() + " (FHIR Client)");
|
||||
theHttpRequest.addHeader("Accept-Charset", "utf-8");
|
||||
theHttpRequest.addHeader("Accept-Encoding", "gzip");
|
||||
|
||||
if (theEncoding == null) {
|
||||
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.HEADER_ACCEPT_VALUE_ALL);
|
||||
} else if (theEncoding == EncodingEnum.JSON) {
|
||||
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON);
|
||||
} else if (theEncoding == EncodingEnum.XML) {
|
||||
theHttpRequest.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML);
|
||||
}
|
||||
}
|
||||
|
||||
private ApacheHttpRequest createHttpRequest(HttpEntity theEntity) {
|
||||
HttpRequestBase request = constructRequestBase(theEntity);
|
||||
ApacheHttpRequest result = new ApacheHttpRequest(myClient, request);
|
||||
addHeaderIfNoneExist(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addHeaderIfNoneExist(IHttpRequest result) {
|
||||
if (myIfNoneExistParams != null) {
|
||||
StringBuilder b = newHeaderBuilder(myUrl);
|
||||
BaseHttpClientInvocation.appendExtraParamsWithQuestionMark(myIfNoneExistParams, b, b.indexOf("?") == -1);
|
||||
result.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
|
||||
if (myIfNoneExistString != null) {
|
||||
StringBuilder b = newHeaderBuilder(myUrl);
|
||||
b.append(b.indexOf("?") == -1 ? '?' : '&');
|
||||
b.append(myIfNoneExistString.substring(myIfNoneExistString.indexOf('?') + 1));
|
||||
result.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuilder newHeaderBuilder(StringBuilder theUrlBase) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theUrlBase);
|
||||
if (theUrlBase.length() > 0 && theUrlBase.charAt(theUrlBase.length() - 1) == '/') {
|
||||
b.deleteCharAt(b.length() - 1);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private HttpRequestBase constructRequestBase(HttpEntity theEntity) {
|
||||
String url = myUrl.toString();
|
||||
switch (myRequestType) {
|
||||
case DELETE:
|
||||
return new HttpDelete(url);
|
||||
case OPTIONS:
|
||||
return new HttpOptions(url);
|
||||
case POST:
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
httpPost.setEntity(theEntity);
|
||||
return httpPost;
|
||||
case PUT:
|
||||
HttpPut httpPut = new HttpPut(url);
|
||||
httpPut.setEntity(theEntity);
|
||||
return httpPut;
|
||||
case GET:
|
||||
default:
|
||||
return new HttpGet(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package ca.uhn.fhir.rest.client.apache;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
|
||||
/**
|
||||
* A Http Request based on Apache. This is an adapter around the class
|
||||
* {@link org.apache.http.client.methods.HttpRequestBase HttpRequestBase}
|
||||
*
|
||||
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||
*/
|
||||
public class ApacheHttpRequest implements IHttpRequest {
|
||||
|
||||
private HttpRequestBase myRequest;
|
||||
private HttpClient myClient;
|
||||
|
||||
public ApacheHttpRequest(HttpClient theClient, HttpRequestBase theApacheRequest) {
|
||||
this.myClient = theClient;
|
||||
this.myRequest = theApacheRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String theName, String theValue) {
|
||||
myRequest.addHeader(theName, theValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ApacheRequest
|
||||
* @return the ApacheRequest
|
||||
*/
|
||||
public HttpRequestBase getApacheRequest() {
|
||||
return myRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpResponse execute() throws IOException {
|
||||
return new ApacheHttpResponse(myClient.execute(myRequest));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getAllHeaders() {
|
||||
Map<String, List<String>> result = new HashMap<String, List<String>>();
|
||||
for (Header header : myRequest.getAllHeaders()) {
|
||||
if (!result.containsKey(header.getName())) {
|
||||
result.put(header.getName(), new LinkedList<String>());
|
||||
}
|
||||
result.get(header.getName()).add(header.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myRequest.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestBodyFromStream() throws IOException {
|
||||
if (myRequest instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntity entity = ((HttpEntityEnclosingRequest) myRequest).getEntity();
|
||||
if (entity.isRepeatable()) {
|
||||
return IOUtils.toString(entity.getContent());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
package ca.uhn.fhir.rest.client.apache;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.entity.ContentType;
|
||||
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
/**
|
||||
* A Http Response based on Apache. This is an adapter around the class
|
||||
* {@link org.apache.http.HttpResponse HttpResponse}
|
||||
*
|
||||
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||
*/
|
||||
public class ApacheHttpResponse implements IHttpResponse {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ApacheHttpResponse.class);
|
||||
|
||||
private boolean myEntityBuffered = false;
|
||||
private final HttpResponse myResponse;
|
||||
private byte[] myEntityBytes;
|
||||
|
||||
public ApacheHttpResponse(HttpResponse theResponse) {
|
||||
this.myResponse = theResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse getResponse() {
|
||||
return myResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatus() {
|
||||
return myResponse.getStatusLine().getStatusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
ContentType ct = ContentType.get(myResponse.getEntity());
|
||||
return ct != null ? ct.getMimeType() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getAllHeaders() {
|
||||
Map<String, List<String>> headers = new HashMap<String, List<String>>();
|
||||
if (myResponse.getAllHeaders() != null) {
|
||||
for (Header next : myResponse.getAllHeaders()) {
|
||||
String name = next.getName().toLowerCase();
|
||||
List<String> list = headers.get(name);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
headers.put(name, list);
|
||||
}
|
||||
list.add(next.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusInfo() {
|
||||
return myResponse.getStatusLine().getReasonPhrase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader createReader() throws IOException {
|
||||
HttpEntity entity = myResponse.getEntity();
|
||||
if (entity == null) {
|
||||
return new StringReader("");
|
||||
}
|
||||
Charset charset = null;
|
||||
if (entity.getContentType() != null && entity.getContentType().getElements() != null
|
||||
&& entity.getContentType().getElements().length > 0) {
|
||||
ContentType ct = ContentType.get(entity);
|
||||
charset = ct.getCharset();
|
||||
}
|
||||
if (charset == null) {
|
||||
if (Constants.STATUS_HTTP_204_NO_CONTENT != myResponse.getStatusLine().getStatusCode()) {
|
||||
ourLog.warn("Response did not specify a charset.");
|
||||
}
|
||||
charset = Charset.forName("UTF-8");
|
||||
}
|
||||
|
||||
Reader reader = new InputStreamReader(readEntity(), charset);
|
||||
return reader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream readEntity() throws IOException {
|
||||
if (this.myEntityBuffered) {
|
||||
return new ByteArrayInputStream(myEntityBytes);
|
||||
} else if (myResponse.getEntity() != null) {
|
||||
return myResponse.getEntity().getContent();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (myResponse instanceof CloseableHttpResponse) {
|
||||
try {
|
||||
((CloseableHttpResponse) myResponse).close();
|
||||
} catch (IOException e) {
|
||||
ourLog.debug("Failed to close response", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferEntitity() throws IOException {
|
||||
if (myEntityBuffered) {
|
||||
return;
|
||||
}
|
||||
InputStream respEntity = readEntity();
|
||||
if (respEntity != null) {
|
||||
this.myEntityBuffered = true;
|
||||
try {
|
||||
this.myEntityBytes = IOUtils.toByteArray(respEntity);
|
||||
} catch (IllegalStateException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
package ca.uhn.fhir.rest.client.apache;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.client.ProxyAuthenticationStrategy;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.RestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.api.Header;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
|
||||
/**
|
||||
* A Restful Factory to create clients, requests and responses based on the Apache httpclient library.
|
||||
*
|
||||
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||
*/
|
||||
public class ApacheRestfulClientFactory extends RestfulClientFactory {
|
||||
|
||||
private HttpClient myHttpClient;
|
||||
private HttpHost myProxy;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ApacheRestfulClientFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theContext
|
||||
* The context
|
||||
*/
|
||||
public ApacheRestfulClientFactory(FhirContext theContext) {
|
||||
super(theContext);
|
||||
}
|
||||
|
||||
public synchronized HttpClient getNativeHttpClient() {
|
||||
if (myHttpClient == null) {
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
connectionManager.setMaxTotal(getPoolMaxTotal());
|
||||
connectionManager.setDefaultMaxPerRoute(getPoolMaxPerRoute());
|
||||
|
||||
// @formatter:off
|
||||
RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(getSocketTimeout())
|
||||
.setConnectTimeout(getConnectTimeout()).setConnectionRequestTimeout(getConnectionRequestTimeout())
|
||||
.setStaleConnectionCheckEnabled(true).setProxy(myProxy).build();
|
||||
|
||||
HttpClientBuilder builder = HttpClients.custom().setConnectionManager(connectionManager)
|
||||
.setDefaultRequestConfig(defaultRequestConfig).disableCookieManagement();
|
||||
|
||||
if (myProxy != null && StringUtils.isNotBlank(getProxyUsername()) && StringUtils.isNotBlank(getProxyPassword())) {
|
||||
CredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||
credsProvider.setCredentials(new AuthScope(myProxy.getHostName(), myProxy.getPort()),
|
||||
new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword()));
|
||||
builder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());
|
||||
builder.setDefaultCredentialsProvider(credsProvider);
|
||||
}
|
||||
|
||||
myHttpClient = builder.build();
|
||||
// @formatter:on
|
||||
|
||||
}
|
||||
|
||||
return myHttpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpClient getHttpClient(StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams,
|
||||
String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
return new ApacheHttpClient(getNativeHttpClient(), theUrl, theIfNoneExistParams, theIfNoneExistString, theRequestType,
|
||||
theHeaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProxy(String theHost, Integer thePort) {
|
||||
if (theHost != null) {
|
||||
myProxy = new HttpHost(theHost, thePort, "http");
|
||||
} else {
|
||||
myProxy = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only allows to set an instance of type org.apache.http.client.HttpClient
|
||||
* @see ca.uhn.fhir.rest.client.IRestfulClientFactory#setHttpClient(ca.uhn.fhir.rest.client.api.IHttpClient)
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setHttpClient(Object theHttpClient) {
|
||||
this.myHttpClient = (HttpClient) theHttpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ApacheHttpClient getHttpClient(String theServerBase) {
|
||||
return new ApacheHttpClient(getNativeHttpClient(), new StringBuilder(theServerBase), null, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetHttpClient() {
|
||||
this.myHttpClient = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package ca.uhn.fhir.rest.client.interceptor;
|
||||
package ca.uhn.fhir.rest.client.apache;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -26,11 +26,12 @@ import java.util.zip.GZIPOutputStream;
|
|||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
/**
|
||||
|
@ -42,7 +43,8 @@ public class GZipContentInterceptor implements IClientInterceptor {
|
|||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(GZipContentInterceptor.class);
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequest theRequestInterface) {
|
||||
HttpRequestBase theRequest = ((ApacheHttpRequest) theRequestInterface).getApacheRequest();
|
||||
if (theRequest instanceof HttpEntityEnclosingRequest) {
|
||||
Header[] encodingHeaders = theRequest.getHeaders(Constants.HEADER_CONTENT_ENCODING);
|
||||
if (encodingHeaders == null || encodingHeaders.length == 0) {
|
||||
|
@ -69,7 +71,7 @@ public class GZipContentInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theResponse) throws IOException {
|
||||
public void interceptResponse(IHttpResponse theResponse) throws IOException {
|
||||
// nothing
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package ca.uhn.fhir.rest.client.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents an HTTP header field.
|
||||
*/
|
||||
public class Header {
|
||||
|
||||
public final String myName;
|
||||
public final String myValue;
|
||||
|
||||
public Header(String myName, String myValue) {
|
||||
this.myName = myName;
|
||||
this.myValue = myValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the Header.
|
||||
*
|
||||
* @return the name of the Header, never {@code null}
|
||||
*/
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the Header.
|
||||
*
|
||||
* @return the value of the Header, may be {@code null}
|
||||
*/
|
||||
public String getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package ca.uhn.fhir.rest.client.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
/**
|
||||
* A HTTP Client interface.
|
||||
*/
|
||||
public interface IHttpClient {
|
||||
|
||||
/**
|
||||
* Create a byte request
|
||||
* @param theContents the contents
|
||||
* @param theContentType the contentType
|
||||
* @param theEncoding the encoding
|
||||
* @return the http request to be executed
|
||||
*/
|
||||
IHttpRequest createByteRequest(String theContents, String theContentType, EncodingEnum theEncoding);
|
||||
|
||||
/**
|
||||
* Create a parameter request
|
||||
* @param theParams the parameters
|
||||
* @param theEncoding the encoding
|
||||
* @return the http request to be executed
|
||||
*/
|
||||
IHttpRequest createParamRequest(Map<String, List<String>> theParams, EncodingEnum theEncoding);
|
||||
|
||||
/**
|
||||
* Create a binary request
|
||||
* @param theBinary the binary
|
||||
* @return the http request to be executed
|
||||
*/
|
||||
IHttpRequest createBinaryRequest(IBaseBinary theBinary);
|
||||
|
||||
/**
|
||||
* Create a normal http get request
|
||||
* @param theEncoding the request encoding
|
||||
* @return the http request to be executed
|
||||
*/
|
||||
IHttpRequest createGetRequest(EncodingEnum theEncoding);
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package ca.uhn.fhir.rest.client.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http Request. Allows addition of headers and execution of the request.
|
||||
*/
|
||||
public interface IHttpRequest {
|
||||
|
||||
/**
|
||||
* Add a header to the request
|
||||
* @param theName the header name
|
||||
* @param theValue the header value
|
||||
*/
|
||||
public void addHeader(String theName, String theValue);
|
||||
|
||||
/**
|
||||
* Execute the request
|
||||
* @return the response
|
||||
* @throws IOException
|
||||
*/
|
||||
public IHttpResponse execute() throws IOException;
|
||||
|
||||
/**
|
||||
* @return all request headers in lower case
|
||||
*/
|
||||
public Map<String, List<String>> getAllHeaders();
|
||||
|
||||
/**
|
||||
* Return the requestbody as a string.
|
||||
* If this is not supported by the underlying technology, null is returned
|
||||
* @return a string representation of the request or null if not supported or empty.
|
||||
* @throws IOException
|
||||
*/
|
||||
public String getRequestBodyFromStream() throws IOException;
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package ca.uhn.fhir.rest.client.api;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An interface around the HTTP Response.
|
||||
*/
|
||||
public interface IHttpResponse {
|
||||
|
||||
/**
|
||||
* Get the status code associated with the response.
|
||||
* @return the response status code.
|
||||
*/
|
||||
public int getStatus();
|
||||
|
||||
/**
|
||||
* @return the native response, depending on the client library used
|
||||
*/
|
||||
Object getResponse();
|
||||
|
||||
/**
|
||||
* Extracts {@code Content-Type} value from the response exactly as
|
||||
* specified by the {@code Content-Type} header. Returns {@code null}
|
||||
* if not specified.
|
||||
*/
|
||||
public String getMimeType();
|
||||
|
||||
/**
|
||||
* Get map of the response headers and corresponding string values.
|
||||
* @return response headers as a map header keys and they values.
|
||||
*/
|
||||
public Map<String, List<String>> getAllHeaders();
|
||||
|
||||
/**
|
||||
* Get the response status information reason phrase associated with the response.
|
||||
* @return the reason phrase.
|
||||
*/
|
||||
public String getStatusInfo();
|
||||
|
||||
/**
|
||||
* Returna reader for the response entity
|
||||
*/
|
||||
public Reader createReader() throws IOException;
|
||||
|
||||
/**
|
||||
* Read the message entity input stream as an InputStream.
|
||||
*/
|
||||
public InputStream readEntity() throws IOException;
|
||||
|
||||
/**
|
||||
* Close the response
|
||||
*/
|
||||
public void close();
|
||||
|
||||
/**
|
||||
* Buffer the message entity data.
|
||||
* <p>
|
||||
* In case the message entity is backed by an unconsumed entity input stream,
|
||||
* all the bytes of the original entity input stream are read and stored in a
|
||||
* local buffer. The original entity input stream is consumed.
|
||||
* </p>
|
||||
* <p>
|
||||
* In case the response entity instance is not backed by an unconsumed input stream
|
||||
* an invocation of {@code bufferEntity} method is ignored and the method returns.
|
||||
* </p>
|
||||
* <p>
|
||||
* This operation is idempotent, i.e. it can be invoked multiple times with
|
||||
* the same effect which also means that calling the {@code bufferEntity()}
|
||||
* method on an already buffered (and thus closed) message instance is legal
|
||||
* and has no further effect.
|
||||
* </p>
|
||||
* <p>
|
||||
* Buffering the message entity data allows for multiple invocations of
|
||||
* {@code readEntity(...)} methods on the response instance.
|
||||
*/
|
||||
void bufferEntitity() throws IOException;
|
||||
|
||||
}
|
|
@ -21,7 +21,6 @@ package ca.uhn.fhir.rest.client.api;
|
|||
*/
|
||||
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
@ -51,7 +50,7 @@ public interface IRestfulClient {
|
|||
* Do not call this method in client code. It is a part of the internal HAPI API and
|
||||
* is subject to change!
|
||||
*/
|
||||
HttpClient getHttpClient();
|
||||
IHttpClient getHttpClient();
|
||||
|
||||
/**
|
||||
* Base URL for the server, with no trailing "/"
|
||||
|
|
|
@ -25,10 +25,10 @@ import java.io.UnsupportedEncodingException;
|
|||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class BasicAuthInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequest theRequest) {
|
||||
String authorizationUnescaped = StringUtils.defaultString(myUsername) + ":" + StringUtils.defaultString(myPassword);
|
||||
String encoded;
|
||||
try {
|
||||
|
@ -64,7 +64,7 @@ public class BasicAuthInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theResponse) throws IOException {
|
||||
public void interceptResponse(IHttpResponse theResponse) throws IOException {
|
||||
// nothing
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@ package ca.uhn.fhir.rest.client.interceptor;
|
|||
*/
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
|
||||
|
@ -71,12 +71,12 @@ public class BearerTokenAuthInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequest theRequest) {
|
||||
theRequest.addHeader(Constants.HEADER_AUTHORIZATION, (Constants.HEADER_AUTHORIZATION_VALPREFIX_BEARER + myToken));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theResponse) {
|
||||
public void interceptResponse(IHttpResponse theResponse) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
|
|
|
@ -20,10 +20,9 @@ package ca.uhn.fhir.rest.client.interceptor;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
|
||||
/**
|
||||
* Client interceptor which simply captures request and response objects and stores them so that they can be inspected after a client
|
||||
|
@ -31,8 +30,8 @@ import ca.uhn.fhir.rest.client.IClientInterceptor;
|
|||
*/
|
||||
public class CapturingInterceptor implements IClientInterceptor {
|
||||
|
||||
private HttpRequestBase myLastRequest;
|
||||
private HttpResponse myLastResponse;
|
||||
private IHttpRequest myLastRequest;
|
||||
private IHttpResponse myLastResponse;
|
||||
|
||||
/**
|
||||
* Clear the last request and response values
|
||||
|
@ -42,21 +41,21 @@ public class CapturingInterceptor implements IClientInterceptor {
|
|||
myLastResponse = null;
|
||||
}
|
||||
|
||||
public HttpRequestBase getLastRequest() {
|
||||
public IHttpRequest getLastRequest() {
|
||||
return myLastRequest;
|
||||
}
|
||||
|
||||
public HttpResponse getLastResponse() {
|
||||
public IHttpResponse getLastResponse() {
|
||||
return myLastResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequest theRequest) {
|
||||
myLastRequest = theRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theRequest) {
|
||||
public void interceptResponse(IHttpResponse theRequest) {
|
||||
myLastResponse = theRequest;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,10 +20,9 @@ package ca.uhn.fhir.rest.client.interceptor;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
/**
|
||||
|
@ -42,12 +41,12 @@ public class CookieInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequest theRequest) {
|
||||
theRequest.addHeader(Constants.HEADER_COOKIE, sessionCookie); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theResponse) {
|
||||
public void interceptResponse(IHttpResponse theResponse) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,22 +20,19 @@ package ca.uhn.fhir.rest.client.interceptor;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.entity.HttpEntityWrapper;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
public class LoggingInterceptor implements IClientInterceptor {
|
||||
|
@ -74,30 +71,22 @@ public class LoggingInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequest theRequest) {
|
||||
if (myLogRequestSummary) {
|
||||
myLog.info("Client request: {}", theRequest);
|
||||
}
|
||||
|
||||
if (myLogRequestHeaders) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int i = 0; i < theRequest.getAllHeaders().length; i++) {
|
||||
Header next = theRequest.getAllHeaders()[i];
|
||||
b.append(next.getName() + ": " + next.getValue());
|
||||
if (i + 1 < theRequest.getAllHeaders().length) {
|
||||
b.append('\n');
|
||||
}
|
||||
}
|
||||
StringBuilder b = headersToString(theRequest.getAllHeaders());
|
||||
myLog.info("Client request headers:\n{}", b.toString());
|
||||
}
|
||||
|
||||
if (myLogRequestBody) {
|
||||
if (theRequest instanceof HttpEntityEnclosingRequest) {
|
||||
HttpEntity entity = ((HttpEntityEnclosingRequest) theRequest).getEntity();
|
||||
if (entity.isRepeatable()) {
|
||||
try {
|
||||
String content = IOUtils.toString(entity.getContent());
|
||||
String content = theRequest.getRequestBodyFromStream();
|
||||
if (content != null) {
|
||||
myLog.info("Client request body:\n{}", content);
|
||||
}
|
||||
} catch (IllegalStateException e) {
|
||||
myLog.warn("Failed to replay request contents (during logging attempt, actual FHIR call did not fail)", e);
|
||||
} catch (IOException e) {
|
||||
|
@ -105,28 +94,16 @@ public class LoggingInterceptor implements IClientInterceptor {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theResponse) throws IOException {
|
||||
public void interceptResponse(IHttpResponse theResponse) throws IOException {
|
||||
if (myLogResponseSummary) {
|
||||
String message = "HTTP " + theResponse.getStatusLine().getStatusCode() + " " + theResponse.getStatusLine().getReasonPhrase();
|
||||
String message = "HTTP " + theResponse.getStatus() + " " + theResponse.getStatusInfo();
|
||||
myLog.info("Client response: {}", message);
|
||||
}
|
||||
|
||||
if (myLogResponseHeaders) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (theResponse.getAllHeaders() != null) {
|
||||
for (int i = 0; i < theResponse.getAllHeaders().length; i++) {
|
||||
Header next = theResponse.getAllHeaders()[i];
|
||||
b.append(next.getName() + ": " + next.getValue());
|
||||
if (i + 1 < theResponse.getAllHeaders().length) {
|
||||
b.append('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
StringBuilder b = headersToString(theResponse.getAllHeaders());
|
||||
// if (theResponse.getEntity() != null && theResponse.getEntity().getContentEncoding() != null) {
|
||||
// Header next = theResponse.getEntity().getContentEncoding();
|
||||
// b.append(next.getName() + ": " + next.getValue());
|
||||
|
@ -143,22 +120,45 @@ public class LoggingInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
if (myLogResponseBody) {
|
||||
HttpEntity respEntity = theResponse.getEntity();
|
||||
theResponse.bufferEntitity();
|
||||
InputStream respEntity = null;
|
||||
try {
|
||||
respEntity = theResponse.readEntity();
|
||||
if (respEntity != null) {
|
||||
final byte[] bytes;
|
||||
try {
|
||||
bytes = IOUtils.toByteArray(respEntity.getContent());
|
||||
bytes = IOUtils.toByteArray(respEntity);
|
||||
} catch (IllegalStateException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
||||
myLog.info("Client response body:\n{}", new String(bytes, "UTF-8"));
|
||||
theResponse.setEntity(new MyEntityWrapper(respEntity, bytes));
|
||||
} else {
|
||||
myLog.info("Client response body: (none)");
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(respEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuilder headersToString(Map<String, List<String>> theHeaders) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (theHeaders != null && !theHeaders.isEmpty()) {
|
||||
Iterator<String> nameEntries = theHeaders.keySet().iterator();
|
||||
while(nameEntries.hasNext()) {
|
||||
String key = nameEntries.next();
|
||||
Iterator<String> values = theHeaders.get(key).iterator();
|
||||
while(values.hasNext()) {
|
||||
String value = values.next();
|
||||
b.append(key + ": " + value);
|
||||
if (nameEntries.hasNext() || values.hasNext()) {
|
||||
b.append('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a logger to use to log messages (default is a logger with this class' name). This can be used to redirect
|
||||
|
@ -214,25 +214,4 @@ public class LoggingInterceptor implements IClientInterceptor {
|
|||
myLogResponseSummary = theValue;
|
||||
}
|
||||
|
||||
private static class MyEntityWrapper extends HttpEntityWrapper {
|
||||
|
||||
private byte[] myBytes;
|
||||
|
||||
public MyEntityWrapper(HttpEntity theWrappedEntity, byte[] theBytes) {
|
||||
super(theWrappedEntity);
|
||||
myBytes = theBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getContent() throws IOException {
|
||||
return new ByteArrayInputStream(myBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(OutputStream theOutstream) throws IOException {
|
||||
theOutstream.write(myBytes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,10 +22,9 @@ package ca.uhn.fhir.rest.client.interceptor;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
|
||||
/**
|
||||
* HTTP interceptor to be used for adding HTTP headers containing user identifying info for auditing purposes to the request
|
||||
|
@ -48,14 +47,14 @@ public class UserInfoInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequest theRequest) {
|
||||
if(myUserId != null) theRequest.addHeader(HEADER_USER_ID, myUserId);
|
||||
if(myUserName != null) theRequest.addHeader(HEADER_USER_NAME, myUserName);
|
||||
if(myAppName != null) theRequest.addHeader(HEADER_APPLICATION_NAME, myAppName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theResponse) throws IOException {
|
||||
public void interceptResponse(IHttpResponse theResponse) throws IOException {
|
||||
// nothing
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
|||
|
||||
class AddTagsMethodBinding extends BaseAddOrDeleteTagsMethodBinding {
|
||||
|
||||
public AddTagsMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider, AddTags theAnnotation) {
|
||||
super(theMethod, theConetxt, theProvider, theAnnotation.type());
|
||||
public AddTagsMethodBinding(Method theMethod, FhirContext theContext, Object theProvider, AddTags theAnnotation) {
|
||||
super(theMethod, theContext, theProvider, theAnnotation.type());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -56,8 +56,8 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
|
|||
private String myResourceName;
|
||||
private Integer myTagListParamIndex;
|
||||
|
||||
public BaseAddOrDeleteTagsMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider, Class<? extends IResource> theTypeFromMethodAnnotation) {
|
||||
super(theMethod, theConetxt, theProvider);
|
||||
public BaseAddOrDeleteTagsMethodBinding(Method theMethod, FhirContext theContext, Object theProvider, Class<? extends IResource> theTypeFromMethodAnnotation) {
|
||||
super(theMethod, theContext, theProvider);
|
||||
|
||||
if (theProvider instanceof IResourceProvider) {
|
||||
myType = ((IResourceProvider) theProvider).getResourceType();
|
||||
|
@ -69,7 +69,7 @@ abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void>
|
|||
throw new ConfigurationException("Method '" + theMethod.getName() + "' does not specify a resource type, but has an @" + IdParam.class.getSimpleName() + " parameter. Please specity a resource type in the method annotation on this method");
|
||||
}
|
||||
|
||||
myResourceName = theConetxt.getResourceDefinition(myType).getName();
|
||||
myResourceName = theContext.getResourceDefinition(myType).getName();
|
||||
|
||||
myIdParamIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
|
||||
myVersionIdParamIndex = MethodUtil.findVersionIdParameterIndex(theMethod);
|
||||
|
|
|
@ -23,19 +23,10 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.entity.AbstractHttpEntity;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
|
@ -47,10 +38,11 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
|||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
/**
|
||||
* @author James Agnew
|
||||
|
@ -63,7 +55,6 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
private final BundleTypeEnum myBundleType;
|
||||
private final String myContents;
|
||||
private boolean myContentsIsBundle;
|
||||
private final FhirContext myContext;
|
||||
private Map<String, List<String>> myIfNoneExistParams;
|
||||
private String myIfNoneExistString;
|
||||
private boolean myOmitResourceId = false;
|
||||
|
@ -74,7 +65,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
private final String myUrlPath;
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, Bundle theBundle) {
|
||||
myContext = theContext;
|
||||
super(theContext);
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = null;
|
||||
|
@ -84,8 +75,9 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
myBundleType = null;
|
||||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource,
|
||||
Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
super(theContext);
|
||||
myResource = theResource;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
|
@ -98,8 +90,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource, String theUrlPath) {
|
||||
super();
|
||||
myContext = theContext;
|
||||
super(theContext);
|
||||
myResource = theResource;
|
||||
myUrlPath = theUrlPath;
|
||||
myTagList = null;
|
||||
|
@ -109,8 +100,9 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
myBundleType = null;
|
||||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, List<? extends IBaseResource> theResources, BundleTypeEnum theBundleType) {
|
||||
myContext = theContext;
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, List<? extends IBaseResource> theResources,
|
||||
BundleTypeEnum theBundleType) {
|
||||
super(theContext);
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = null;
|
||||
|
@ -120,8 +112,9 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
myBundleType = theBundleType;
|
||||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, Map<String, List<String>> theParams,
|
||||
String... theUrlPath) {
|
||||
super(theContext);
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
|
@ -133,8 +126,9 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
myBundleType = null;
|
||||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents, boolean theIsBundle, String theUrlPath) {
|
||||
myContext = theContext;
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents, boolean theIsBundle,
|
||||
String theUrlPath) {
|
||||
super(theContext);
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = theUrlPath;
|
||||
|
@ -145,8 +139,9 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
myBundleType = null;
|
||||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents,
|
||||
Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
super(theContext);
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
|
@ -159,13 +154,12 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, TagList theTagList, String... theUrlPath) {
|
||||
super();
|
||||
super(theContext);
|
||||
if (theTagList == null) {
|
||||
throw new NullPointerException("Tag list must not be null");
|
||||
}
|
||||
|
||||
myResource = null;
|
||||
myContext = theContext;
|
||||
myTagList = theTagList;
|
||||
myResources = null;
|
||||
myBundle = null;
|
||||
|
@ -175,23 +169,8 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
}
|
||||
|
||||
private void addMatchHeaders(HttpRequestBase theHttpRequest, StringBuilder theUrlBase) {
|
||||
if (myIfNoneExistParams != null) {
|
||||
StringBuilder b = newHeaderBuilder(theUrlBase);
|
||||
appendExtraParamsWithQuestionMark(myIfNoneExistParams, b, b.indexOf("?") == -1);
|
||||
theHttpRequest.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
|
||||
if (myIfNoneExistString != null) {
|
||||
StringBuilder b = newHeaderBuilder(theUrlBase);
|
||||
b.append(b.indexOf("?") == -1 ? '?' : '&');
|
||||
b.append(myIfNoneExistString.substring(myIfNoneExistString.indexOf('?') + 1));
|
||||
theHttpRequest.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) throws DataFormatException {
|
||||
public IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) throws DataFormatException {
|
||||
StringBuilder url = new StringBuilder();
|
||||
|
||||
if (myUrlPath == null) {
|
||||
|
@ -207,43 +186,46 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, url, url.indexOf("?") == -1);
|
||||
IHttpClient httpClient = getRestfulClientFactory().getHttpClient(url, myIfNoneExistParams, myIfNoneExistString, getRequestType(), getHeaders());
|
||||
|
||||
if (myResource != null && IBaseBinary.class.isAssignableFrom(myResource.getClass())) {
|
||||
IBaseBinary binary = (IBaseBinary) myResource;
|
||||
if (isBlank(binary.getContentType()) || EncodingEnum.forContentTypeStrict(binary.getContentType()) != null) {
|
||||
ourLog.trace("Binary has Content-Type {}, encoding as a FHIR resource instead of raw", binary.getContentType());
|
||||
return httpClient.createBinaryRequest((IBaseBinary) myResource);
|
||||
} else {
|
||||
/*
|
||||
* Note: Be careful about changing which constructor we use for ByteArrayEntity,
|
||||
* as Android's version of HTTPClient doesn't support the newer ones for
|
||||
* whatever reason.
|
||||
*/
|
||||
ByteArrayEntity entity = new ByteArrayEntity(binary.getContent());
|
||||
|
||||
HttpRequestBase retVal = createRequest(url, entity);
|
||||
addMatchHeaders(retVal, url);
|
||||
super.addHeadersToRequest(retVal, null);
|
||||
if (isNotBlank(binary.getContentType())) {
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_TYPE, binary.getContentType());
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
IParser parser;
|
||||
String contentType;
|
||||
EncodingEnum encoding = null;
|
||||
encoding = theEncoding;
|
||||
|
||||
EncodingEnum encoding = theEncoding;
|
||||
if (myContents != null) {
|
||||
encoding = MethodUtil.detectEncoding(myContents);
|
||||
}
|
||||
|
||||
if (encoding == EncodingEnum.JSON) {
|
||||
parser = myContext.newJsonParser();
|
||||
} else {
|
||||
if (encoding == null) {
|
||||
encoding = EncodingEnum.XML;
|
||||
parser = myContext.newXmlParser();
|
||||
}
|
||||
|
||||
if (myParams != null) {
|
||||
return httpClient.createParamRequest(myParams, encoding);
|
||||
} else {
|
||||
String contents = parseContents(thePrettyPrint, encoding);
|
||||
String contentType = getContentType(encoding);
|
||||
return httpClient.createByteRequest(contents, contentType, encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getContentType(EncodingEnum encoding) {
|
||||
if (myBundle != null || (getFhirContext().getVersion().getVersion() == FhirVersionEnum.DSTU1
|
||||
&& ((myContents != null && myContentsIsBundle) || myResources != null))) {
|
||||
return encoding.getBundleContentType();
|
||||
} else {
|
||||
return encoding.getResourceContentType();
|
||||
}
|
||||
}
|
||||
|
||||
private String parseContents(Boolean thePrettyPrint, EncodingEnum encoding) {
|
||||
IParser parser;
|
||||
|
||||
if (encoding == EncodingEnum.JSON) {
|
||||
parser = getFhirContext().newJsonParser();
|
||||
} else {
|
||||
parser = getFhirContext().newXmlParser();
|
||||
}
|
||||
|
||||
if (thePrettyPrint != null) {
|
||||
|
@ -251,84 +233,27 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
|
||||
parser.setOmitResourceId(myOmitResourceId);
|
||||
|
||||
AbstractHttpEntity entity;
|
||||
if (myParams != null) {
|
||||
contentType = null;
|
||||
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
|
||||
for (Entry<String, List<String>> nextParam : myParams.entrySet()) {
|
||||
List<String> value = nextParam.getValue();
|
||||
for (String s : value) {
|
||||
parameters.add(new BasicNameValuePair(nextParam.getKey(), s));
|
||||
}
|
||||
}
|
||||
try {
|
||||
entity = new UrlEncodedFormEntity(parameters, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalErrorException("Server does not support UTF-8 (should not happen)", e);
|
||||
}
|
||||
} else {
|
||||
String contents;
|
||||
if (myTagList != null) {
|
||||
contents = parser.encodeTagListToString(myTagList);
|
||||
contentType = encoding.getResourceContentType();
|
||||
return parser.encodeTagListToString(myTagList);
|
||||
} else if (myBundle != null) {
|
||||
contents = parser.encodeBundleToString(myBundle);
|
||||
contentType = encoding.getBundleContentType();
|
||||
return parser.encodeBundleToString(myBundle);
|
||||
} else if (myResources != null) {
|
||||
IVersionSpecificBundleFactory bundleFactory = myContext.newBundleFactory();
|
||||
IVersionSpecificBundleFactory bundleFactory = getFhirContext().newBundleFactory();
|
||||
bundleFactory.initializeBundleFromResourceList("", myResources, "", "", myResources.size(), myBundleType);
|
||||
Bundle bundle = bundleFactory.getDstu1Bundle();
|
||||
if (bundle != null) {
|
||||
contents = parser.encodeBundleToString(bundle);
|
||||
contentType = encoding.getBundleContentType();
|
||||
return parser.encodeBundleToString(bundle);
|
||||
} else {
|
||||
IBaseResource bundleRes = bundleFactory.getResourceBundle();
|
||||
contents = parser.encodeResourceToString(bundleRes);
|
||||
contentType = encoding.getResourceContentType();
|
||||
return parser.encodeResourceToString(bundleRes);
|
||||
}
|
||||
} else if (myContents != null) {
|
||||
contents = myContents;
|
||||
if (myContentsIsBundle && myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
contentType = encoding.getBundleContentType();
|
||||
return myContents;
|
||||
} else {
|
||||
contentType = encoding.getResourceContentType();
|
||||
return parser.encodeResourceToString(myResource);
|
||||
}
|
||||
} else {
|
||||
contents = parser.encodeResourceToString(myResource);
|
||||
contentType = encoding.getResourceContentType();
|
||||
}
|
||||
|
||||
/*
|
||||
* We aren't using a StringEntity here because the constructors supported by
|
||||
* Android aren't available in non-Android, and vice versa. Since we add the
|
||||
* content type header manually, it makes no difference which one
|
||||
* we use anyhow.
|
||||
*/
|
||||
entity = new ByteArrayEntity(contents.getBytes(Constants.CHARSET_UTF8));
|
||||
}
|
||||
|
||||
HttpRequestBase retVal = createRequest(url, entity);
|
||||
super.addHeadersToRequest(retVal, encoding);
|
||||
addMatchHeaders(retVal, url);
|
||||
|
||||
if (contentType != null) {
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_TYPE, contentType + Constants.HEADER_SUFFIX_CT_UTF_8);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected abstract HttpRequestBase createRequest(StringBuilder theUrl, AbstractHttpEntity theEntity);
|
||||
|
||||
private StringBuilder newHeaderBuilder(StringBuilder theUrlBase) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theUrlBase);
|
||||
if (theUrlBase.length() > 0 && theUrlBase.charAt(theUrlBase.length() - 1) == '/') {
|
||||
b.deleteCharAt(b.length() - 1);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
public void setIfNoneExistParams(Map<String, List<String>> theIfNoneExist) {
|
||||
myIfNoneExistParams = theIfNoneExist;
|
||||
}
|
||||
|
@ -341,4 +266,9 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
myOmitResourceId = theOmitResourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP request type.
|
||||
*/
|
||||
protected abstract RequestTypeEnum getRequestType();
|
||||
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ public class ConformanceMethodBinding extends BaseResourceReturningMethodBinding
|
|||
|
||||
@Override
|
||||
public HttpGetClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
|
||||
HttpGetClientInvocation retVal = MethodUtil.createConformanceInvocation();
|
||||
HttpGetClientInvocation retVal = MethodUtil.createConformanceInvocation(getContext());
|
||||
|
||||
if (theArgs != null) {
|
||||
for (int idx = 0; idx < theArgs.length; idx++) {
|
||||
|
|
|
@ -119,7 +119,7 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
|
|||
throw new InvalidRequestException("ID parameter has the wrong resource type, expected '" + getResourceName() + "', found: " + idDt.getResourceType());
|
||||
}
|
||||
|
||||
HttpDeleteClientInvocation retVal = createDeleteInvocation(idDt);
|
||||
HttpDeleteClientInvocation retVal = createDeleteInvocation(getContext(), idDt);
|
||||
|
||||
for (int idx = 0; idx < theArgs.length; idx++) {
|
||||
IParameter nextParam = getParameters().get(idx);
|
||||
|
@ -129,8 +129,8 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(IIdType theId) {
|
||||
HttpDeleteClientInvocation retVal = new HttpDeleteClientInvocation(theId);
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(FhirContext theContext, IIdType theId) {
|
||||
HttpDeleteClientInvocation retVal = new HttpDeleteClientInvocation(theContext, theId);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -144,13 +144,13 @@ public class DeleteMethodBinding extends BaseOutcomeReturningMethodBinding {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(String theSearchUrl) {
|
||||
HttpDeleteClientInvocation retVal = new HttpDeleteClientInvocation(theSearchUrl);
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(FhirContext theContext, String theSearchUrl) {
|
||||
HttpDeleteClientInvocation retVal = new HttpDeleteClientInvocation(theContext, theSearchUrl);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(String theResourceType, Map<String, List<String>> theParams) {
|
||||
return new HttpDeleteClientInvocation(theResourceType, theParams);
|
||||
public static HttpDeleteClientInvocation createDeleteInvocation(FhirContext theContext, String theResourceType, Map<String, List<String>> theParams) {
|
||||
return new HttpDeleteClientInvocation(theContext, theResourceType, theParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
|||
|
||||
public class DeleteTagsMethodBinding extends BaseAddOrDeleteTagsMethodBinding {
|
||||
|
||||
public DeleteTagsMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider, DeleteTags theDeleteTags) {
|
||||
super(theMethod, theConetxt, theProvider, theDeleteTags.type());
|
||||
public DeleteTagsMethodBinding(Method theMethod, FhirContext theContext, Object theProvider, DeleteTags theDeleteTags) {
|
||||
super(theMethod, theContext, theProvider, theDeleteTags.type());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -48,8 +48,8 @@ public class DynamicSearchMethodBinding extends BaseResourceReturningMethodBindi
|
|||
private HashSet<String> myParamNames;
|
||||
private Integer myIdParamIndex;
|
||||
|
||||
public DynamicSearchMethodBinding(Class<? extends IBaseResource> theReturnResourceType, Method theMethod, FhirContext theConetxt, IDynamicSearchResourceProvider theProvider) {
|
||||
super(theReturnResourceType, theMethod, theConetxt, theProvider);
|
||||
public DynamicSearchMethodBinding(Class<? extends IBaseResource> theReturnResourceType, Method theMethod, FhirContext theContext, IDynamicSearchResourceProvider theProvider) {
|
||||
super(theReturnResourceType, theMethod, theContext, theProvider);
|
||||
|
||||
myProvider = theProvider;
|
||||
mySearchParameters = myProvider.getSearchParameters();
|
||||
|
|
|
@ -54,8 +54,8 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
|||
private Class<? extends IBaseResource> myType;
|
||||
private Integer myVersionIdParamIndex;
|
||||
|
||||
public GetTagsMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider, GetTags theAnnotation) {
|
||||
super(theMethod, theConetxt, theProvider);
|
||||
public GetTagsMethodBinding(Method theMethod, FhirContext theContext, Object theProvider, GetTags theAnnotation) {
|
||||
super(theMethod, theContext, theProvider);
|
||||
|
||||
if (theProvider instanceof IResourceProvider) {
|
||||
myType = ((IResourceProvider) theProvider).getResourceType();
|
||||
|
@ -64,7 +64,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
|||
}
|
||||
|
||||
if (!Modifier.isInterface(myType.getModifiers())) {
|
||||
myResourceName = theConetxt.getResourceDefinition(myType).getName();
|
||||
myResourceName = theContext.getResourceDefinition(myType).getName();
|
||||
}
|
||||
|
||||
myIdParamIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
|
||||
|
@ -127,17 +127,17 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
|||
if (myType != IResource.class) {
|
||||
if (id != null) {
|
||||
if (versionId != null) {
|
||||
retVal = new HttpGetClientInvocation(getResourceName(), id.getIdPart(), Constants.PARAM_HISTORY, versionId.getValue(), Constants.PARAM_TAGS);
|
||||
retVal = new HttpGetClientInvocation(getContext(), getResourceName(), id.getIdPart(), Constants.PARAM_HISTORY, versionId.getValue(), Constants.PARAM_TAGS);
|
||||
} else if (id.hasVersionIdPart()) {
|
||||
retVal = new HttpGetClientInvocation(getResourceName(), id.getIdPart(), Constants.PARAM_HISTORY, id.getVersionIdPart(), Constants.PARAM_TAGS);
|
||||
retVal = new HttpGetClientInvocation(getContext(), getResourceName(), id.getIdPart(), Constants.PARAM_HISTORY, id.getVersionIdPart(), Constants.PARAM_TAGS);
|
||||
} else {
|
||||
retVal = new HttpGetClientInvocation(getResourceName(), id.getIdPart(), Constants.PARAM_TAGS);
|
||||
retVal = new HttpGetClientInvocation(getContext(), getResourceName(), id.getIdPart(), Constants.PARAM_TAGS);
|
||||
}
|
||||
} else {
|
||||
retVal = new HttpGetClientInvocation(getResourceName(), Constants.PARAM_TAGS);
|
||||
retVal = new HttpGetClientInvocation(getContext(), getResourceName(), Constants.PARAM_TAGS);
|
||||
}
|
||||
} else {
|
||||
retVal = new HttpGetClientInvocation(Constants.PARAM_TAGS);
|
||||
retVal = new HttpGetClientInvocation(getContext(), Constants.PARAM_TAGS);
|
||||
}
|
||||
|
||||
if (theArgs != null) {
|
||||
|
|
|
@ -53,8 +53,8 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
private String myResourceName;
|
||||
private final RestOperationTypeEnum myResourceOperationType;
|
||||
|
||||
public HistoryMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider) {
|
||||
super(toReturnType(theMethod, theProvider), theMethod, theConetxt, theProvider);
|
||||
public HistoryMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
super(toReturnType(theMethod, theProvider), theMethod, theContext, theProvider);
|
||||
|
||||
myIdParamIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
|
||||
|
||||
|
@ -80,7 +80,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
if (type != IResource.class) {
|
||||
myResourceName = theConetxt.getResourceDefinition(type).getName();
|
||||
myResourceName = theContext.getResourceDefinition(type).getName();
|
||||
} else {
|
||||
myResourceName = null;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
|
||||
String historyId = id != null ? id.getIdPart() : null;
|
||||
HttpGetClientInvocation retVal = createHistoryInvocation(resourceName, historyId, null, null);
|
||||
HttpGetClientInvocation retVal = createHistoryInvocation(getContext(), resourceName, historyId, null, null);
|
||||
|
||||
if (theArgs != null) {
|
||||
for (int idx = 0; idx < theArgs.length; idx++) {
|
||||
|
@ -206,7 +206,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
};
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createHistoryInvocation(String theResourceName, String theId, IPrimitiveType<Date> theSince, Integer theLimit) {
|
||||
public static HttpGetClientInvocation createHistoryInvocation(FhirContext theContext, String theResourceName, String theId, IPrimitiveType<Date> theSince, Integer theLimit) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (theResourceName != null) {
|
||||
b.append(theResourceName);
|
||||
|
@ -230,7 +230,7 @@ public class HistoryMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
b.append(Constants.PARAM_COUNT).append('=').append(theLimit);
|
||||
}
|
||||
|
||||
HttpGetClientInvocation retVal = new HttpGetClientInvocation(b.toString());
|
||||
HttpGetClientInvocation retVal = new HttpGetClientInvocation(theContext, b.toString());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,12 @@ package ca.uhn.fhir.rest.method;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
public class HttpDeleteClientInvocation extends BaseHttpClientInvocation {
|
||||
|
@ -35,22 +36,24 @@ public class HttpDeleteClientInvocation extends BaseHttpClientInvocation {
|
|||
private String myUrlPath;
|
||||
private Map<String, List<String>> myParams;
|
||||
|
||||
public HttpDeleteClientInvocation(IIdType theId) {
|
||||
super();
|
||||
public HttpDeleteClientInvocation(FhirContext theContext, IIdType theId) {
|
||||
super(theContext);
|
||||
myUrlPath = theId.toUnqualifiedVersionless().getValue();
|
||||
}
|
||||
|
||||
public HttpDeleteClientInvocation(String theSearchUrl) {
|
||||
public HttpDeleteClientInvocation(FhirContext theContext, String theSearchUrl) {
|
||||
super(theContext);
|
||||
myUrlPath = theSearchUrl;
|
||||
}
|
||||
|
||||
public HttpDeleteClientInvocation(String theResourceType, Map<String, List<String>> theParams) {
|
||||
public HttpDeleteClientInvocation(FhirContext theContext, String theResourceType, Map<String, List<String>> theParams) {
|
||||
super(theContext);
|
||||
myUrlPath = theResourceType;
|
||||
myParams = theParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
|
||||
public IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theUrlBase);
|
||||
if (!theUrlBase.endsWith("/")) {
|
||||
|
@ -61,9 +64,7 @@ public class HttpDeleteClientInvocation extends BaseHttpClientInvocation {
|
|||
appendExtraParamsWithQuestionMark(myParams, b, b.indexOf("?") == -1);
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, b, b.indexOf("?") == -1);
|
||||
|
||||
HttpDelete retVal = new HttpDelete(b.toString());
|
||||
super.addHeadersToRequest(retVal, theEncoding);
|
||||
return retVal;
|
||||
return createHttpRequest(b.toString(), theEncoding, RequestTypeEnum.DELETE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,10 +28,12 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
/**
|
||||
|
@ -43,28 +45,33 @@ public class HttpGetClientInvocation extends BaseHttpClientInvocation {
|
|||
private final Map<String, List<String>> myParameters;
|
||||
private final String myUrlPath;
|
||||
|
||||
public HttpGetClientInvocation(Map<String, List<String>> theParameters, String... theUrlFragments) {
|
||||
public HttpGetClientInvocation(FhirContext theContext, Map<String, List<String>> theParameters, String... theUrlFragments) {
|
||||
super(theContext);
|
||||
myParameters = theParameters;
|
||||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
||||
public HttpGetClientInvocation(Map<String, List<String>> theParameters, List<String> theUrlFragments) {
|
||||
public HttpGetClientInvocation(FhirContext theContext, Map<String, List<String>> theParameters, List<String> theUrlFragments) {
|
||||
super(theContext);
|
||||
myParameters = theParameters;
|
||||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
||||
public HttpGetClientInvocation(String theUrlPath) {
|
||||
public HttpGetClientInvocation(FhirContext theContext, String theUrlPath) {
|
||||
super(theContext);
|
||||
myParameters = new HashMap<String, List<String>>();
|
||||
myUrlPath = theUrlPath;
|
||||
}
|
||||
|
||||
public HttpGetClientInvocation(String... theUrlFragments) {
|
||||
public HttpGetClientInvocation(FhirContext theContext, String... theUrlFragments) {
|
||||
super(theContext);
|
||||
myParameters = new HashMap<String, List<String>>();
|
||||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
||||
|
||||
public HttpGetClientInvocation(List<String> theUrlFragments) {
|
||||
public HttpGetClientInvocation(FhirContext theContext, List<String> theUrlFragments) {
|
||||
super(theContext);
|
||||
myParameters = new HashMap<String, List<String>>();
|
||||
myUrlPath = StringUtils.join(theUrlFragments, '/');
|
||||
}
|
||||
|
@ -78,7 +85,7 @@ public class HttpGetClientInvocation extends BaseHttpClientInvocation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public HttpGet asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
|
||||
public IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
||||
if (!myUrlPath.contains("://")) {
|
||||
|
@ -102,10 +109,7 @@ public class HttpGetClientInvocation extends BaseHttpClientInvocation {
|
|||
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, b, first);
|
||||
|
||||
HttpGet retVal = new HttpGet(b.toString());
|
||||
super.addHeadersToRequest(retVal, theEncoding);
|
||||
|
||||
return retVal;
|
||||
return super.createHttpRequest(b.toString(), theEncoding, RequestTypeEnum.GET);
|
||||
}
|
||||
|
||||
private boolean addQueryParameter(StringBuilder b, boolean first, String nextKey, String nextValue) {
|
||||
|
|
|
@ -23,14 +23,13 @@ package ca.uhn.fhir.rest.method;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.AbstractHttpEntity;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
|
||||
public class HttpPostClientInvocation extends BaseHttpClientInvocationWithContents {
|
||||
|
||||
|
@ -63,11 +62,8 @@ public class HttpPostClientInvocation extends BaseHttpClientInvocationWithConten
|
|||
super(theContext, theParams, theUrlExtension);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpPost createRequest(StringBuilder theUrlBase, AbstractHttpEntity theEntity) {
|
||||
HttpPost retVal = new HttpPost(theUrlBase.toString());
|
||||
retVal.setEntity(theEntity);
|
||||
return retVal;
|
||||
protected RequestTypeEnum getRequestType() {
|
||||
return RequestTypeEnum.POST;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,12 +20,10 @@ package ca.uhn.fhir.rest.method;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.entity.AbstractHttpEntity;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
|
||||
public class HttpPutClientInvocation extends BaseHttpClientInvocationWithContents {
|
||||
|
||||
|
@ -38,10 +36,8 @@ public class HttpPutClientInvocation extends BaseHttpClientInvocationWithContent
|
|||
}
|
||||
|
||||
@Override
|
||||
protected HttpRequestBase createRequest(StringBuilder theUrl, AbstractHttpEntity theEntity) {
|
||||
HttpPut retVal = new HttpPut(theUrl.toString());
|
||||
retVal.setEntity(theEntity);
|
||||
return retVal;
|
||||
protected RequestTypeEnum getRequestType() {
|
||||
return RequestTypeEnum.PUT;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,25 +23,24 @@ package ca.uhn.fhir.rest.method;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
public class HttpSimpleGetClientInvocation extends BaseHttpClientInvocation {
|
||||
|
||||
private final String myUrl;
|
||||
|
||||
public HttpSimpleGetClientInvocation(String theUrlPath) {
|
||||
public HttpSimpleGetClientInvocation(FhirContext theContext, String theUrlPath) {
|
||||
super(theContext);
|
||||
myUrl = theUrlPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
|
||||
HttpGet retVal = new HttpGet(myUrl);
|
||||
super.addHeadersToRequest(retVal, theEncoding);
|
||||
return retVal;
|
||||
public IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
|
||||
return createHttpRequest(myUrl, theEncoding, RequestTypeEnum.GET);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.utils.DateUtils;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -89,6 +88,7 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IDynamicSearchResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.SearchParameterMap;
|
||||
import ca.uhn.fhir.util.DateUtils;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
|
||||
/*
|
||||
|
@ -146,8 +146,8 @@ public class MethodUtil {
|
|||
return value;
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createConformanceInvocation() {
|
||||
return new HttpGetClientInvocation("metadata");
|
||||
public static HttpGetClientInvocation createConformanceInvocation(FhirContext theContext) {
|
||||
return new HttpGetClientInvocation(theContext, "metadata");
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IBaseResource theResource, FhirContext theContext) {
|
||||
|
|
|
@ -358,7 +358,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
IPrimitiveType<?> primitive = (IPrimitiveType<?>) value;
|
||||
params.get(nextName).add(primitive.getValueAsString());
|
||||
}
|
||||
return new HttpGetClientInvocation(params, b.toString());
|
||||
return new HttpGetClientInvocation(theContext, params, b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -167,15 +167,15 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
|
|||
if (myVersionIdIndex == null) {
|
||||
String resourceName = getResourceName();
|
||||
if (id.hasVersionIdPart()) {
|
||||
retVal = createVReadInvocation(new IdDt(resourceName, id.getIdPart(), id.getVersionIdPart()), resourceName);
|
||||
retVal = createVReadInvocation(getContext(), new IdDt(resourceName, id.getIdPart(), id.getVersionIdPart()), resourceName);
|
||||
} else {
|
||||
retVal = createReadInvocation(id, resourceName);
|
||||
retVal = createReadInvocation(getContext(), id, resourceName);
|
||||
}
|
||||
} else {
|
||||
IdDt vid = ((IdDt) theArgs[myVersionIdIndex]);
|
||||
String resourceName = getResourceName();
|
||||
|
||||
retVal = createVReadInvocation(new IdDt(resourceName, id.getIdPart(), vid.getVersionIdPart()), resourceName);
|
||||
retVal = createVReadInvocation(getContext(), new IdDt(resourceName, id.getIdPart(), vid.getVersionIdPart()), resourceName);
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < theArgs.length; idx++) {
|
||||
|
@ -249,20 +249,20 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding implem
|
|||
return mySupportsVersion || myVersionIdIndex != null;
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createAbsoluteReadInvocation(IIdType theId) {
|
||||
return new HttpGetClientInvocation(theId.toVersionless().getValue());
|
||||
public static HttpGetClientInvocation createAbsoluteReadInvocation(FhirContext theContext, IIdType theId) {
|
||||
return new HttpGetClientInvocation(theContext, theId.toVersionless().getValue());
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createAbsoluteVReadInvocation(IIdType theId) {
|
||||
return new HttpGetClientInvocation(theId.getValue());
|
||||
public static HttpGetClientInvocation createAbsoluteVReadInvocation(FhirContext theContext, IIdType theId) {
|
||||
return new HttpGetClientInvocation(theContext, theId.getValue());
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createReadInvocation(IIdType theId, String theResourceName) {
|
||||
return new HttpGetClientInvocation(new IdDt(theResourceName, theId.getIdPart()).getValue());
|
||||
public static HttpGetClientInvocation createReadInvocation(FhirContext theContext, IIdType theId, String theResourceName) {
|
||||
return new HttpGetClientInvocation(theContext, new IdDt(theResourceName, theId.getIdPart()).getValue());
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createVReadInvocation(IIdType theId, String theResourceName) {
|
||||
return new HttpGetClientInvocation(new IdDt(theResourceName, theId.getIdPart(), theId.getVersionIdPart()).getValue());
|
||||
public static HttpGetClientInvocation createVReadInvocation(FhirContext theContext, IIdType theId, String theResourceName) {
|
||||
return new HttpGetClientInvocation(theContext, new IdDt(theResourceName, theId.getIdPart(), theId.getVersionIdPart()).getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -274,4 +275,9 @@ public abstract class RequestDetails {
|
|||
mySecondaryOperation = theSecondaryOperation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the charset as defined by the header contenttype. Return null if it is not set.
|
||||
*/
|
||||
public abstract Charset getCharset();
|
||||
|
||||
}
|
||||
|
|
|
@ -340,16 +340,16 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
case GET:
|
||||
default:
|
||||
if (compartmentSearch) {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName, theId.getIdPart(), theCompartmentName);
|
||||
invocation = new HttpGetClientInvocation(theContext, theParameters, theResourceName, theId.getIdPart(), theCompartmentName);
|
||||
} else {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName);
|
||||
invocation = new HttpGetClientInvocation(theContext, theParameters, theResourceName);
|
||||
}
|
||||
break;
|
||||
case GET_WITH_SEARCH:
|
||||
if (compartmentSearch) {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName, theId.getIdPart(), theCompartmentName, Constants.PARAM_SEARCH);
|
||||
invocation = new HttpGetClientInvocation(theContext, theParameters, theResourceName, theId.getIdPart(), theCompartmentName, Constants.PARAM_SEARCH);
|
||||
} else {
|
||||
invocation = new HttpGetClientInvocation(theParameters, theResourceName, Constants.PARAM_SEARCH);
|
||||
invocation = new HttpGetClientInvocation(theContext, theParameters, theResourceName, Constants.PARAM_SEARCH);
|
||||
}
|
||||
break;
|
||||
case POST:
|
||||
|
@ -456,8 +456,8 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
|
||||
}
|
||||
|
||||
public static BaseHttpClientInvocation createSearchInvocation(String theSearchUrl, Map<String, List<String>> theParams) {
|
||||
return new HttpGetClientInvocation(theParams, theSearchUrl);
|
||||
public static BaseHttpClientInvocation createSearchInvocation(FhirContext theContext, String theSearchUrl, Map<String, List<String>> theParams) {
|
||||
return new HttpGetClientInvocation(theContext, theParams, theSearchUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,8 +53,8 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
|
|||
private int myTransactionParamIndex;
|
||||
private ParamStyle myTransactionParamStyle;
|
||||
|
||||
public TransactionMethodBinding(Method theMethod, FhirContext theConetxt, Object theProvider) {
|
||||
super(null, theMethod, theConetxt, theProvider);
|
||||
public TransactionMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||
super(null, theMethod, theContext, theProvider);
|
||||
|
||||
myTransactionParamIndex = -1;
|
||||
int index = 0;
|
||||
|
|
|
@ -20,7 +20,6 @@ package ca.uhn.fhir.rest.param;
|
|||
* #L%
|
||||
*/
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -35,7 +34,6 @@ import java.util.Map;
|
|||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
|
@ -130,13 +128,7 @@ public class ResourceParameter implements IParameter {
|
|||
}
|
||||
|
||||
public static Charset determineRequestCharset(RequestDetails theRequest) {
|
||||
String ct = theRequest.getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
|
||||
Charset charset = null;
|
||||
if (isNotBlank(ct)) {
|
||||
ContentType parsedCt = ContentType.parse(ct);
|
||||
charset = parsedCt.getCharset();
|
||||
}
|
||||
Charset charset = theRequest.getCharset();
|
||||
if (charset == null) {
|
||||
charset = Charset.forName("UTF-8");
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ import java.util.regex.Pattern;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.utils.DateUtils;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -69,6 +68,7 @@ import ca.uhn.fhir.rest.method.RequestDetails;
|
|||
import ca.uhn.fhir.rest.method.SummaryEnumParameter;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.DateUtils;
|
||||
|
||||
public class RestfulServerUtils {
|
||||
static final Pattern ACCEPT_HEADER_PATTERN = Pattern.compile("\\s*([a-zA-Z0-9+.*/-]+)\\s*(;\\s*([a-zA-Z]+)\\s*=\\s*([a-zA-Z0-9.]+)\\s*)?(,?)");
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package ca.uhn.fhir.rest.server.servlet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -21,10 +19,13 @@ import java.io.ByteArrayInputStream;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
|
@ -37,6 +38,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.entity.ContentType;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
|
@ -176,4 +178,16 @@ public class ServletRequestDetails extends RequestDetails {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Charset getCharset() {
|
||||
String ct = getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
|
||||
Charset charset = null;
|
||||
if (isNotBlank(ct)) {
|
||||
ContentType parsedCt = ContentType.parse(ct);
|
||||
charset = parsedCt.getCharset();
|
||||
}
|
||||
return charset;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.text.ParsePosition;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* A utility class for parsing and formatting HTTP dates as used in cookies and
|
||||
* other headers. This class handles dates as defined by RFC 2616 section
|
||||
* 3.3.1 as well as some other common non-standard formats.
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
public final class DateUtils {
|
||||
|
||||
/**
|
||||
* Date format pattern used to parse HTTP date headers in RFC 1123 format.
|
||||
*/
|
||||
public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
||||
|
||||
/**
|
||||
* Date format pattern used to parse HTTP date headers in RFC 1036 format.
|
||||
*/
|
||||
public static final String PATTERN_RFC1036 = "EEE, dd-MMM-yy HH:mm:ss zzz";
|
||||
|
||||
/**
|
||||
* Date format pattern used to parse HTTP date headers in ANSI C
|
||||
* {@code asctime()} format.
|
||||
*/
|
||||
public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
|
||||
|
||||
private static final String[] DEFAULT_PATTERNS = new String[] {
|
||||
PATTERN_RFC1123,
|
||||
PATTERN_RFC1036,
|
||||
PATTERN_ASCTIME
|
||||
};
|
||||
|
||||
private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
|
||||
|
||||
public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
|
||||
|
||||
static {
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeZone(GMT);
|
||||
calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a date value. The formats used for parsing the date value are retrieved from
|
||||
* the default http params.
|
||||
*
|
||||
* @param dateValue the date value to parse
|
||||
*
|
||||
* @return the parsed date or null if input could not be parsed
|
||||
*/
|
||||
public static Date parseDate(final String dateValue) {
|
||||
return parseDate(dateValue, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the date value using the given date formats.
|
||||
*
|
||||
* @param dateValue the date value to parse
|
||||
* @param dateFormats the date formats to use
|
||||
*
|
||||
* @return the parsed date or null if input could not be parsed
|
||||
*/
|
||||
public static Date parseDate(final String dateValue, final String[] dateFormats) {
|
||||
return parseDate(dateValue, dateFormats, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the date value using the given date formats.
|
||||
*
|
||||
* @param dateValue the date value to parse
|
||||
* @param dateFormats the date formats to use
|
||||
* @param startDate During parsing, two digit years will be placed in the range
|
||||
* {@code startDate} to {@code startDate + 100 years}. This value may
|
||||
* be {@code null}. When {@code null} is given as a parameter, year
|
||||
* {@code 2000} will be used.
|
||||
*
|
||||
* @return the parsed date or null if input could not be parsed
|
||||
*/
|
||||
public static Date parseDate(
|
||||
final String dateValue,
|
||||
final String[] dateFormats,
|
||||
final Date startDate) {
|
||||
notNull(dateValue, "Date value");
|
||||
final String[] localDateFormats = dateFormats != null ? dateFormats : DEFAULT_PATTERNS;
|
||||
final Date localStartDate = startDate != null ? startDate : DEFAULT_TWO_DIGIT_YEAR_START;
|
||||
String v = dateValue;
|
||||
// trim single quotes around date if present
|
||||
// see issue #5279
|
||||
if (v.length() > 1 && v.startsWith("'") && v.endsWith("'")) {
|
||||
v = v.substring (1, v.length() - 1);
|
||||
}
|
||||
|
||||
for (final String dateFormat : localDateFormats) {
|
||||
final SimpleDateFormat dateParser = DateFormatHolder.formatFor(dateFormat);
|
||||
dateParser.set2DigitYearStart(localStartDate);
|
||||
final ParsePosition pos = new ParsePosition(0);
|
||||
final Date result = dateParser.parse(v, pos);
|
||||
if (pos.getIndex() != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given date according to the RFC 1123 pattern.
|
||||
*
|
||||
* @param date The date to format.
|
||||
* @return An RFC 1123 formatted date string.
|
||||
*
|
||||
* @see #PATTERN_RFC1123
|
||||
*/
|
||||
public static String formatDate(final Date date) {
|
||||
return formatDate(date, PATTERN_RFC1123);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given date according to the specified pattern. The pattern
|
||||
* must conform to that used by the {@link SimpleDateFormat simple date
|
||||
* format} class.
|
||||
*
|
||||
* @param date The date to format.
|
||||
* @param pattern The pattern to use for formatting the date.
|
||||
* @return A formatted date string.
|
||||
*
|
||||
* @throws IllegalArgumentException If the given date pattern is invalid.
|
||||
*
|
||||
* @see SimpleDateFormat
|
||||
*/
|
||||
public static String formatDate(final Date date, final String pattern) {
|
||||
notNull(date, "Date");
|
||||
notNull(pattern, "Pattern");
|
||||
final SimpleDateFormat formatter = DateFormatHolder.formatFor(pattern);
|
||||
return formatter.format(date);
|
||||
}
|
||||
|
||||
|
||||
public static <T> T notNull(final T argument, final String name) {
|
||||
if (argument == null) {
|
||||
throw new IllegalArgumentException(name + " may not be null");
|
||||
}
|
||||
return argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears thread-local variable containing {@link java.text.DateFormat} cache.
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
public static void clearThreadLocal() {
|
||||
DateFormatHolder.clearThreadLocal();
|
||||
}
|
||||
|
||||
/** This class should not be instantiated. */
|
||||
private DateUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory for {@link SimpleDateFormat}s. The instances are stored in a
|
||||
* threadlocal way because SimpleDateFormat is not threadsafe as noted in
|
||||
* {@link SimpleDateFormat its javadoc}.
|
||||
*
|
||||
*/
|
||||
final static class DateFormatHolder {
|
||||
|
||||
private static final ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>
|
||||
THREADLOCAL_FORMATS = new ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>() {
|
||||
|
||||
@Override
|
||||
protected SoftReference<Map<String, SimpleDateFormat>> initialValue() {
|
||||
return new SoftReference<Map<String, SimpleDateFormat>>(
|
||||
new HashMap<String, SimpleDateFormat>());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* creates a {@link SimpleDateFormat} for the requested format string.
|
||||
*
|
||||
* @param pattern
|
||||
* a non-{@code null} format String according to
|
||||
* {@link SimpleDateFormat}. The format is not checked against
|
||||
* {@code null} since all paths go through
|
||||
* {@link DateUtils}.
|
||||
* @return the requested format. This simple dateformat should not be used
|
||||
* to {@link SimpleDateFormat#applyPattern(String) apply} to a
|
||||
* different pattern.
|
||||
*/
|
||||
public static SimpleDateFormat formatFor(final String pattern) {
|
||||
final SoftReference<Map<String, SimpleDateFormat>> ref = THREADLOCAL_FORMATS.get();
|
||||
Map<String, SimpleDateFormat> formats = ref.get();
|
||||
if (formats == null) {
|
||||
formats = new HashMap<String, SimpleDateFormat>();
|
||||
THREADLOCAL_FORMATS.set(
|
||||
new SoftReference<Map<String, SimpleDateFormat>>(formats));
|
||||
}
|
||||
|
||||
SimpleDateFormat format = formats.get(pattern);
|
||||
if (format == null) {
|
||||
format = new SimpleDateFormat(pattern, Locale.US);
|
||||
format.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
formats.put(pattern, format);
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
public static void clearThreadLocal() {
|
||||
THREADLOCAL_FORMATS.remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -208,7 +208,7 @@
|
|||
<artifactItem>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli-jpaserver</artifactId>
|
||||
<version>1.4-SNAPSHOT</version>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<type>war</type>
|
||||
<overWrite>true</overWrite>
|
||||
<outputDirectory>target/classes</outputDirectory>
|
||||
|
|
|
@ -53,7 +53,7 @@ import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
|||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.interceptor.GZipContentInterceptor;
|
||||
import ca.uhn.fhir.rest.client.apache.GZipContentInterceptor;
|
||||
import ca.uhn.fhir.util.ResourceReferenceInfo;
|
||||
|
||||
public class ExampleDataUploader extends BaseCommand {
|
||||
|
|
|
@ -24,6 +24,14 @@
|
|||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- conformance profile -->
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
package ca.uhn.fhir.jaxrs.client;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.Entity;
|
||||
import javax.ws.rs.client.Invocation.Builder;
|
||||
import javax.ws.rs.core.Form;
|
||||
import javax.ws.rs.core.MultivaluedHashMap;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.api.Header;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.util.VersionUtil;
|
||||
|
||||
/**
|
||||
* A Http Request based on JaxRs. This is an adapter around the class
|
||||
* {@link javax.ws.rs.client.Client Client}
|
||||
*
|
||||
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||
*/
|
||||
public class JaxRsHttpClient implements IHttpClient {
|
||||
|
||||
private Client myClient;
|
||||
private List<Header> myHeaders;
|
||||
private StringBuilder myUrl;
|
||||
private Map<String, List<String>> myIfNoneExistParams;
|
||||
private String myIfNoneExistString;
|
||||
private RequestTypeEnum myRequestType;
|
||||
|
||||
public JaxRsHttpClient(Client theClient, StringBuilder theUrl, Map<String, List<String>> theIfNoneExistParams, String theIfNoneExistString,
|
||||
RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
this.myClient = theClient;
|
||||
this.myUrl = theUrl;
|
||||
this.myIfNoneExistParams = theIfNoneExistParams;
|
||||
this.myIfNoneExistString = theIfNoneExistString;
|
||||
this.myRequestType = theRequestType;
|
||||
this.myHeaders = theHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequest createByteRequest(String theContents, String theContentType, EncodingEnum theEncoding) {
|
||||
Entity<String> entity = Entity.entity(theContents, theContentType + Constants.HEADER_SUFFIX_CT_UTF_8);
|
||||
JaxRsHttpRequest retVal = createHttpRequest(entity);
|
||||
addHeadersToRequest(retVal, theEncoding);
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_TYPE, theContentType + Constants.HEADER_SUFFIX_CT_UTF_8);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequest createParamRequest(Map<String, List<String>> theParams, EncodingEnum theEncoding) {
|
||||
MultivaluedMap<String, String> map = new MultivaluedHashMap<String, String>();
|
||||
for (Map.Entry<String, List<String>> nextParam : theParams.entrySet()) {
|
||||
List<String> value = nextParam.getValue();
|
||||
for (String s : value) {
|
||||
map.add(nextParam.getKey(), s);
|
||||
}
|
||||
}
|
||||
Entity<Form> entity = Entity.form(map);
|
||||
JaxRsHttpRequest retVal = createHttpRequest(entity);
|
||||
// addHeadersToRequest(retVal, encoding);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequest createBinaryRequest(IBaseBinary theBinary) {
|
||||
Entity<String> entity = Entity.entity(theBinary.getContentAsBase64(), theBinary.getContentType());
|
||||
JaxRsHttpRequest retVal = createHttpRequest(entity);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequest createGetRequest(EncodingEnum theEncoding) {
|
||||
JaxRsHttpRequest result = createHttpRequest(null);
|
||||
addHeadersToRequest(result, theEncoding);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void addHeadersToRequest(JaxRsHttpRequest theHttpRequest, EncodingEnum theEncoding) {
|
||||
if (myHeaders != null) {
|
||||
for (Header next : myHeaders) {
|
||||
theHttpRequest.addHeader(next.getName(), next.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
theHttpRequest.addHeader("User-Agent", "HAPI-FHIR/" + VersionUtil.getVersion() + " (FHIR Client)");
|
||||
theHttpRequest.addHeader("Accept-Charset", "utf-8");
|
||||
|
||||
Builder request = theHttpRequest.getRequest();
|
||||
request.acceptEncoding("gzip");
|
||||
|
||||
if (theEncoding == null) {
|
||||
request.accept(Constants.HEADER_ACCEPT_VALUE_ALL);
|
||||
} else if (theEncoding == EncodingEnum.JSON) {
|
||||
request.accept(Constants.CT_FHIR_JSON);
|
||||
} else if (theEncoding == EncodingEnum.XML) {
|
||||
request.accept(Constants.CT_FHIR_XML);
|
||||
}
|
||||
}
|
||||
|
||||
private JaxRsHttpRequest createHttpRequest(Entity<?> entity) {
|
||||
Builder request = myClient.target(myUrl.toString()).request();
|
||||
JaxRsHttpRequest result = new JaxRsHttpRequest(request, myRequestType, entity);
|
||||
addHeaderIfNoneExist(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addHeaderIfNoneExist(IHttpRequest result) {
|
||||
if (myIfNoneExistParams != null) {
|
||||
StringBuilder b = newHeaderBuilder(myUrl);
|
||||
BaseHttpClientInvocation.appendExtraParamsWithQuestionMark(myIfNoneExistParams, b, b.indexOf("?") == -1);
|
||||
result.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
|
||||
if (myIfNoneExistString != null) {
|
||||
StringBuilder b = newHeaderBuilder(myUrl);
|
||||
b.append(b.indexOf("?") == -1 ? '?' : '&');
|
||||
b.append(myIfNoneExistString.substring(myIfNoneExistString.indexOf('?') + 1));
|
||||
result.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuilder newHeaderBuilder(StringBuilder theUrlBase) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(theUrlBase);
|
||||
if (theUrlBase.length() > 0 && theUrlBase.charAt(theUrlBase.length() - 1) == '/') {
|
||||
b.deleteCharAt(b.length() - 1);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package ca.uhn.fhir.jaxrs.client;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.client.Entity;
|
||||
import javax.ws.rs.client.Invocation;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
|
||||
/**
|
||||
* A Http Request based on JaxRs. This is an adapter around the class
|
||||
* {@link javax.ws.rs.client.Invocation Invocation}
|
||||
*
|
||||
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||
*/
|
||||
public class JaxRsHttpRequest implements IHttpRequest {
|
||||
|
||||
private Invocation.Builder myRequest;
|
||||
private RequestTypeEnum myRequestType;
|
||||
private Entity<?> myEntity;
|
||||
private final Map<String, List<String>> myHeaders = new HashMap<String, List<String>>();
|
||||
|
||||
public JaxRsHttpRequest(Invocation.Builder theRequest, RequestTypeEnum theRequestType, Entity<?> theEntity) {
|
||||
this.myRequest = theRequest;
|
||||
this.myRequestType = theRequestType;
|
||||
this.myEntity = theEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String theName, String theValue) {
|
||||
if (!myHeaders.containsKey(theName)) {
|
||||
myHeaders.put(theName, new LinkedList<String>());
|
||||
}
|
||||
myHeaders.get(theName).add(theValue);
|
||||
getRequest().header(theName, theValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Request
|
||||
* @return the Request
|
||||
*/
|
||||
public Invocation.Builder getRequest() {
|
||||
return myRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Request Type
|
||||
* @return the request type
|
||||
*/
|
||||
public RequestTypeEnum getRequestType() {
|
||||
return myRequestType == null ? RequestTypeEnum.GET : myRequestType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Entity
|
||||
* @return the entity
|
||||
*/
|
||||
public Entity<?> getEntity() {
|
||||
return myEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpResponse execute() {
|
||||
Invocation invocation = getRequest().build(getRequestType().name(), getEntity());
|
||||
Response response = invocation.invoke();
|
||||
return new JaxRsHttpResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getAllHeaders() {
|
||||
return this.myHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestBodyFromStream() {
|
||||
// not supported
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package ca.uhn.fhir.jaxrs.client;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
|
||||
/**
|
||||
* A Http Response based on JaxRs. This is an adapter around the class {@link javax.ws.rs.core.Response Response}
|
||||
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||
*/
|
||||
public class JaxRsHttpResponse implements IHttpResponse {
|
||||
|
||||
private final Response myResponse;
|
||||
private boolean myBufferedEntity = false;
|
||||
|
||||
public JaxRsHttpResponse(Response theResponse) {
|
||||
this.myResponse = theResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return myResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatus() {
|
||||
return myResponse.getStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
MediaType mediaType = myResponse.getMediaType();
|
||||
//Keep only type and subtype and do not include the parameters such as charset
|
||||
return new MediaType(mediaType.getType(), mediaType.getSubtype()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getAllHeaders() {
|
||||
Map<String, List<String>> theHeaders = new ConcurrentHashMap<String, List<String>>();
|
||||
for (Entry<String, List<String>> iterable_element : myResponse.getStringHeaders().entrySet()) {
|
||||
theHeaders.put(iterable_element.getKey().toLowerCase(), iterable_element.getValue());
|
||||
}
|
||||
return theHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusInfo() {
|
||||
return myResponse.getStatusInfo().getReasonPhrase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader createReader() {
|
||||
if (!myBufferedEntity && !myResponse.hasEntity()) {
|
||||
return new StringReader("");
|
||||
} else {
|
||||
return new StringReader(myResponse.readEntity(String.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream readEntity() {
|
||||
return myResponse.readEntity(java.io.InputStream.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bufferEntitity() {
|
||||
if(!myBufferedEntity && myResponse.hasEntity()) {
|
||||
myBufferedEntity = true;
|
||||
myResponse.bufferEntity();
|
||||
} else {
|
||||
myResponse.bufferEntity();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// automatically done by jax-rs
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package ca.uhn.fhir.jaxrs.client;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2016 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.RestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.api.Header;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A Restful Client Factory, based on Jax Rs
|
||||
*
|
||||
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
|
||||
*/
|
||||
public class JaxRsRestfulClientFactory extends RestfulClientFactory {
|
||||
|
||||
private Client myNativeClient;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public JaxRsRestfulClientFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param theFhirContext The context
|
||||
*/
|
||||
public JaxRsRestfulClientFactory(FhirContext theFhirContext) {
|
||||
super(theFhirContext);
|
||||
}
|
||||
|
||||
public synchronized Client getNativeClientClient() {
|
||||
if (myNativeClient == null) {
|
||||
ClientBuilder builder = ClientBuilder.newBuilder();
|
||||
myNativeClient = builder.build();
|
||||
}
|
||||
|
||||
return myNativeClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpClient getHttpClient(StringBuilder url, Map<String, List<String>> theIfNoneExistParams,
|
||||
String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
return new JaxRsHttpClient(getNativeClientClient(), url, theIfNoneExistParams, theIfNoneExistString, theRequestType,
|
||||
theHeaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProxy(String theHost, Integer thePort) {
|
||||
throw new UnsupportedOperationException("Proxies are not supported yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Only accept clients of type javax.ws.rs.client.Client
|
||||
* @param theHttpClient
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setHttpClient(Object theHttpClient) {
|
||||
this.myNativeClient = (Client) theHttpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JaxRsHttpClient getHttpClient(String theServerBase) {
|
||||
return new JaxRsHttpClient(getNativeClientClient(), new StringBuilder(theServerBase), null, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetHttpClient() {
|
||||
this.myNativeClient = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,10 +23,12 @@ package ca.uhn.fhir.jaxrs.server.util;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
@ -149,8 +151,8 @@ public class JaxRsRequest extends RequestDetails {
|
|||
}
|
||||
}
|
||||
|
||||
private String theResourceString;
|
||||
private HttpHeaders headers;
|
||||
private String myResourceString;
|
||||
private HttpHeaders myHeaders;
|
||||
private AbstractJaxRsProvider myServer;
|
||||
|
||||
/**
|
||||
|
@ -162,8 +164,8 @@ public class JaxRsRequest extends RequestDetails {
|
|||
*/
|
||||
public JaxRsRequest(AbstractJaxRsProvider server, String resourceString, RequestTypeEnum requestType,
|
||||
RestOperationTypeEnum restOperation) {
|
||||
this.headers = server.getHeaders();
|
||||
this.theResourceString = resourceString;
|
||||
this.myHeaders = server.getHeaders();
|
||||
this.myResourceString = resourceString;
|
||||
this.setRestOperationType(restOperation);
|
||||
setServer(server);
|
||||
setFhirServerBase(server.getBaseForServer());
|
||||
|
@ -192,7 +194,7 @@ public class JaxRsRequest extends RequestDetails {
|
|||
|
||||
@Override
|
||||
public List<String> getHeaders(String name) {
|
||||
List<String> requestHeader = headers.getRequestHeader(name);
|
||||
List<String> requestHeader = myHeaders.getRequestHeader(name);
|
||||
return requestHeader == null ? Collections.<String> emptyList() : requestHeader;
|
||||
}
|
||||
|
||||
|
@ -203,7 +205,7 @@ public class JaxRsRequest extends RequestDetails {
|
|||
|
||||
@Override
|
||||
protected byte[] getByteStreamRequestContents() {
|
||||
return StringUtils.defaultIfEmpty(theResourceString, "")
|
||||
return StringUtils.defaultIfEmpty(myResourceString, "")
|
||||
.getBytes(ResourceParameter.determineRequestCharset(this));
|
||||
}
|
||||
|
||||
|
@ -226,4 +228,18 @@ public class JaxRsRequest extends RequestDetails {
|
|||
// not yet implemented
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Charset getCharset() {
|
||||
String charset = null;
|
||||
|
||||
if(myHeaders.getMediaType() != null && myHeaders.getMediaType().getParameters() != null) {
|
||||
charset = myHeaders.getMediaType().getParameters().get(MediaType.CHARSET_PARAMETER);
|
||||
}
|
||||
if(charset != null) {
|
||||
return Charset.forName(charset);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import ca.uhn.fhir.jaxrs.server.test.RandomServerPortProvider;
|
|||
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsConformanceRestProvider;
|
||||
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPageProvider;
|
||||
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPatientRestProvider;
|
||||
import ca.uhn.fhir.jaxrs.client.JaxRsRestfulClientFactory;
|
||||
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -104,6 +105,7 @@ public class AbstractJaxRsResourceProviderTest {
|
|||
|
||||
jettyServer.start();
|
||||
|
||||
ourCtx.setRestfulClientFactory(new JaxRsRestfulClientFactory(ourCtx));
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
||||
serverBase = "http://localhost:" + ourPort + "/";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ca.uhn.fhir.jaxrs.server.example;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.junit.Ignore;
|
|||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jaxrs.client.JaxRsRestfulClientFactory;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
|
@ -66,6 +67,7 @@ public class JaxRsPatientProviderTest {
|
|||
//@formatter:on
|
||||
jettyServer.start();
|
||||
|
||||
ourCtx.setRestfulClientFactory(new JaxRsRestfulClientFactory(ourCtx));
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
||||
client = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort + "/");
|
||||
|
|
|
@ -24,12 +24,14 @@ import java.util.Set;
|
|||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.input.ReaderInputStream;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
|
@ -66,6 +68,7 @@ import ca.uhn.fhir.rest.annotation.RequiredParam;
|
|||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.client.apache.ApacheHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
|
||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||
|
@ -150,7 +153,7 @@ public class ClientDstu1Test {
|
|||
|
||||
MethodOutcome response = client.createPatient(patient);
|
||||
|
||||
assertEquals(interceptor.getLastRequest().getURI().toASCIIString(), "http://foo/Patient");
|
||||
assertEquals(((ApacheHttpRequest) interceptor.getLastRequest()).getApacheRequest().getURI().toASCIIString(), "http://foo/Patient");
|
||||
|
||||
assertEquals(HttpPost.class, capt.getValue().getClass());
|
||||
HttpPost post = (HttpPost) capt.getValue();
|
||||
|
|
|
@ -82,7 +82,7 @@ public class LoggingInterceptorTest {
|
|||
public boolean matches(final Object argument) {
|
||||
String formattedMessage = ((LoggingEvent) argument).getFormattedMessage();
|
||||
System.out.println("Verifying: " + formattedMessage);
|
||||
return formattedMessage.replace("; ", ";").replace("UTF", "utf").contains("Content-Type: application/xml+fhir;charset=utf-8");
|
||||
return formattedMessage.replace("; ", ";").toLowerCase().contains("Content-Type: application/xml+fhir;charset=utf-8".toLowerCase());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import ca.uhn.fhir.rest.annotation.Create;
|
|||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.apache.GZipContentInterceptor;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
|
|
|
@ -52,6 +52,8 @@ import ca.uhn.fhir.model.primitive.DecimalDt;
|
|||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.client.GenericClient;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.to.model.HomeRequest;
|
||||
|
@ -290,7 +292,7 @@ public class BaseController {
|
|||
returnsResource = ResultType.NONE;
|
||||
ourLog.warn("Failed to invoke server", e);
|
||||
|
||||
if (theClient.getLastResponse() == null) {
|
||||
if (e != null) {
|
||||
theModel.put("errorMsg", "Error: " + e.getMessage());
|
||||
}
|
||||
|
||||
|
@ -653,17 +655,17 @@ public class BaseController {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequest theRequest) {
|
||||
assert myLastRequest == null;
|
||||
myLastRequest = theRequest;
|
||||
myLastRequest = (HttpRequestBase) theRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theResponse) throws IOException {
|
||||
public void interceptResponse(IHttpResponse theResponse) throws IOException {
|
||||
assert myLastResponse == null;
|
||||
myLastResponse = theResponse;
|
||||
myLastResponse = (HttpResponse) theResponse;
|
||||
|
||||
HttpEntity respEntity = theResponse.getEntity();
|
||||
HttpEntity respEntity = myLastResponse.getEntity();
|
||||
if (respEntity != null) {
|
||||
final byte[] bytes;
|
||||
try {
|
||||
|
@ -673,7 +675,7 @@ public class BaseController {
|
|||
}
|
||||
|
||||
myResponseBody = new String(bytes, "UTF-8");
|
||||
theResponse.setEntity(new MyEntityWrapper(respEntity, bytes));
|
||||
myLastResponse.setEntity(new MyEntityWrapper(respEntity, bytes));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ import ca.uhn.fhir.rest.api.SummaryEnum;
|
|||
import ca.uhn.fhir.rest.client.GenericClient;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IncomingRequestAddressStrategy;
|
||||
import ca.uhn.fhir.to.Controller;
|
||||
|
@ -163,12 +165,12 @@ public class HomeRequest {
|
|||
retVal.registerInterceptor(new IClientInterceptor() {
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theRequest) {
|
||||
public void interceptResponse(IHttpResponse theRequest) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequest theRequest) {
|
||||
if (isNotBlank(remoteAddr)) {
|
||||
theRequest.addHeader("x-forwarded-for", remoteAddr);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue