001/* 002 * #%L 003 * HAPI FHIR - Client Framework 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.rest.client.apache; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.rest.api.RequestTypeEnum; 024import ca.uhn.fhir.rest.client.api.Header; 025import ca.uhn.fhir.rest.client.api.IHttpClient; 026import ca.uhn.fhir.rest.client.impl.RestfulClientFactory; 027import org.apache.http.HttpHost; 028import org.apache.http.auth.AuthScope; 029import org.apache.http.auth.UsernamePasswordCredentials; 030import org.apache.http.client.CredentialsProvider; 031import org.apache.http.client.HttpClient; 032import org.apache.http.client.config.RequestConfig; 033import org.apache.http.impl.client.BasicCredentialsProvider; 034import org.apache.http.impl.client.HttpClientBuilder; 035import org.apache.http.impl.client.HttpClients; 036import org.apache.http.impl.client.ProxyAuthenticationStrategy; 037import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 038 039import java.util.List; 040import java.util.Map; 041import java.util.concurrent.TimeUnit; 042 043import static org.apache.commons.lang3.StringUtils.isNotBlank; 044 045/** 046 * A Restful Factory to create clients, requests and responses based on the Apache httpclient library. 047 * 048 * @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare 049 */ 050public class ApacheRestfulClientFactory extends RestfulClientFactory { 051 052 private HttpClient myHttpClient; 053 private HttpHost myProxy; 054 055 /** 056 * Constructor 057 */ 058 public ApacheRestfulClientFactory() { 059 super(); 060 } 061 062 /** 063 * Constructor 064 * 065 * @param theContext 066 * The context 067 */ 068 public ApacheRestfulClientFactory(FhirContext theContext) { 069 super(theContext); 070 } 071 072 @Override 073 protected synchronized IHttpClient getHttpClient(String theServerBase) { 074 return getHttpClient(new StringBuilder(theServerBase), null, null, null, null); 075 } 076 077 @Override 078 public synchronized IHttpClient getHttpClient( 079 StringBuilder theUrl, 080 Map<String, List<String>> theIfNoneExistParams, 081 String theIfNoneExistString, 082 RequestTypeEnum theRequestType, 083 List<Header> theHeaders) { 084 return new ApacheHttpClient( 085 getNativeHttpClient(), theUrl, theIfNoneExistParams, theIfNoneExistString, theRequestType, theHeaders); 086 } 087 088 public HttpClient getNativeHttpClient() { 089 if (myHttpClient == null) { 090 091 // TODO: Use of a deprecated method should be resolved. 092 RequestConfig defaultRequestConfig = RequestConfig.custom() 093 .setSocketTimeout(getSocketTimeout()) 094 .setConnectTimeout(getConnectTimeout()) 095 .setConnectionRequestTimeout(getConnectionRequestTimeout()) 096 .setStaleConnectionCheckEnabled(true) 097 .setProxy(myProxy) 098 .build(); 099 100 HttpClientBuilder builder = getHttpClientBuilder() 101 .useSystemProperties() 102 .setDefaultRequestConfig(defaultRequestConfig) 103 .disableCookieManagement(); 104 105 PoolingHttpClientConnectionManager connectionManager = 106 new PoolingHttpClientConnectionManager(getConnectionTimeToLive(), TimeUnit.MILLISECONDS); 107 connectionManager.setMaxTotal(getPoolMaxTotal()); 108 connectionManager.setDefaultMaxPerRoute(getPoolMaxPerRoute()); 109 builder.setConnectionManager(connectionManager); 110 111 if (myProxy != null && isNotBlank(getProxyUsername()) && isNotBlank(getProxyPassword())) { 112 CredentialsProvider credsProvider = new BasicCredentialsProvider(); 113 credsProvider.setCredentials( 114 new AuthScope(myProxy.getHostName(), myProxy.getPort()), 115 new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword())); 116 builder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy()); 117 builder.setDefaultCredentialsProvider(credsProvider); 118 } 119 120 myHttpClient = builder.build(); 121 } 122 123 return myHttpClient; 124 } 125 126 protected HttpClientBuilder getHttpClientBuilder() { 127 return HttpClients.custom(); 128 } 129 130 @Override 131 protected void resetHttpClient() { 132 this.myHttpClient = null; 133 } 134 135 /** 136 * Only allows to set an instance of type org.apache.http.client.HttpClient 137 * @see ca.uhn.fhir.rest.client.api.IRestfulClientFactory#setHttpClient(Object) 138 */ 139 @Override 140 public synchronized void setHttpClient(Object theHttpClient) { 141 this.myHttpClient = (HttpClient) theHttpClient; 142 } 143 144 @Override 145 public void setProxy(String theHost, Integer thePort) { 146 if (theHost != null) { 147 myProxy = new HttpHost(theHost, thePort, "http"); 148 } else { 149 myProxy = null; 150 } 151 } 152}