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.Constants;
024import ca.uhn.fhir.rest.api.EncodingEnum;
025import ca.uhn.fhir.rest.api.RequestTypeEnum;
026import ca.uhn.fhir.rest.client.api.Header;
027import ca.uhn.fhir.rest.client.api.HttpClientUtil;
028import ca.uhn.fhir.rest.client.api.IHttpClient;
029import ca.uhn.fhir.rest.client.api.IHttpRequest;
030import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
031import ca.uhn.fhir.rest.client.method.MethodUtil;
032import org.hl7.fhir.instance.model.api.IBaseBinary;
033
034import java.util.List;
035import java.util.Map;
036
037public abstract class BaseHttpClient implements IHttpClient {
038
039        private final List<Header> myHeaders;
040        private final Map<String, List<String>> myIfNoneExistParams;
041        private final String myIfNoneExistString;
042        protected final RequestTypeEnum myRequestType;
043        protected final StringBuilder myUrl;
044
045        /**
046         * Constructor
047         */
048        public BaseHttpClient(
049                        StringBuilder theUrl,
050                        Map<String, List<String>> theIfNoneExistParams,
051                        String theIfNoneExistString,
052                        RequestTypeEnum theRequestType,
053                        List<Header> theHeaders) {
054                this.myUrl = theUrl;
055                this.myIfNoneExistParams = theIfNoneExistParams;
056                this.myIfNoneExistString = theIfNoneExistString;
057                this.myRequestType = theRequestType;
058                this.myHeaders = theHeaders;
059        }
060
061        private void addHeaderIfNoneExist(IHttpRequest result) {
062                if (myIfNoneExistParams != null) {
063                        StringBuilder b = newHeaderBuilder(myUrl);
064                        BaseHttpClientInvocation.appendExtraParamsWithQuestionMark(myIfNoneExistParams, b, b.indexOf("?") == -1);
065                        result.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
066                }
067
068                if (myIfNoneExistString != null) {
069                        StringBuilder b = newHeaderBuilder(myUrl);
070                        b.append(b.indexOf("?") == -1 ? '?' : '&');
071                        b.append(myIfNoneExistString.substring(myIfNoneExistString.indexOf('?') + 1));
072                        result.addHeader(Constants.HEADER_IF_NONE_EXIST, b.toString());
073                }
074        }
075
076        public void addHeadersToRequest(IHttpRequest theHttpRequest, EncodingEnum theEncoding, FhirContext theContext) {
077                if (myHeaders != null) {
078                        for (Header next : myHeaders) {
079                                theHttpRequest.addHeader(next.getName(), next.getValue());
080                        }
081                }
082
083                theHttpRequest.addHeader("User-Agent", HttpClientUtil.createUserAgentString(theContext, "apache"));
084                theHttpRequest.addHeader("Accept-Charset", "utf-8");
085                theHttpRequest.addHeader("Accept-Encoding", "gzip");
086
087                addHeaderIfNoneExist(theHttpRequest);
088
089                MethodUtil.addAcceptHeaderToRequest(theEncoding, theHttpRequest, theContext);
090        }
091
092        @Override
093        public IHttpRequest createBinaryRequest(FhirContext theContext, IBaseBinary theBinary) {
094                byte[] content = theBinary.getContent();
095                IHttpRequest retVal = createHttpRequest(content);
096                addHeadersToRequest(retVal, null, theContext);
097                retVal.addHeader(Constants.HEADER_CONTENT_TYPE, theBinary.getContentType());
098                return retVal;
099        }
100
101        @Override
102        public IHttpRequest createByteRequest(
103                        FhirContext theContext, String theContents, String theContentType, EncodingEnum theEncoding) {
104                IHttpRequest retVal = createHttpRequest(theContents);
105                addHeadersToRequest(retVal, theEncoding, theContext);
106                retVal.addHeader(Constants.HEADER_CONTENT_TYPE, theContentType + Constants.HEADER_SUFFIX_CT_UTF_8);
107                return retVal;
108        }
109
110        @Override
111        public IHttpRequest createGetRequest(FhirContext theContext, EncodingEnum theEncoding) {
112                IHttpRequest retVal = createHttpRequest();
113                addHeadersToRequest(retVal, theEncoding, theContext);
114                return retVal;
115        }
116
117        protected abstract IHttpRequest createHttpRequest();
118
119        protected abstract IHttpRequest createHttpRequest(byte[] theContent);
120
121        protected abstract IHttpRequest createHttpRequest(Map<String, List<String>> theParams);
122
123        protected abstract IHttpRequest createHttpRequest(String theContents);
124
125        @Override
126        public IHttpRequest createParamRequest(
127                        FhirContext theContext, Map<String, List<String>> theParams, EncodingEnum theEncoding) {
128                IHttpRequest retVal = createHttpRequest(theParams);
129                addHeadersToRequest(retVal, theEncoding, theContext);
130                return retVal;
131        }
132
133        private StringBuilder newHeaderBuilder(StringBuilder theUrlBase) {
134                StringBuilder b = new StringBuilder();
135                b.append(theUrlBase);
136                if (theUrlBase.length() > 0 && theUrlBase.charAt(theUrlBase.length() - 1) == '/') {
137                        b.deleteCharAt(b.length() - 1);
138                }
139                return b;
140        }
141}