Java.libraries.apache-httpclient.ApiClient.mustache Maven / Gradle / Ivy
{{>licenseInfo}}
package {{invokerPackage}};
{{#threetenbp}}
import org.threeten.bp.*;
{{/threetenbp}}
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
{{#joda}}
import com.fasterxml.jackson.datatype.joda.JodaModule;
{{/joda}}
{{#java8}}
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
{{^threetenbp}}
import java.time.OffsetDateTime;
{{/threetenbp}}
{{/java8}}
{{#threetenbp}}
import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
{{/threetenbp}}
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.http.cookie.Cookie;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.net.URLEncoder;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.nio.file.Paths;
import java.lang.reflect.Type;
import java.net.URI;
import java.text.DateFormat;
import {{invokerPackage}}.auth.Authentication;
{{#hasHttpBasicMethods}}
import {{invokerPackage}}.auth.HttpBasicAuth;
{{/hasHttpBasicMethods}}
{{#hasHttpBearerMethods}}
import {{invokerPackage}}.auth.HttpBearerAuth;
{{/hasHttpBearerMethods}}
{{#hasApiKeyMethods}}
import {{invokerPackage}}.auth.ApiKeyAuth;
{{/hasApiKeyMethods}}
{{#hasOAuthMethods}}
import {{invokerPackage}}.auth.OAuth;
{{/hasOAuthMethods}}
{{>generatedAnnotation}}
public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
private Map defaultHeaderMap = new HashMap();
private Map defaultCookieMap = new HashMap();
private String basePath = "{{{basePath}}}";
protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList(
{{/-first}} new ServerConfiguration(
"{{{url}}}",
"{{{description}}}{{^description}}No description provided{{/description}}",
new HashMap(){{#variables}}{{#-first}} {{
{{/-first}} put("{{{name}}}", new ServerVariable(
"{{{description}}}{{^description}}No description provided{{/description}}",
"{{{defaultValue}}}",
new HashSet(
{{#enumValues}}
{{#-first}}
Arrays.asList(
{{/-first}}
"{{{.}}}"{{^-last}},{{/-last}}
{{#-last}}
)
{{/-last}}
{{/enumValues}}
)
));
{{#-last}}
}}{{/-last}}{{/variables}}
){{^-last}},{{/-last}}
{{#-last}}
){{/-last}}{{/servers}});
protected Integer serverIndex = 0;
protected Map serverVariables = null;
private boolean debugging = false;
private int connectionTimeout = 0;
private CloseableHttpClient httpClient;
private ObjectMapper objectMapper;
protected String tempFolderPath = null;
private Map authentications;
private int statusCode;
private Map> responseHeaders;
private DateFormat dateFormat;
// Methods that can have a request body
private static List bodyMethods = Arrays.asList("POST", "PUT", "DELETE", "PATCH");
public ApiClient(CloseableHttpClient httpClient) {
objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
{{#joda}}
objectMapper.registerModule(new JodaModule());
{{/joda}}
{{#java8}}
objectMapper.registerModule(new JavaTimeModule());
{{/java8}}
{{#threetenbp}}
ThreeTenModule module = new ThreeTenModule();
module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
objectMapper.registerModule(module);
{{/threetenbp}}
objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat());
dateFormat = ApiClient.buildDefaultDateFormat();
// Set default User-Agent.
setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}}
authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}}
authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
this.httpClient = httpClient;
}
public ApiClient() {
this(HttpClients.createDefault());
}
public static DateFormat buildDefaultDateFormat() {
return new RFC3339DateFormat();
}
/**
* Returns the current object mapper used for JSON serialization/deserialization.
*
* Note: If you make changes to the object mapper, remember to set it back via
* setObjectMapper
in order to trigger HTTP client rebuilding.
*
* @return Object mapper
*/
public ObjectMapper getObjectMapper() {
return objectMapper;
}
/**
* @return API client
*/
public ApiClient setObjectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
return this;
}
public CloseableHttpClient getHttpClient() {
return httpClient;
}
/**
* @return API client
*/
public ApiClient setHttpClient(CloseableHttpClient httpClient) {
this.httpClient = httpClient;
return this;
}
public String getBasePath() {
return basePath;
}
/**
* @return API client
*/
public ApiClient setBasePath(String basePath) {
this.basePath = basePath;
return this;
}
public List getServers() {
return servers;
}
/**
* @return API client
*/
public ApiClient setServers(List servers) {
this.servers = servers;
return this;
}
public Integer getServerIndex() {
return serverIndex;
}
/**
* @return API client
*/
public ApiClient setServerIndex(Integer serverIndex) {
this.serverIndex = serverIndex;
return this;
}
public Map getServerVariables() {
return serverVariables;
}
/**
* @return API client
*/
public ApiClient setServerVariables(Map serverVariables) {
this.serverVariables = serverVariables;
return this;
}
/**
* Gets the status code of the previous request
* @return Status code
*/
public int getStatusCode() {
return statusCode;
}
/**
* Gets the response headers of the previous request
* @return Response headers
*/
public Map> getResponseHeaders() {
return responseHeaders;
}
/**
* Get authentications (key: authentication name, value: authentication).
* @return Map of authentication
*/
public Map getAuthentications() {
return authentications;
}
/**
* Get authentication for the given name.
*
* @param authName The authentication name
* @return The authentication, null if not found
*/
public Authentication getAuthentication(String authName) {
return authentications.get(authName);
}
/**
* The path of temporary folder used to store downloaded files from endpoints
* with file response. The default value is null
, i.e. using
* the system's default temporary folder.
*
* @return Temp folder path
*/
public String getTempFolderPath() {
return tempFolderPath;
}
{{#hasHttpBearerMethods}}
/**
* Helper method to set access token for the first Bearer authentication.
* @param bearerToken Bearer token
* @return API client
*/
public ApiClient setBearerToken(String bearerToken) {
for (Authentication auth : authentications.values()) {
if (auth instanceof HttpBearerAuth) {
((HttpBearerAuth) auth).setBearerToken(bearerToken);
return this;
}
}
throw new RuntimeException("No Bearer authentication configured!");
}
{{/hasHttpBearerMethods}}
{{#hasHttpBasicMethods}}
/**
* Helper method to set username for the first HTTP basic authentication.
* @param username Username
* @return API client
*/
public ApiClient setUsername(String username) {
for (Authentication auth : authentications.values()) {
if (auth instanceof HttpBasicAuth) {
((HttpBasicAuth) auth).setUsername(username);
return this;
}
}
throw new RuntimeException("No HTTP basic authentication configured!");
}
/**
* Helper method to set password for the first HTTP basic authentication.
* @param password Password
* @return API client
*/
public ApiClient setPassword(String password) {
for (Authentication auth : authentications.values()) {
if (auth instanceof HttpBasicAuth) {
((HttpBasicAuth) auth).setPassword(password);
return this;
}
}
throw new RuntimeException("No HTTP basic authentication configured!");
}
{{/hasHttpBasicMethods}}
{{#hasApiKeyMethods}}
/**
* Helper method to set API key value for the first API key authentication.
* @param apiKey the API key
* @return API client
*/
public ApiClient setApiKey(String apiKey) {
for (Authentication auth : authentications.values()) {
if (auth instanceof ApiKeyAuth) {
((ApiKeyAuth) auth).setApiKey(apiKey);
return this;
}
}
throw new RuntimeException("No API key authentication configured!");
}
/**
* Helper method to set API key prefix for the first API key authentication.
* @param apiKeyPrefix API key prefix
* @return API client
*/
public ApiClient setApiKeyPrefix(String apiKeyPrefix) {
for (Authentication auth : authentications.values()) {
if (auth instanceof ApiKeyAuth) {
((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
return this;
}
}
throw new RuntimeException("No API key authentication configured!");
}
{{/hasApiKeyMethods}}
{{#hasOAuthMethods}}
/**
* Helper method to set access token for the first OAuth2 authentication.
* @param accessToken Access token
* @return API client
*/
public ApiClient setAccessToken(String accessToken) {
for (Authentication auth : authentications.values()) {
if (auth instanceof OAuth) {
((OAuth) auth).setAccessToken(accessToken);
return this;
}
}
throw new RuntimeException("No OAuth2 authentication configured!");
}
{{/hasOAuthMethods}}
/**
* Set the User-Agent header's value (by adding to the default header map).
* @param userAgent User agent
* @return API client
*/
public ApiClient setUserAgent(String userAgent) {
addDefaultHeader("User-Agent", userAgent);
return this;
}
/**
* Set temp folder path
* @param tempFolderPath Temp folder path
* @return API client
*/
public ApiClient setTempFolderPath(String tempFolderPath) {
this.tempFolderPath = tempFolderPath;
return this;
}
/**
* Add a default header.
*
* @param key The header's key
* @param value The header's value
* @return API client
*/
public ApiClient addDefaultHeader(String key, String value) {
defaultHeaderMap.put(key, value);
return this;
}
/**
* Add a default cookie.
*
* @param key The cookie's key
* @param value The cookie's value
* @return API client
*/
public ApiClient addDefaultCookie(String key, String value) {
defaultCookieMap.put(key, value);
return this;
}
/**
* Check that whether debugging is enabled for this API client.
* @return True if debugging is on
*/
public boolean isDebugging() {
return debugging;
}
/**
* Enable/disable debugging for this API client.
*
* @param debugging To enable (true) or disable (false) debugging
* @return API client
*/
public ApiClient setDebugging(boolean debugging) {
// TODO: implement debugging mode
this.debugging = debugging;
return this;
}
/**
* Connect timeout (in milliseconds).
* @return Connection timeout
*/
public int getConnectTimeout() {
return connectionTimeout;
}
/**
* Set the connect timeout (in milliseconds).
* A value of 0 means no timeout, otherwise values must be between 1 and
* {@link Integer#MAX_VALUE}.
* @param connectionTimeout Connection timeout in milliseconds
* @return API client
*/
public ApiClient setConnectTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
return this;
}
/**
* Get the date format used to parse/format date parameters.
* @return Date format
*/
public DateFormat getDateFormat() {
return dateFormat;
}
/**
* Set the date format used to parse/format date parameters.
* @param dateFormat Date format
* @return API client
*/
public ApiClient setDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
// Also set the date format for model (de)serialization with Date properties.
this.objectMapper.setDateFormat((DateFormat) dateFormat.clone());
return this;
}
/**
* Parse the given string into Date object.
* @param str String
* @return Date
*/
public Date parseDate(String str) {
try {
return dateFormat.parse(str);
} catch (java.text.ParseException e) {
throw new RuntimeException(e);
}
}
/**
* Format the given Date object into string.
* @param date Date
* @return Date in string format
*/
public String formatDate(Date date) {
return dateFormat.format(date);
}
/**
* Format the given parameter object into string.
* @param param Object
* @return Object in string format
*/
public String parameterToString(Object param) {
if (param == null) {
return "";
} else if (param instanceof Date) {
return formatDate((Date) param);
} {{#jsr310}}else if (param instanceof OffsetDateTime) {
return formatOffsetDateTime((OffsetDateTime) param);
} {{/jsr310}}else if (param instanceof Collection) {
StringBuilder b = new StringBuilder();
for(Object o : (Collection>)param) {
if(b.length() > 0) {
b.append(',');
}
b.append(String.valueOf(o));
}
return b.toString();
} else {
return String.valueOf(param);
}
}
/**
* Formats the specified query parameter to a list containing a single {@code Pair} object.
*
* Note that {@code value} must not be a collection.
*
* @param name The name of the parameter.
* @param value The value of the parameter.
* @return A list containing a single {@code Pair} object.
*/
public List parameterToPair(String name, Object value) {
List params = new ArrayList();
// preconditions
if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params;
params.add(new Pair(name, parameterToString(value)));
return params;
}
/**
* Formats the specified collection query parameters to a list of {@code Pair} objects.
*
* Note that the values of each of the returned Pair objects are percent-encoded.
*
* @param collectionFormat The collection format of the parameter.
* @param name The name of the parameter.
* @param value The value of the parameter.
* @return A list of {@code Pair} objects.
*/
public List parameterToPairs(String collectionFormat, String name, Collection value) {
List params = new ArrayList();
// preconditions
if (name == null || name.isEmpty() || value == null) {
return params;
}
// create the params based on the collection format
if ("multi".equals(collectionFormat)) {
for (Object item : value) {
params.add(new Pair(name, escapeString(parameterToString(item))));
}
return params;
}
// collectionFormat is assumed to be "csv" by default
String delimiter = ",";
// escape all delimiters except commas, which are URI reserved
// characters
if ("ssv".equals(collectionFormat)) {
delimiter = escapeString(" ");
} else if ("tsv".equals(collectionFormat)) {
delimiter = escapeString("\t");
} else if ("pipes".equals(collectionFormat)) {
delimiter = escapeString("|");
}
StringBuilder sb = new StringBuilder() ;
for (Object item : value) {
sb.append(delimiter);
sb.append(escapeString(parameterToString(item)));
}
params.add(new Pair(name, sb.substring(delimiter.length())));
return params;
}
/**
* Check if the given MIME is a JSON MIME.
* JSON MIME examples:
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
* application/vnd.company+json
* @param mime MIME
* @return True if MIME type is boolean
*/
public boolean isJsonMime(String mime) {
String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
}
/**
* Select the Accept header's value from the given accepts array:
* if JSON exists in the given array, use it;
* otherwise use all of them (joining into a string)
*
* @param accepts The accepts array to select from
* @return The Accept header to use. If the given array is empty,
* null will be returned (not to set the Accept header explicitly).
*/
public String selectHeaderAccept(String[] accepts) {
if (accepts.length == 0) {
return null;
}
for (String accept : accepts) {
if (isJsonMime(accept)) {
return accept;
}
}
return StringUtil.join(accepts, ",");
}
/**
* Select the Content-Type header's value from the given array:
* if JSON exists in the given array, use it;
* otherwise use the first one of the array.
*
* @param contentTypes The Content-Type array to select from
* @return The Content-Type header to use. If the given array is empty,
* or matches "any", JSON will be used.
*/
public String selectHeaderContentType(String[] contentTypes) {
if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) {
return "application/json";
}
for (String contentType : contentTypes) {
if (isJsonMime(contentType)) {
return contentType;
}
}
return contentTypes[0];
}
/**
* Escape the given string to be used as URL query value.
* @param str String
* @return Escaped string
*/
public String escapeString(String str) {
try {
return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
return str;
}
}
/**
* Transform response headers into map
*/
protected Map> transformResponseHeaders(Header[] headers) {
Map> headersMap = new HashMap<>();
for (Header header : headers) {
List valuesList = headersMap.get(header.getName());
if (valuesList != null) {
valuesList.add(header.getValue());
} else {
valuesList = new ArrayList<>();
valuesList.add(header.getValue());
headersMap.put(header.getName(), valuesList);
}
}
return headersMap;
}
/**
* Parse content type object from header value
*/
private ContentType getContentType(String headerValue) throws ApiException {
try {
return ContentType.parse(headerValue);
} catch (ParseException e) {
throw new ApiException("Could not parse content type " + headerValue);
}
}
/**
* Get content type of a response or null if one was not provided
*/
private String getResponseMimeType(HttpResponse response) throws ApiException {
Header contentTypeHeader = response.getFirstHeader("Content-Type");
if (contentTypeHeader != null) {
return getContentType(contentTypeHeader.getValue()).getMimeType();
}
return null;
}
/**
* Serialize the given Java object into string according the given
* Content-Type (only JSON is supported for now).
* @param obj Object
* @param contentType Content type
* @param formParams Form parameters
* @return Object
* @throws ApiException API exception
*/
public HttpEntity serialize(Object obj, Map formParams, ContentType contentType) throws ApiException {
String mimeType = contentType.getMimeType();
if (isJsonMime(mimeType)) {
try {
return new StringEntity(objectMapper.writeValueAsString(obj), contentType);
} catch (JsonProcessingException e) {
throw new ApiException(e);
}
} else if (mimeType.equals(ContentType.MULTIPART_FORM_DATA.getMimeType())) {
MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create();
for (Entry paramEntry : formParams.entrySet()) {
Object value = paramEntry.getValue();
if (value instanceof File) {
multiPartBuilder.addBinaryBody(paramEntry.getKey(), (File) value);
} else if (value instanceof byte[]) {
multiPartBuilder.addBinaryBody(paramEntry.getKey(), (byte[]) value);
} else {
multiPartBuilder.addTextBody(paramEntry.getKey(), parameterToString(paramEntry.getValue()));
}
}
return multiPartBuilder.build();
} else if (mimeType.equals(ContentType.APPLICATION_FORM_URLENCODED.getMimeType())) {
List formValues = new ArrayList<>();
for (Entry paramEntry : formParams.entrySet()) {
formValues.add(new BasicNameValuePair(paramEntry.getKey(), parameterToString(paramEntry.getValue())));
}
try {
return new UrlEncodedFormEntity(formValues);
} catch (UnsupportedEncodingException e) {
throw new ApiException(e);
}
} else {
// Handle files with unknown content type
if (obj instanceof File) {
return new FileEntity((File) obj, contentType);
} else if (obj instanceof byte[]) {
return new ByteArrayEntity((byte[]) obj, contentType);
}
throw new ApiException("Serialization for content type '" + contentType + "' not supported");
}
}
/**
* Deserialize response content
*/
public T deserialize(HttpResponse response, TypeReference valueType) throws ApiException, IOException {
if (valueType == null) {
return null;
}
HttpEntity entity = response.getEntity();
Type valueRawType = valueType.getType();
if (valueRawType.equals(byte[].class)) {
return (T) EntityUtils.toByteArray(entity);
} else if (valueRawType.equals(File.class)) {
return (T) downloadFileFromResponse(response);
}
String mimeType = getResponseMimeType(response);
if (mimeType == null || isJsonMime(mimeType)) {
// Assume json if no mime type
return objectMapper.readValue(entity.getContent(), valueType);
} else {
throw new ApiException(
"Deserialization for content type '" + mimeType + "' not supported for type '" + valueType + "'",
response.getStatusLine().getStatusCode(),
responseHeaders,
EntityUtils.toString(entity)
);
}
}
private File downloadFileFromResponse(HttpResponse response) throws IOException {
Header contentDispositionHeader = response.getFirstHeader("Content-Disposition");
String contentDisposition = contentDispositionHeader == null ? null : contentDispositionHeader.getValue();
File file = prepareDownloadFile(contentDisposition);
Files.copy(response.getEntity().getContent(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
return file;
}
protected File prepareDownloadFile(String contentDisposition) throws IOException {
String filename = null;
if (contentDisposition != null && !"".equals(contentDisposition)) {
// Get filename from the Content-Disposition header.
Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?");
Matcher matcher = pattern.matcher(contentDisposition);
if (matcher.find())
filename = matcher.group(1);
}
String prefix;
String suffix = null;
if (filename == null) {
prefix = "download-";
suffix = "";
} else {
int pos = filename.lastIndexOf('.');
if (pos == -1) {
prefix = filename + "-";
} else {
prefix = filename.substring(0, pos) + "-";
suffix = filename.substring(pos);
}
// Files.createTempFile requires the prefix to be at least three characters long
if (prefix.length() < 3)
prefix = "download-";
}
if (tempFolderPath == null)
return Files.createTempFile(prefix, suffix).toFile();
else
return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile();
}
/**
* Build full URL by concatenating base path, the given sub path and query parameters.
*
* @param path The sub path
* @param queryParams The query parameters
* @param collectionQueryParams The collection query parameters
* @return The full URL
*/
private String buildUrl(String path, List queryParams, List collectionQueryParams) {
String baseURL;
if (serverIndex != null) {
if (serverIndex < 0 || serverIndex >= servers.size()) {
throw new ArrayIndexOutOfBoundsException(String.format(
"Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size()
));
}
baseURL = servers.get(serverIndex).URL(serverVariables);
} else {
baseURL = basePath;
}
final StringBuilder url = new StringBuilder();
url.append(baseURL).append(path);
if (queryParams != null && !queryParams.isEmpty()) {
// support (constant) query string in `path`, e.g. "/posts?draft=1"
String prefix = path.contains("?") ? "&" : "?";
for (Pair param : queryParams) {
if (param.getValue() != null) {
if (prefix != null) {
url.append(prefix);
prefix = null;
} else {
url.append("&");
}
String value = parameterToString(param.getValue());
url.append(escapeString(param.getName())).append("=").append(escapeString(value));
}
}
}
if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) {
String prefix = url.toString().contains("?") ? "&" : "?";
for (Pair param : collectionQueryParams) {
if (param.getValue() != null) {
if (prefix != null) {
url.append(prefix);
prefix = null;
} else {
url.append("&");
}
String value = parameterToString(param.getValue());
// collection query parameter value already escaped as part of parameterToPairs
url.append(escapeString(param.getName())).append("=").append(value);
}
}
}
return url.toString();
}
protected boolean isSuccessfulStatus(int statusCode) {
return statusCode >= 200 && statusCode < 300;
}
protected boolean isBodyAllowed(String method) {
return bodyMethods.contains(method);
}
protected Cookie buildCookie(String key, String value, URI uri) {
BasicClientCookie cookie = new BasicClientCookie(key, value);
cookie.setDomain(uri.getHost());
cookie.setPath("/");
return cookie;
}
protected T processResponse(CloseableHttpResponse response, TypeReference returnType) throws ApiException, IOException {
statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_NO_CONTENT) {
return null;
}
responseHeaders = transformResponseHeaders(response.getAllHeaders());
if (isSuccessfulStatus(statusCode)) {
return this.deserialize(response, returnType);
} else {
String message = EntityUtils.toString(response.getEntity());
throw new ApiException(message, statusCode, responseHeaders, message);
}
}
/**
* Invoke API by sending HTTP request with the given options.
*
* @param Type
* @param path The sub-path of the HTTP URL
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
* @param queryParams The query parameters
* @param collectionQueryParams The collection query parameters
* @param body The request body object - if it is not binary, otherwise null
* @param headerParams The header parameters
* @param cookieParams The cookie parameters
* @param formParams The form parameters
* @param accept The request's Accept header
* @param contentType The request's Content-Type header
* @param authNames The authentications to apply
* @param returnType Return type
* @return The response body in type of string
* @throws ApiException API exception
*/
public T invokeAPI(
String path,
String method,
List queryParams,
List collectionQueryParams,
Object body,
Map headerParams,
Map cookieParams,
Map formParams,
String accept,
String contentType,
String[] authNames,
TypeReference returnType) throws ApiException {
if (body != null && !formParams.isEmpty()) {
throw new ApiException("Cannot have body and form params");
}
updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);
final String url = buildUrl(path, queryParams, collectionQueryParams);
RequestBuilder builder = RequestBuilder.create(method);
builder.setUri(url);
RequestConfig config = RequestConfig.custom()
.setConnectionRequestTimeout(connectionTimeout)
.build();
builder.setConfig(config);
if (accept != null) {
builder.addHeader("Accept", accept);
}
for (Entry keyValue : headerParams.entrySet()) {
builder.addHeader(keyValue.getKey(), keyValue.getValue());
}
for (Map.Entry keyValue : defaultHeaderMap.entrySet()) {
if (!headerParams.containsKey(keyValue.getKey())) {
builder.addHeader(keyValue.getKey(), keyValue.getValue());
}
}
BasicCookieStore store = new BasicCookieStore();
for (Entry keyValue : cookieParams.entrySet()) {
store.addCookie(buildCookie(keyValue.getKey(), keyValue.getValue(), builder.getUri()));
}
for (Entry keyValue : defaultCookieMap.entrySet()) {
if (!cookieParams.containsKey(keyValue.getKey())) {
store.addCookie(buildCookie(keyValue.getKey(), keyValue.getValue(), builder.getUri()));
}
}
HttpClientContext context = HttpClientContext.create();
context.setCookieStore(store);
ContentType contentTypeObj = getContentType(contentType);
if (body != null || !formParams.isEmpty()) {
if (isBodyAllowed(method)) {
// Add entity if we have content and a valid method
builder.setEntity(serialize(body, formParams, contentTypeObj));
} else {
throw new ApiException("method " + method + " does not support a request body");
}
}
try (CloseableHttpResponse response = httpClient.execute(builder.build(), context)) {
return processResponse(response, returnType);
} catch (IOException e) {
throw new ApiException(e);
}
}
/**
* Update query and header parameters based on authentication settings.
*
* @param authNames The authentications to apply
* @param queryParams Query parameters
* @param headerParams Header parameters
* @param cookieParams Cookie parameters
*/
private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) {
for (String authName : authNames) {
Authentication auth = authentications.get(authName);
if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);
auth.applyToParams(queryParams, headerParams, cookieParams);
}
}
}