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-Encoding", "gzip");
085
086                addHeaderIfNoneExist(theHttpRequest);
087
088                MethodUtil.addAcceptHeaderToRequest(theEncoding, theHttpRequest, theContext);
089        }
090
091        @Override
092        public IHttpRequest createBinaryRequest(FhirContext theContext, IBaseBinary theBinary) {
093                byte[] content = theBinary.getContent();
094                IHttpRequest retVal = createHttpRequest(content);
095                addHeadersToRequest(retVal, null, theContext);
096                retVal.addHeader(Constants.HEADER_CONTENT_TYPE, theBinary.getContentType());
097                return retVal;
098        }
099
100        @Override
101        public IHttpRequest createByteRequest(
102                        FhirContext theContext, String theContents, String theContentType, EncodingEnum theEncoding) {
103                IHttpRequest retVal = createHttpRequest(theContents);
104                addHeadersToRequest(retVal, theEncoding, theContext);
105                retVal.addHeader(Constants.HEADER_CONTENT_TYPE, theContentType + Constants.HEADER_SUFFIX_CT_UTF_8);
106                return retVal;
107        }
108
109        @Override
110        public IHttpRequest createGetRequest(FhirContext theContext, EncodingEnum theEncoding) {
111                IHttpRequest retVal = createHttpRequest();
112                addHeadersToRequest(retVal, theEncoding, theContext);
113                return retVal;
114        }
115
116        protected abstract IHttpRequest createHttpRequest();
117
118        protected abstract IHttpRequest createHttpRequest(byte[] theContent);
119
120        protected abstract IHttpRequest createHttpRequest(Map<String, List<String>> theParams);
121
122        protected abstract IHttpRequest createHttpRequest(String theContents);
123
124        @Override
125        public IHttpRequest createParamRequest(
126                        FhirContext theContext, Map<String, List<String>> theParams, EncodingEnum theEncoding) {
127                IHttpRequest retVal = createHttpRequest(theParams);
128                addHeadersToRequest(retVal, theEncoding, theContext);
129                return retVal;
130        }
131
132        private StringBuilder newHeaderBuilder(StringBuilder theUrlBase) {
133                StringBuilder b = new StringBuilder();
134                b.append(theUrlBase);
135                if (theUrlBase.length() > 0 && theUrlBase.charAt(theUrlBase.length() - 1) == '/') {
136                        b.deleteCharAt(b.length() - 1);
137                }
138                return b;
139        }
140}