create a jax-rs client
This commit is contained in:
parent
a54cb06c03
commit
1271c36d1b
|
@ -0,0 +1,147 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>1.4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<url>http://jamesagnew.github.io/hapi-fhir/</url>
|
||||
|
||||
<name>HAPI FHIR - Core Client</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>hapi-fhir-base-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- JSON -->
|
||||
<dependency>
|
||||
<groupId>javax.json</groupId>
|
||||
<artifactId>javax.json-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.json</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- XML -->
|
||||
<dependency>
|
||||
<groupId>org.codehaus.woodstox</groupId>
|
||||
<artifactId>woodstox-core-asl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Only required for narrative generator support -->
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Only required for CORS support -->
|
||||
<dependency>
|
||||
<groupId>org.ebaysf.web</groupId>
|
||||
<artifactId>cors-filter</artifactId>
|
||||
<optional>true</optional>
|
||||
<!-- <exclusions> <exclusion> <artifactId>servlet-api</artifactId> <groupId>javax.servlet</groupId>
|
||||
</exclusion> </exclusions> -->
|
||||
</dependency>
|
||||
|
||||
<!-- Only required for Schematron Validator Support -->
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-schematron</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.phloc</groupId>
|
||||
<artifactId>phloc-commons</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId>
|
||||
<version>2.11.0</version> <optional>true</optional> </dependency> -->
|
||||
|
||||
<!-- General -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Client -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
-->
|
||||
<!-- Server -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,205 @@
|
|||
package ca.uhn.fhir.rest.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.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.http.Header;
|
||||
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.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
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 {
|
||||
|
||||
HttpClient myClient;
|
||||
/**
|
||||
* Get the myClient
|
||||
* @return the myClient
|
||||
*/
|
||||
public HttpClient getMyClient() {
|
||||
return myClient;
|
||||
}
|
||||
|
||||
private List<Header> myHeaders;
|
||||
private StringBuilder myUrl;
|
||||
private Map<String, List<String>> myIfNoneExistParams;
|
||||
private String myIfNoneExistString;
|
||||
private RequestTypeEnum myRequestType;
|
||||
|
||||
public ApacheHttpClient(HttpClient myClient, StringBuilder url, Map<String, List<String>> myIfNoneExistParams, String myIfNoneExistString, EncodingEnum theEncoding, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
this.myHeaders = theHeaders;
|
||||
this.myClient = myClient;
|
||||
this.myUrl = url;
|
||||
this.myIfNoneExistParams = myIfNoneExistParams;
|
||||
this.myIfNoneExistString = myIfNoneExistString;
|
||||
this.myRequestType = theRequestType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequestBase createByteRequest(String contents, String contentType, EncodingEnum encoding) {
|
||||
/*
|
||||
* 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(contents.getBytes(Constants.CHARSET_UTF8));
|
||||
HttpRequestBase retVal = createRequest(myUrl, entity);
|
||||
addHeadersToRequest(retVal, encoding);
|
||||
addMatchHeaders(retVal, myUrl);
|
||||
retVal.addHeader(Constants.HEADER_CONTENT_TYPE, contentType + Constants.HEADER_SUFFIX_CT_UTF_8);
|
||||
return new ApacheHttpRequestBase(myClient, retVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequestBase createParamRequest(Map<String, List<String>> myParams, EncodingEnum encoding) {
|
||||
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 {
|
||||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters, "UTF-8");
|
||||
HttpRequestBase retVal = createRequest(myUrl, entity);
|
||||
addMatchHeaders(retVal, myUrl);
|
||||
return new ApacheHttpRequestBase(myClient, retVal);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalErrorException("Server does not support UTF-8 (should not happen)", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequestBase createBinaryRequest(IBaseBinary binary) {
|
||||
/*
|
||||
* 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());
|
||||
entity.setContentType(binary.getContentType());
|
||||
HttpRequestBase retVal = createRequest(myUrl, entity);
|
||||
addMatchHeaders(retVal, myUrl);
|
||||
return new ApacheHttpRequestBase(myClient, retVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequestBase createGetRequest(EncodingEnum theEncoding) {
|
||||
HttpRequestBase retVal = createRequest(myUrl, null);
|
||||
addHeadersToRequest(retVal, theEncoding);
|
||||
addMatchHeaders(retVal, myUrl);
|
||||
return new ApacheHttpRequestBase(myClient, retVal);
|
||||
}
|
||||
|
||||
public void addHeadersToRequest(HttpRequestBase 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 void addMatchHeaders(HttpRequestBase theHttpRequest, StringBuilder theUrlBase) {
|
||||
if (myIfNoneExistParams != null) {
|
||||
StringBuilder b = newHeaderBuilder(theUrlBase);
|
||||
BaseHttpClientInvocation.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());
|
||||
}
|
||||
}
|
||||
|
||||
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 createRequest(StringBuilder url2, HttpEntity entity) {
|
||||
String uri = url2.toString();
|
||||
switch(myRequestType) {
|
||||
case DELETE :
|
||||
return new HttpDelete(uri);
|
||||
case OPTIONS :
|
||||
return new HttpOptions(uri);
|
||||
case POST :
|
||||
HttpPost httpPost = new HttpPost(uri);
|
||||
httpPost.setEntity(entity);
|
||||
return httpPost;
|
||||
case PUT :
|
||||
HttpPut httpPut = new HttpPut(uri);
|
||||
httpPut.setEntity(entity);
|
||||
return httpPut;
|
||||
case GET :
|
||||
default:
|
||||
return new HttpGet(uri);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package ca.uhn.fhir.rest.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.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
|
||||
import ca.uhn.fhir.rest.api.IHttpRequestBase;
|
||||
|
||||
/**
|
||||
* 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 ApacheHttpRequestBase implements IHttpRequestBase {
|
||||
|
||||
private HttpRequestBase myRequest;
|
||||
private HttpClient myClient;
|
||||
|
||||
public ApacheHttpRequestBase(HttpClient theClient, HttpRequestBase theApacheRequest) {
|
||||
this.myClient = theClient;
|
||||
this.myRequest = theApacheRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String theName, String theValue) {
|
||||
getApacheRequest().addHeader(theName, theValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the myApacheRequest
|
||||
* @return the myApacheRequest
|
||||
*/
|
||||
public HttpRequestBase getApacheRequest() {
|
||||
return myRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpResponse execute() throws IOException {
|
||||
return new ApacheHttpResponse(myClient.execute(getApacheRequest()));
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
package ca.uhn.fhir.rest.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.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.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 UnsupportedOperationException, 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,147 @@
|
|||
package ca.uhn.fhir.rest.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.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Header;
|
||||
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.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
/**
|
||||
* A Restful Factory to create clients, requests and responses based on Apache.
|
||||
* @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 theFhirContext
|
||||
* The context
|
||||
*/
|
||||
public ApacheRestfulClientFactory(FhirContext theFhirContext) {
|
||||
super(theFhirContext);
|
||||
}
|
||||
|
||||
public synchronized HttpClient getNativeHttpClient() {
|
||||
if (myHttpClient == null) {
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
|
||||
//@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);
|
||||
}
|
||||
|
||||
myHttpClient = builder.build();
|
||||
//@formatter:on
|
||||
|
||||
}
|
||||
|
||||
return myHttpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientInvocationHandler newInvocationHandler(IHttpClient theClient, String myUrlBase, Map<Method, Object> myMethodToReturnValue, Map<Method, BaseMethodBinding<?>> myBindings, Map<Method, ClientInvocationHandlerFactory.ILambda> myMethodToLambda) {
|
||||
ApacheHttpClient apacheHttpClient = (ApacheHttpClient) theClient;
|
||||
return new ClientInvocationHandler(apacheHttpClient, myContext, myUrlBase.toString(), myMethodToReturnValue, myBindings, myMethodToLambda, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpClient getHttpClient(StringBuilder url, Map<String, List<String>> myIfNoneExistParams, String myIfNoneExistString,
|
||||
EncodingEnum theEncoding, RequestTypeEnum theRequestType, List<Header> myHeaders) {
|
||||
return new ApacheHttpClient(getNativeHttpClient(), url, myIfNoneExistParams, myIfNoneExistString, theEncoding, theRequestType, myHeaders);
|
||||
}
|
||||
|
||||
@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, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetHttpClient() {
|
||||
this.myHttpClient = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -26,11 +26,13 @@ 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.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.ApacheHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
/**
|
||||
|
@ -42,7 +44,9 @@ 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(IHttpRequestBase theRequestInterface) {
|
||||
HttpRequestBase theRequest = ((ApacheHttpRequestBase) theRequestInterface).getApacheRequest();
|
||||
|
||||
if (theRequest instanceof HttpEntityEnclosingRequest) {
|
||||
Header[] encodingHeaders = theRequest.getHeaders(Constants.HEADER_CONTENT_ENCODING);
|
||||
if (encodingHeaders == null || encodingHeaders.length == 0) {
|
||||
|
@ -69,7 +73,7 @@ public class GZipContentInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theResponse) throws IOException {
|
||||
public void interceptResponse(IHttpResponse theResponse) throws IOException {
|
||||
// nothing
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<artifactId>hapi-fhir-base-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<url>http://jamesagnew.github.io/hapi-fhir/</url>
|
||||
|
|
|
@ -294,9 +294,26 @@ 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. The default method will create this based upon the apache restful client factory
|
||||
* @return the factory used to create the restful clients
|
||||
*/
|
||||
public IRestfulClientFactory getRestfulClientFactory() {
|
||||
if (myRestfulClientFactory == null) {
|
||||
myRestfulClientFactory = new RestfulClientFactory(this);
|
||||
try {
|
||||
myRestfulClientFactory = (IRestfulClientFactory) Class.forName("ca.uhn.fhir.rest.client.ApacheRestfulClientFactory").getConstructor(getClass()).newInstance(this);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Could not create the RestfulClientFactory", e);
|
||||
}
|
||||
}
|
||||
return myRestfulClientFactory;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package ca.uhn.fhir.rest.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;
|
||||
|
||||
import ca.uhn.fhir.rest.client.IHttpResponse;
|
||||
|
||||
/**
|
||||
* Http Base Request. Allows addition of headers and execution of the request.
|
||||
*/
|
||||
public interface IHttpRequestBase {
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
}
|
|
@ -2,6 +2,10 @@ package ca.uhn.fhir.rest.client;
|
|||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -22,13 +26,8 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
* #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.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -40,14 +39,8 @@ 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;
|
||||
|
@ -61,7 +54,9 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.IHttpRequestBase;
|
||||
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.client.exceptions.FhirClientConnectionException;
|
||||
import ca.uhn.fhir.rest.client.exceptions.InvalidResponseException;
|
||||
|
@ -79,19 +74,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 +125,7 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public HttpClient getHttpClient() {
|
||||
public IHttpClient getHttpClient() {
|
||||
return myClient;
|
||||
}
|
||||
|
||||
|
@ -141,7 +136,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,35 +188,35 @@ 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;
|
||||
IHttpRequestBase httpRequest;
|
||||
IHttpResponse response = null;
|
||||
try {
|
||||
Map<String, List<String>> params = createExtraParams();
|
||||
Map<String, List<String>> params = createExtraParams();
|
||||
|
||||
if (theEncoding == EncodingEnum.XML) {
|
||||
params.put(Constants.PARAM_FORMAT, Collections.singletonList("xml"));
|
||||
} else if (theEncoding == EncodingEnum.JSON) {
|
||||
params.put(Constants.PARAM_FORMAT, Collections.singletonList("json"));
|
||||
}
|
||||
if (theEncoding == EncodingEnum.XML) {
|
||||
params.put(Constants.PARAM_FORMAT, Collections.singletonList("xml"));
|
||||
} else if (theEncoding == EncodingEnum.JSON) {
|
||||
params.put(Constants.PARAM_FORMAT, Collections.singletonList("json"));
|
||||
}
|
||||
|
||||
if (theSummaryMode != null) {
|
||||
params.put(Constants.PARAM_SUMMARY, Collections.singletonList(theSummaryMode.getCode()));
|
||||
} else if (mySummary != null) {
|
||||
params.put(Constants.PARAM_SUMMARY, Collections.singletonList(mySummary.getCode()));
|
||||
}
|
||||
if (theSummaryMode != null) {
|
||||
params.put(Constants.PARAM_SUMMARY, Collections.singletonList(theSummaryMode.getCode()));
|
||||
} else if (mySummary != null) {
|
||||
params.put(Constants.PARAM_SUMMARY, Collections.singletonList(mySummary.getCode()));
|
||||
}
|
||||
|
||||
if (thePrettyPrint == Boolean.TRUE) {
|
||||
params.put(Constants.PARAM_PRETTY, Collections.singletonList(Constants.PARAM_PRETTY_VALUE_TRUE));
|
||||
}
|
||||
if (thePrettyPrint == Boolean.TRUE) {
|
||||
params.put(Constants.PARAM_PRETTY, Collections.singletonList(Constants.PARAM_PRETTY_VALUE_TRUE));
|
||||
}
|
||||
|
||||
if (theSubsetElements != null && theSubsetElements.isEmpty() == false) {
|
||||
params.put(Constants.PARAM_ELEMENTS, Collections.singletonList(StringUtils.join(theSubsetElements, ',')));
|
||||
}
|
||||
if (theSubsetElements != null && theSubsetElements.isEmpty() == false) {
|
||||
params.put(Constants.PARAM_ELEMENTS, Collections.singletonList(StringUtils.join(theSubsetElements, ',')));
|
||||
}
|
||||
|
||||
EncodingEnum encoding = getEncoding();
|
||||
if (theEncoding != null) {
|
||||
encoding = theEncoding;
|
||||
}
|
||||
EncodingEnum encoding = getEncoding();
|
||||
if (theEncoding != null) {
|
||||
encoding = theEncoding;
|
||||
}
|
||||
|
||||
httpRequest = clientInvocation.asHttpRequest(myUrlBase, params, encoding, thePrettyPrint);
|
||||
|
||||
|
@ -235,50 +230,31 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (IClientInterceptor nextInterceptor : myInterceptors) {
|
||||
nextInterceptor.interceptRequest(httpRequest);
|
||||
nextInterceptor.interceptRequest(httpRequest);
|
||||
}
|
||||
|
||||
response = httpRequest.execute();
|
||||
|
||||
for (IClientInterceptor nextInterceptor : myInterceptors) {
|
||||
nextInterceptor.interceptResponse(response);
|
||||
}
|
||||
|
||||
response = myClient.execute(httpRequest);
|
||||
|
||||
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 +262,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 +285,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 +297,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 +306,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 +315,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 +331,23 @@ 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 +368,14 @@ 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 {
|
||||
|
@ -406,7 +384,7 @@ public abstract class BaseClient implements IRestfulClient {
|
|||
} else {
|
||||
ourLog.trace("FHIR response:\n{}\n{}", response, responseString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerInterceptor(IClientInterceptor theInterceptor) {
|
||||
|
@ -444,7 +422,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 +455,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);
|
||||
}
|
||||
|
|
|
@ -28,16 +28,23 @@ 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.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.util.VersionUtil;
|
||||
|
||||
public abstract class BaseHttpClientInvocation {
|
||||
|
||||
private List<Header> myHeaders;
|
||||
protected List<Header> myHeaders;
|
||||
private final FhirContext myContext;
|
||||
|
||||
public BaseHttpClientInvocation(FhirContext myContext) {
|
||||
this.myContext = myContext;
|
||||
}
|
||||
|
||||
|
||||
public void addHeader(String theName, String theValue) {
|
||||
if (myHeaders == null) {
|
||||
|
@ -57,15 +64,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 IHttpRequestBase 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,24 +93,25 @@ public abstract class BaseHttpClientInvocation {
|
|||
}
|
||||
}
|
||||
|
||||
public void addHeadersToRequest(HttpRequestBase theHttpRequest, EncodingEnum theEncoding) {
|
||||
if (myHeaders != null) {
|
||||
for (Header next : myHeaders) {
|
||||
theHttpRequest.addHeader(next);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* Get thre restful client factory
|
||||
* @return
|
||||
*/
|
||||
public IRestfulClientFactory getRestfulClientFactory() {
|
||||
return myContext.getRestfulClientFactory();
|
||||
}
|
||||
|
||||
public IHttpRequestBase createHttpRequest(String theUrl, EncodingEnum theEncoding, RequestTypeEnum theRequestType) {
|
||||
IHttpClient httpClient = getRestfulClientFactory().getHttpClient(new StringBuilder(theUrl), null, null, theEncoding, theRequestType, myHeaders);
|
||||
return httpClient.createGetRequest(theEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the myContext
|
||||
* @return the myContext
|
||||
*/
|
||||
public FhirContext getContext() {
|
||||
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,29 +24,27 @@ 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 FhirContext myContext;
|
||||
private final IHttpClient myClient;
|
||||
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;
|
||||
|
||||
try {
|
||||
myMethodToReturnValue.put(theClientType.getMethod("getFhirContext"), theContext);
|
||||
|
@ -72,10 +70,10 @@ class ClientInvocationHandlerFactory {
|
|||
}
|
||||
|
||||
ClientInvocationHandler newInvocationHandler(RestfulClientFactory theRestfulClientFactory) {
|
||||
return new ClientInvocationHandler(myClient, myContext, myUrlBase, myMethodToReturnValue, myBindings, myMethodToLambda, theRestfulClientFactory);
|
||||
return theRestfulClientFactory.newInvocationHandler(myClient, myUrlBase, myMethodToReturnValue, myBindings, myMethodToLambda);
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -69,9 +67,11 @@ import ca.uhn.fhir.model.primitive.InstantDt;
|
|||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.IHttpRequestBase;
|
||||
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.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 IHttpRequestBase 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 IHttpRequestBase 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(IHttpRequestBase 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,18 @@ 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.api.IHttpRequestBase;
|
||||
|
||||
public interface IClientInterceptor {
|
||||
|
||||
/**
|
||||
* Fired by the client just before invoking the HTTP client request
|
||||
*/
|
||||
void interceptRequest(HttpRequestBase theRequest);
|
||||
void interceptRequest(IHttpRequestBase 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;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
package ca.uhn.fhir.rest.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.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IHttpResponse {
|
||||
|
||||
/**
|
||||
* @return the response status number
|
||||
*/
|
||||
public int getStatus();
|
||||
|
||||
/**
|
||||
* @return the raw response underlying response object
|
||||
*/
|
||||
Object getResponse();
|
||||
|
||||
/**
|
||||
* @return the response mime type
|
||||
*/
|
||||
public String getMimeType();
|
||||
|
||||
/**
|
||||
* @return all the headers
|
||||
*/
|
||||
public Map<String, List<String>> getAllHeaders();
|
||||
|
||||
/**
|
||||
* @return the status info
|
||||
*/
|
||||
public String getStatusInfo();
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public Reader createReader() throws IOException;
|
||||
|
||||
/**
|
||||
* Read the entity as inputstream
|
||||
* @return the inputstream
|
||||
* @throws IOException
|
||||
*/
|
||||
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 and automatically
|
||||
* closed as part of the operation and the method returns {@code true}.
|
||||
* </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
|
||||
* {@code false}.
|
||||
* </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. Also, the result returned by the {@code bufferEntity()}
|
||||
* method is consistent across all invocations of the method on the same
|
||||
* {@code Response} instance.
|
||||
* </p>
|
||||
* <p>
|
||||
* Buffering the message entity data allows for multiple invocations of
|
||||
* {@code readEntity(...)} methods on the response instance. Note however, that
|
||||
* once the response instance itself is {@link #close() closed}, the implementations
|
||||
* are expected to release the buffered message entity data too. Therefore any subsequent
|
||||
* attempts to read a message entity stream on such closed response will result in an
|
||||
* {@link IllegalStateException} being thrown.
|
||||
* </p>
|
||||
* @throws IOException
|
||||
* @throws IllegalStateException in case the response has been {@link #close() closed}.
|
||||
*/
|
||||
void bufferEntitity() throws IOException;
|
||||
|
||||
}
|
|
@ -1,5 +1,11 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.Header;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -23,7 +29,11 @@ package ca.uhn.fhir.rest.client;
|
|||
import org.apache.http.client.HttpClient;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
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;
|
||||
|
||||
public interface IRestfulClientFactory {
|
||||
|
||||
|
@ -70,7 +80,7 @@ public interface IRestfulClientFactory {
|
|||
*
|
||||
* @see #setHttpClient(HttpClient)
|
||||
*/
|
||||
HttpClient getHttpClient();
|
||||
IHttpClient getHttpClient(StringBuilder url, Map<String, List<String>> myIfNoneExistParams, String myIfNoneExistString, EncodingEnum theEncoding, RequestTypeEnum theRequestType, List<Header> myHeaders);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getServerValidationMode()} instead
|
||||
|
@ -120,6 +130,19 @@ public interface IRestfulClientFactory {
|
|||
* @return A newly created client
|
||||
*/
|
||||
IGenericClient newGenericClient(String theServerBase);
|
||||
|
||||
/**
|
||||
* Instantiates a new client invocation handler
|
||||
* @param theClient
|
||||
* the client which will invoke the call
|
||||
* @param myUrlBase
|
||||
* the url base
|
||||
* @param myMethodToReturnValue
|
||||
* @param myBindings
|
||||
* @param myMethodToLambda
|
||||
* @return a newly created client invocation handler
|
||||
*/
|
||||
ClientInvocationHandler newInvocationHandler(IHttpClient theClient, String myUrlBase, Map<Method, Object> myMethodToReturnValue, Map<Method, BaseMethodBinding<?>> myBindings, Map<Method, ClientInvocationHandlerFactory.ILambda> myMethodToLambda);
|
||||
|
||||
/**
|
||||
* Sets the connection request timeout, in milliseconds. This is the amount of time that the HTTPClient connection
|
||||
|
@ -146,7 +169,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
|
||||
|
@ -193,4 +216,8 @@ public interface IRestfulClientFactory {
|
|||
*/
|
||||
void setSocketTimeout(int theSocketTimeout);
|
||||
|
||||
void validateServerBase(String theServerBase, IHttpClient theHttpClient, BaseClient theClient);
|
||||
|
||||
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>());
|
||||
protected int myConnectionRequestTimeout = DEFAULT_CONNECTION_REQUEST_TIMEOUT;
|
||||
protected int myConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
||||
protected FhirContext myContext;
|
||||
protected Map<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory> myInvocationHandlers = new HashMap<Class<? extends IRestfulClient>, ClientInvocationHandlerFactory>();
|
||||
protected ServerValidationModeEnum myServerValidationMode = DEFAULT_SERVER_VALIDATION_MODE;
|
||||
protected int mySocketTimeout = DEFAULT_SOCKET_TIMEOUT;
|
||||
protected Set<String> myValidatedServerBaseUrls = Collections.synchronizedSet(new HashSet<String>());
|
||||
protected String myProxyUsername;
|
||||
protected String myProxyPassword;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -95,44 +84,6 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
return myConnectTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized HttpClient getHttpClient() {
|
||||
if (myHttpClient == null) {
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
|
||||
//@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);
|
||||
}
|
||||
|
||||
myHttpClient = builder.build();
|
||||
//@formatter:on
|
||||
|
||||
}
|
||||
|
||||
return myHttpClient;
|
||||
}
|
||||
|
||||
private String myProxyUsername;
|
||||
private String myProxyPassword;
|
||||
|
||||
@Override
|
||||
public void setProxyCredentials(String theUsername, String thePassword) {
|
||||
myProxyUsername=theUsername;
|
||||
|
@ -175,7 +126,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);
|
||||
|
@ -191,14 +142,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) {
|
||||
|
@ -224,13 +173,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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -243,27 +192,6 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
myContext = theContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServerValidationMode(ServerValidationModeEnum theServerValidationMode) {
|
||||
Validate.notNull(theServerValidationMode, "theServerValidationMode may not be null");
|
||||
|
@ -273,11 +201,11 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
@Override
|
||||
public synchronized void setSocketTimeout(int theSocketTimeout) {
|
||||
mySocketTimeout = theSocketTimeout;
|
||||
myHttpClient = null;
|
||||
resetHttpClient();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void validateServerBase(String theServerBase, HttpClient theHttpClient, BaseClient theClient) {
|
||||
@Override
|
||||
public void validateServerBase(String theServerBase, IHttpClient theHttpClient, BaseClient theClient) {
|
||||
|
||||
GenericClient client = new GenericClient(myContext, theHttpClient, theServerBase, this);
|
||||
client.setEncoding(theClient.getEncoding());
|
||||
|
@ -337,5 +265,18 @@ public class RestfulClientFactory implements IRestfulClientFactory {
|
|||
public void setServerValidationModeEnum(ServerValidationModeEnum theServerValidationMode) {
|
||||
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,67 @@
|
|||
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.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
/**
|
||||
* A HTTP Client
|
||||
*/
|
||||
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
|
||||
*/
|
||||
IHttpRequestBase 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
|
||||
*/
|
||||
IHttpRequestBase createParamRequest(Map<String, List<String>> theParams, EncodingEnum theEncoding);
|
||||
|
||||
/**
|
||||
* Create a binary request
|
||||
* @param theBinary the binary
|
||||
* @return the http request to be executed
|
||||
*/
|
||||
IHttpRequestBase createBinaryRequest(IBaseBinary theBinary);
|
||||
|
||||
/**
|
||||
* Create a normal http get request
|
||||
* @param theEncoding the request encoding
|
||||
* @return the http request to be executed
|
||||
*/
|
||||
IHttpRequestBase createGetRequest(EncodingEnum theEncoding);
|
||||
|
||||
}
|
|
@ -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.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.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(IHttpRequestBase 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.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.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(IHttpRequestBase 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.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.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 IHttpRequestBase 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 IHttpRequestBase getLastRequest() {
|
||||
return myLastRequest;
|
||||
}
|
||||
|
||||
public HttpResponse getLastResponse() {
|
||||
public IHttpResponse getLastResponse() {
|
||||
return myLastResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequestBase 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.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.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(IHttpRequestBase theRequest) {
|
||||
theRequest.addHeader(Constants.HEADER_COOKIE, sessionCookie); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interceptResponse(HttpResponse theResponse) {
|
||||
public void interceptResponse(IHttpResponse theResponse) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@ 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 java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
@ -35,7 +39,9 @@ import org.apache.http.client.methods.HttpRequestBase;
|
|||
import org.apache.http.entity.HttpEntityWrapper;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import ca.uhn.fhir.rest.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
public class LoggingInterceptor implements IClientInterceptor {
|
||||
|
@ -74,20 +80,13 @@ public class LoggingInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequestBase 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 = getHeaderString(theRequest.getAllHeaders());
|
||||
myLog.info("Client request headers:\n{}", b.toString());
|
||||
}
|
||||
|
||||
|
@ -110,23 +109,14 @@ 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 = getHeaderString(theResponse.getAllHeaders());
|
||||
// if (theResponse.getEntity() != null && theResponse.getEntity().getContentEncoding() != null) {
|
||||
// Header next = theResponse.getEntity().getContentEncoding();
|
||||
// b.append(next.getName() + ": " + next.getValue());
|
||||
|
@ -143,23 +133,41 @@ public class LoggingInterceptor implements IClientInterceptor {
|
|||
}
|
||||
|
||||
if (myLogResponseBody) {
|
||||
HttpEntity respEntity = theResponse.getEntity();
|
||||
theResponse.bufferEntitity();
|
||||
InputStream respEntity = theResponse.readEntity();
|
||||
if (respEntity != null) {
|
||||
final byte[] bytes;
|
||||
try {
|
||||
bytes = IOUtils.toByteArray(respEntity.getContent());
|
||||
} catch (IllegalStateException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
||||
myLog.info("Client response body:\n{}", new String(bytes, "UTF-8"));
|
||||
theResponse.setEntity(new MyEntityWrapper(respEntity, bytes));
|
||||
final byte[] bytes;
|
||||
try {
|
||||
bytes = IOUtils.toByteArray(respEntity);
|
||||
} catch (IllegalStateException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
myLog.info("Client response body:\n{}", new String(bytes, "UTF-8"));
|
||||
} else {
|
||||
myLog.info("Client response body: (none)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuilder getHeaderString(Map<String, List<String>> allHeaders) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (allHeaders != null && !allHeaders.isEmpty()) {
|
||||
Iterator<String> nameEntries = allHeaders.keySet().iterator();
|
||||
while(nameEntries.hasNext()) {
|
||||
String key = nameEntries.next();
|
||||
Iterator<String> values = allHeaders.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
|
||||
* logs to a differently named logger instead.
|
||||
|
@ -214,25 +222,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.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.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(IHttpRequestBase 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
|
||||
}
|
||||
|
||||
|
|
|
@ -20,19 +20,11 @@ package ca.uhn.fhir.rest.method;
|
|||
* #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.apache.http.Header;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
|
@ -44,10 +36,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.api.IHttpRequestBase;
|
||||
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
|
||||
|
@ -59,7 +52,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;
|
||||
|
@ -70,7 +62,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;
|
||||
|
@ -81,7 +73,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
super(theContext);
|
||||
myResource = theResource;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
|
@ -94,8 +86,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;
|
||||
|
@ -106,7 +97,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, List<? extends IBaseResource> theResources, BundleTypeEnum theBundleType) {
|
||||
myContext = theContext;
|
||||
super(theContext);
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = null;
|
||||
|
@ -117,7 +108,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
super(theContext);
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
|
@ -130,7 +121,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents, boolean theIsBundle, String theUrlPath) {
|
||||
myContext = theContext;
|
||||
super(theContext);
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = theUrlPath;
|
||||
|
@ -142,7 +133,7 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
}
|
||||
|
||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents, Map<String, List<String>> theParams, String... theUrlPath) {
|
||||
myContext = theContext;
|
||||
super(theContext);
|
||||
myResource = null;
|
||||
myTagList = null;
|
||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
||||
|
@ -155,13 +146,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;
|
||||
|
@ -171,153 +161,76 @@ 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 {
|
||||
StringBuilder url = new StringBuilder();
|
||||
|
||||
if (myUrlPath == null) {
|
||||
url.append(theUrlBase);
|
||||
public IHttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) throws DataFormatException {
|
||||
IHttpClient httpClient = getHttpClient(theUrlBase, theEncoding, theExtraParams, myHeaders);
|
||||
if (myResource != null && IBaseBinary.class.isAssignableFrom(myResource.getClass())) {
|
||||
return httpClient.createBinaryRequest((IBaseBinary) myResource);
|
||||
} else {
|
||||
if (!myUrlPath.contains("://")) {
|
||||
url.append(theUrlBase);
|
||||
if (!theUrlBase.endsWith("/")) {
|
||||
url.append('/');
|
||||
}
|
||||
}
|
||||
url.append(myUrlPath);
|
||||
}
|
||||
EncodingEnum encoding = theEncoding;
|
||||
if (myContents != null) {
|
||||
encoding = MethodUtil.detectEncoding(myContents);
|
||||
}
|
||||
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, url, url.indexOf("?") == -1);
|
||||
|
||||
if (myResource != null && IBaseBinary.class.isAssignableFrom(myResource.getClass())) {
|
||||
IBaseBinary binary = (IBaseBinary) myResource;
|
||||
|
||||
/*
|
||||
* 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());
|
||||
entity.setContentType(binary.getContentType());
|
||||
HttpRequestBase retVal = createRequest(url, entity);
|
||||
addMatchHeaders(retVal, url);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
IParser parser;
|
||||
String contentType;
|
||||
EncodingEnum encoding = null;
|
||||
encoding = theEncoding;
|
||||
|
||||
if (myContents != null) {
|
||||
encoding = MethodUtil.detectEncoding(myContents);
|
||||
}
|
||||
|
||||
if (encoding == EncodingEnum.JSON) {
|
||||
parser = myContext.newJsonParser();
|
||||
} else {
|
||||
encoding = EncodingEnum.XML;
|
||||
parser = myContext.newXmlParser();
|
||||
}
|
||||
|
||||
if (thePrettyPrint != null) {
|
||||
parser.setPrettyPrint(thePrettyPrint);
|
||||
}
|
||||
|
||||
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();
|
||||
} else if (myBundle != null) {
|
||||
contents = parser.encodeBundleToString(myBundle);
|
||||
contentType = encoding.getBundleContentType();
|
||||
} else if (myResources != null) {
|
||||
IVersionSpecificBundleFactory bundleFactory = myContext.newBundleFactory();
|
||||
bundleFactory.initializeBundleFromResourceList("", myResources, "", "", myResources.size(), myBundleType);
|
||||
Bundle bundle = bundleFactory.getDstu1Bundle();
|
||||
if (bundle != null) {
|
||||
contents = parser.encodeBundleToString(bundle);
|
||||
contentType = encoding.getBundleContentType();
|
||||
} else {
|
||||
IBaseResource bundleRes = bundleFactory.getResourceBundle();
|
||||
contents = parser.encodeResourceToString(bundleRes);
|
||||
contentType = encoding.getResourceContentType();
|
||||
}
|
||||
} else if (myContents != null) {
|
||||
contents = myContents;
|
||||
if (myContentsIsBundle && myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
|
||||
contentType = encoding.getBundleContentType();
|
||||
} else {
|
||||
contentType = encoding.getResourceContentType();
|
||||
}
|
||||
} 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;
|
||||
if (encoding == null) {
|
||||
encoding = EncodingEnum.XML;
|
||||
}
|
||||
|
||||
|
||||
if (myParams != null) {
|
||||
return httpClient.createParamRequest(myParams, encoding);
|
||||
} else {
|
||||
String contents = parseContents(thePrettyPrint, encoding);
|
||||
String contentType = getContentType(encoding);
|
||||
return httpClient.createByteRequest(contents, contentType, encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract HttpRequestBase createRequest(StringBuilder theUrl, AbstractHttpEntity theEntity);
|
||||
private String getContentType(EncodingEnum encoding) {
|
||||
if(myBundle != null ||
|
||||
(getContext().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 = getContext().newJsonParser();
|
||||
} else {
|
||||
parser = getContext().newXmlParser();
|
||||
}
|
||||
|
||||
if (thePrettyPrint != null) {
|
||||
parser.setPrettyPrint(thePrettyPrint);
|
||||
}
|
||||
|
||||
parser.setOmitResourceId(myOmitResourceId);
|
||||
if (myTagList != null) {
|
||||
return parser.encodeTagListToString(myTagList);
|
||||
} else if (myBundle != null) {
|
||||
return parser.encodeBundleToString(myBundle);
|
||||
} else if (myResources != null) {
|
||||
IVersionSpecificBundleFactory bundleFactory = getContext().newBundleFactory();
|
||||
bundleFactory.initializeBundleFromResourceList("", myResources, "", "", myResources.size(), myBundleType);
|
||||
Bundle bundle = bundleFactory.getDstu1Bundle();
|
||||
if (bundle != null) {
|
||||
return parser.encodeBundleToString(bundle);
|
||||
} else {
|
||||
IBaseResource bundleRes = bundleFactory.getResourceBundle();
|
||||
return parser.encodeResourceToString(bundleRes);
|
||||
}
|
||||
} else if (myContents != null) {
|
||||
return myContents;
|
||||
} else {
|
||||
return parser.encodeResourceToString(myResource);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -329,5 +242,27 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
|||
public void setOmitResourceId(boolean theOmitResourceId) {
|
||||
myOmitResourceId = theOmitResourceId;
|
||||
}
|
||||
|
||||
public IHttpClient getHttpClient(String theUrlBase, EncodingEnum theEncoding, Map<String, List<String>> theExtraParams, List<Header> myHeaders) {
|
||||
//TODO move this to the factory
|
||||
StringBuilder url = new StringBuilder();
|
||||
|
||||
if (myUrlPath == null) {
|
||||
url.append(theUrlBase);
|
||||
} else {
|
||||
if (!myUrlPath.contains("://")) {
|
||||
url.append(theUrlBase);
|
||||
if (!theUrlBase.endsWith("/")) {
|
||||
url.append('/');
|
||||
}
|
||||
}
|
||||
url.append(myUrlPath);
|
||||
}
|
||||
|
||||
appendExtraParamsWithQuestionMark(theExtraParams, url, url.indexOf("?") == -1);
|
||||
return getRestfulClientFactory().getHttpClient(url, myIfNoneExistParams, myIfNoneExistString, theEncoding, getRequestType(), myHeaders);
|
||||
}
|
||||
|
||||
protected abstract RequestTypeEnum getRequestType();
|
||||
|
||||
}
|
||||
|
|
|
@ -59,7 +59,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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 theFhirContext, 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(theFhirContext, b.toString());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,10 +23,11 @@ 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.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
|
@ -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 IHttpRequestBase 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,9 +28,11 @@ 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.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
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 IHttpRequestBase 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,9 @@ 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.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
|
||||
|
@ -33,15 +36,14 @@ 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 IHttpRequestBase asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
|
||||
return createHttpRequest(myUrl, theEncoding, RequestTypeEnum.GET);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -146,8 +146,8 @@ public class MethodUtil {
|
|||
return value;
|
||||
}
|
||||
|
||||
public static HttpGetClientInvocation createConformanceInvocation() {
|
||||
return new HttpGetClientInvocation("metadata");
|
||||
public static HttpGetClientInvocation createConformanceInvocation(FhirContext theFhirContext) {
|
||||
return new HttpGetClientInvocation(theFhirContext, "metadata");
|
||||
}
|
||||
|
||||
public static HttpPostClientInvocation createCreateInvocation(IBaseResource theResource, FhirContext theContext) {
|
||||
|
|
|
@ -334,7 +334,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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
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.apache.http.Header;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
|
||||
import ca.uhn.fhir.rest.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
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 myClient, StringBuilder url, Map<String, List<String>> myIfNoneExistParams, String myIfNoneExistString, EncodingEnum theEncoding, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
this.myHeaders = theHeaders;
|
||||
this.myClient = myClient;
|
||||
this.myUrl = url;
|
||||
this.myIfNoneExistParams = myIfNoneExistParams;
|
||||
this.myIfNoneExistString = myIfNoneExistString;
|
||||
this.myRequestType = theRequestType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequestBase createByteRequest(String contents, String contentType, EncodingEnum encoding) {
|
||||
Builder retVal = createRequest();
|
||||
addHeadersToRequest(retVal, encoding);
|
||||
addMatchHeaders(retVal, myUrl);
|
||||
Entity<String> entity = Entity.entity(contents, contentType + Constants.HEADER_SUFFIX_CT_UTF_8);
|
||||
retVal.header(Constants.HEADER_CONTENT_TYPE, contentType + Constants.HEADER_SUFFIX_CT_UTF_8);
|
||||
return new JaxRsHttpRequestBase(retVal, myRequestType, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequestBase createParamRequest(Map<String, List<String>> myParams, EncodingEnum encoding) {
|
||||
MultivaluedMap<String, String> map = new MultivaluedHashMap<String, String>();
|
||||
for (Map.Entry<String, List<String>> nextParam : myParams.entrySet()) {
|
||||
List<String> value = nextParam.getValue();
|
||||
for (String s : value) {
|
||||
map.add(nextParam.getKey(), s);
|
||||
}
|
||||
}
|
||||
Builder retVal = createRequest();
|
||||
//addHeadersToRequest(retVal, encoding);
|
||||
addMatchHeaders(retVal, myUrl);
|
||||
Entity<Form> entity = Entity.form(map);
|
||||
return new JaxRsHttpRequestBase(retVal, myRequestType, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequestBase createBinaryRequest(IBaseBinary binary) {
|
||||
Entity<String> entity = Entity.entity(binary.getContentAsBase64(), binary.getContentType());
|
||||
Builder retVal = createRequest();
|
||||
addMatchHeaders(retVal, myUrl);
|
||||
return new JaxRsHttpRequestBase(retVal, myRequestType, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpRequestBase createGetRequest(EncodingEnum theEncoding) {
|
||||
Builder builder = createRequest();
|
||||
addHeadersToRequest(builder, theEncoding);
|
||||
addMatchHeaders(builder, myUrl);
|
||||
return new JaxRsHttpRequestBase(builder, myRequestType, null);
|
||||
}
|
||||
|
||||
public void addHeadersToRequest(Builder builder, EncodingEnum theEncoding) {
|
||||
if (myHeaders != null) {
|
||||
for (Header next : myHeaders) {
|
||||
builder.header(next.getName(), next.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
builder.header("User-Agent", "HAPI-FHIR/" + VersionUtil.getVersion() + " (FHIR Client)");
|
||||
builder.header("Accept-Charset", "utf-8");
|
||||
builder.acceptEncoding("gzip");
|
||||
|
||||
if (theEncoding == null) {
|
||||
builder.accept(Constants.HEADER_ACCEPT_VALUE_ALL);
|
||||
} else if (theEncoding == EncodingEnum.JSON) {
|
||||
builder.accept(Constants.CT_FHIR_JSON);
|
||||
} else if (theEncoding == EncodingEnum.XML) {
|
||||
builder.accept(Constants.CT_FHIR_XML);
|
||||
}
|
||||
}
|
||||
|
||||
private void addMatchHeaders(Builder theHttpRequest, StringBuilder theUrlBase) {
|
||||
if (myIfNoneExistParams != null) {
|
||||
StringBuilder b = newHeaderBuilder(theUrlBase);
|
||||
BaseHttpClientInvocation.appendExtraParamsWithQuestionMark(myIfNoneExistParams, b, b.indexOf("?") == -1);
|
||||
theHttpRequest.header(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.header(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 Builder createRequest() {
|
||||
return myClient.target(myUrl.toString()).request();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
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 ca.uhn.fhir.rest.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.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 JaxRsHttpRequestBase implements IHttpRequestBase {
|
||||
|
||||
private Invocation.Builder myRequest;
|
||||
private RequestTypeEnum myRequestType;
|
||||
private Entity<?> myEntity;
|
||||
private Map<String, List<String>> myHeaders = new HashMap<String, List<String>>();
|
||||
|
||||
public JaxRsHttpRequestBase(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() {
|
||||
return new JaxRsHttpResponse(getRequest().build(getRequestType().name(), getEntity()).invoke());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getAllHeaders() {
|
||||
return this.myHeaders;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
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.IOException;
|
||||
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.HttpHeaders;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.http.entity.ContentType;
|
||||
|
||||
import ca.uhn.fhir.rest.client.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() {
|
||||
ContentType ct = ContentType.parse(myResponse.getHeaderString(HttpHeaders.CONTENT_TYPE));
|
||||
return ct != null ? ct.getMimeType() : null;
|
||||
}
|
||||
|
||||
@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() throws UnsupportedOperationException, IOException {
|
||||
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(myResponse.hasEntity()) {
|
||||
myBufferedEntity = true;
|
||||
myResponse.bufferEntity();
|
||||
} else {
|
||||
myResponse.bufferEntity();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
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.ClientInvocationHandler;
|
||||
import ca.uhn.fhir.rest.client.ClientInvocationHandlerFactory;
|
||||
import ca.uhn.fhir.rest.client.RestfulClientFactory;
|
||||
import ca.uhn.fhir.rest.client.api.IHttpClient;
|
||||
import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import org.apache.http.Header;
|
||||
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
import java.lang.reflect.Method;
|
||||
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 JaxRsHttpClient myHttpClient;
|
||||
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 ClientInvocationHandler newInvocationHandler(IHttpClient theClient, String myUrlBase, Map<Method, Object> myMethodToReturnValue, Map<Method, BaseMethodBinding<?>> myBindings, Map<Method, ClientInvocationHandlerFactory.ILambda> myMethodToLambda) {
|
||||
return new ClientInvocationHandler(myHttpClient, myContext, myUrlBase.toString(), myMethodToReturnValue, myBindings, myMethodToLambda, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IHttpClient getHttpClient(StringBuilder url, Map<String, List<String>> myIfNoneExistParams, String myIfNoneExistString,
|
||||
EncodingEnum theEncoding, RequestTypeEnum theRequestType, List<Header> myHeaders) {
|
||||
return new JaxRsHttpClient(getNativeClientClient(), url, myIfNoneExistParams, myIfNoneExistString, theEncoding, theRequestType, myHeaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProxy(String theHost, Integer thePort) {
|
||||
throw new UnsupportedOperationException("Proxy setting is 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, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetHttpClient() {
|
||||
this.myHttpClient = 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;
|
||||
|
@ -106,6 +107,7 @@ public class AbstractJaxRsResourceProviderTest {
|
|||
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
||||
ourCtx.setRestfulClientFactory(new JaxRsRestfulClientFactory(ourCtx));
|
||||
serverBase = "http://localhost:" + ourPort + "/";
|
||||
client = ourCtx.newRestfulGenericClient(serverBase);
|
||||
client.setEncoding(EncodingEnum.JSON);
|
||||
|
|
|
@ -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;
|
||||
|
@ -150,7 +152,7 @@ public class ClientDstu1Test {
|
|||
|
||||
MethodOutcome response = client.createPatient(patient);
|
||||
|
||||
assertEquals(interceptor.getLastRequest().getURI().toASCIIString(), "http://foo/Patient");
|
||||
assertEquals(((ApacheHttpRequestBase) 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());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -48,8 +48,10 @@ import ca.uhn.fhir.model.dstu.resource.Conformance;
|
|||
import ca.uhn.fhir.model.dstu.resource.Conformance.Rest;
|
||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.api.IHttpRequestBase;
|
||||
import ca.uhn.fhir.rest.client.GenericClient;
|
||||
import ca.uhn.fhir.rest.client.IClientInterceptor;
|
||||
import ca.uhn.fhir.rest.client.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.to.model.HomeRequest;
|
||||
|
@ -288,7 +290,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());
|
||||
}
|
||||
|
||||
|
@ -647,17 +649,17 @@ public class BaseController {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void interceptRequest(HttpRequestBase theRequest) {
|
||||
public void interceptRequest(IHttpRequestBase 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 {
|
||||
|
@ -667,7 +669,7 @@ public class BaseController {
|
|||
}
|
||||
|
||||
myResponseBody = new String(bytes, "UTF-8");
|
||||
theResponse.setEntity(new MyEntityWrapper(respEntity, bytes));
|
||||
myLastResponse.setEntity(new MyEntityWrapper(respEntity, bytes));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,11 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.IHttpRequestBase;
|
||||
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.IHttpResponse;
|
||||
import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.IncomingRequestAddressStrategy;
|
||||
|
@ -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(IHttpRequestBase theRequest) {
|
||||
if (isNotBlank(remoteAddr)) {
|
||||
theRequest.addHeader("x-forwarded-for", remoteAddr);
|
||||
}
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -1396,6 +1396,7 @@
|
|||
<id>SITE</id>
|
||||
<modules>
|
||||
<module>hapi-fhir-base</module>
|
||||
<module>hapi-fhir-base-client</module>
|
||||
<module>hapi-fhir-structures-dstu</module>
|
||||
<module>hapi-fhir-structures-dstu2</module>
|
||||
<module>hapi-fhir-structures-hl7org-dstu2</module>
|
||||
|
@ -1432,6 +1433,7 @@
|
|||
<modules>
|
||||
<module>hapi-deployable-pom</module>
|
||||
<module>hapi-fhir-base</module>
|
||||
<module>hapi-fhir-base-client</module>
|
||||
<!--<module>hapi-fhir-oauth2</module> -->
|
||||
<module>hapi-fhir-base-test-mindeps-client</module>
|
||||
<module>hapi-fhir-base-test-mindeps-server</module>
|
||||
|
|
Loading…
Reference in New Issue