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