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.i18n.Msg; 023import ca.uhn.fhir.rest.api.Constants; 024import ca.uhn.fhir.rest.api.RequestTypeEnum; 025import ca.uhn.fhir.rest.client.api.Header; 026import ca.uhn.fhir.rest.client.api.IHttpClient; 027import ca.uhn.fhir.rest.client.api.IHttpRequest; 028import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 029import org.apache.http.HttpEntity; 030import org.apache.http.NameValuePair; 031import org.apache.http.client.HttpClient; 032import org.apache.http.client.entity.UrlEncodedFormEntity; 033import org.apache.http.client.methods.HttpDelete; 034import org.apache.http.client.methods.HttpGet; 035import org.apache.http.client.methods.HttpOptions; 036import org.apache.http.client.methods.HttpPatch; 037import org.apache.http.client.methods.HttpPost; 038import org.apache.http.client.methods.HttpPut; 039import org.apache.http.client.methods.HttpRequestBase; 040import org.apache.http.entity.ByteArrayEntity; 041import org.apache.http.message.BasicNameValuePair; 042 043import java.io.UnsupportedEncodingException; 044import java.util.ArrayList; 045import java.util.List; 046import java.util.Map; 047import java.util.Map.Entry; 048 049/** 050 * A Http Client based on Apache. This is an adapter around the class 051 * {@link org.apache.http.client.HttpClient HttpClient} 052 * 053 * @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare 054 */ 055public class ApacheHttpClient extends BaseHttpClient implements IHttpClient { 056 057 private final HttpClient myClient; 058 059 public ApacheHttpClient( 060 HttpClient theClient, 061 StringBuilder theUrl, 062 Map<String, List<String>> theIfNoneExistParams, 063 String theIfNoneExistString, 064 RequestTypeEnum theRequestType, 065 List<Header> theHeaders) { 066 super(theUrl, theIfNoneExistParams, theIfNoneExistString, theRequestType, theHeaders); 067 this.myClient = theClient; 068 } 069 070 private HttpRequestBase constructRequestBase(HttpEntity theEntity) { 071 String url = myUrl.toString(); 072 switch (myRequestType) { 073 case DELETE: 074 return new HttpDelete(url); 075 case PATCH: 076 HttpPatch httpPatch = new HttpPatch(url); 077 httpPatch.setEntity(theEntity); 078 return httpPatch; 079 case OPTIONS: 080 return new HttpOptions(url); 081 case POST: 082 HttpPost httpPost = new HttpPost(url); 083 httpPost.setEntity(theEntity); 084 return httpPost; 085 case PUT: 086 HttpPut httpPut = new HttpPut(url); 087 httpPut.setEntity(theEntity); 088 return httpPut; 089 case GET: 090 default: 091 return new HttpGet(url); 092 } 093 } 094 095 private UrlEncodedFormEntity createFormEntity(List<NameValuePair> parameters) { 096 try { 097 return new UrlEncodedFormEntity(parameters, "UTF-8"); 098 } catch (UnsupportedEncodingException e) { 099 throw new InternalErrorException(Msg.code(1479) + "Server does not support UTF-8 (should not happen)", e); 100 } 101 } 102 103 @Override 104 protected IHttpRequest createHttpRequest() { 105 return createHttpRequest((HttpEntity) null); 106 } 107 108 @Override 109 protected IHttpRequest createHttpRequest(byte[] content) { 110 /* 111 * Note: Be careful about changing which constructor we use for 112 * ByteArrayEntity, as Android's version of HTTPClient doesn't support 113 * the newer ones for whatever reason. 114 */ 115 ByteArrayEntity entity = new ByteArrayEntity(content); 116 return createHttpRequest(entity); 117 } 118 119 private ApacheHttpRequest createHttpRequest(HttpEntity theEntity) { 120 HttpRequestBase request = constructRequestBase(theEntity); 121 return new ApacheHttpRequest(myClient, request); 122 } 123 124 @Override 125 protected IHttpRequest createHttpRequest(Map<String, List<String>> theParams) { 126 List<NameValuePair> parameters = new ArrayList<>(); 127 for (Entry<String, List<String>> nextParam : theParams.entrySet()) { 128 List<String> value = nextParam.getValue(); 129 for (String s : value) { 130 parameters.add(new BasicNameValuePair(nextParam.getKey(), s)); 131 } 132 } 133 134 UrlEncodedFormEntity entity = createFormEntity(parameters); 135 return createHttpRequest(entity); 136 } 137 138 @Override 139 protected IHttpRequest createHttpRequest(String theContents) { 140 /* 141 * We aren't using a StringEntity here because the constructors 142 * supported by Android aren't available in non-Android, and vice versa. 143 * Since we add the content type header manually, it makes no difference 144 * which one we use anyhow. 145 */ 146 ByteArrayEntity entity = new ByteArrayEntity(theContents.getBytes(Constants.CHARSET_UTF8)); 147 return createHttpRequest(entity); 148 } 149}