github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/java/libraries/native/ApiClient.mustache (about) 1 {{>licenseInfo}} 2 package {{invokerPackage}}; 3 4 import com.fasterxml.jackson.annotation.JsonInclude; 5 import com.fasterxml.jackson.databind.DeserializationFeature; 6 import com.fasterxml.jackson.databind.ObjectMapper; 7 import com.fasterxml.jackson.databind.SerializationFeature; 8 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 9 import org.openapitools.jackson.nullable.JsonNullableModule; 10 11 import java.io.InputStream; 12 import java.net.URI; 13 import java.net.URLEncoder; 14 import java.net.http.HttpClient; 15 import java.net.http.HttpRequest; 16 import java.net.http.HttpResponse; 17 import java.nio.charset.Charset; 18 import java.time.Duration; 19 import java.util.Collection; 20 import java.util.Collections; 21 import java.util.List; 22 import java.util.StringJoiner; 23 import java.util.function.Consumer; 24 import java.util.stream.Collectors; 25 26 /** 27 * Configuration and utility class for API clients. 28 * 29 * <p>This class can be constructed and modified, then used to instantiate the 30 * various API classes. The API classes use the settings in this class to 31 * configure themselves, but otherwise do not store a link to this class.</p> 32 * 33 * <p>This class is mutable and not synchronized, so it is not thread-safe. 34 * The API classes generated from this are immutable and thread-safe.</p> 35 * 36 * <p>The setter methods of this class return the current object to facilitate 37 * a fluent style of configuration.</p> 38 */ 39 {{>generatedAnnotation}} 40 public class ApiClient { 41 42 private static final Charset UTF_8 = Charset.forName("UTF-8"); 43 44 private HttpClient.Builder builder; 45 private ObjectMapper mapper; 46 private String scheme; 47 private String host; 48 private int port; 49 private String basePath; 50 private Consumer<HttpRequest.Builder> interceptor; 51 private Consumer<HttpResponse<InputStream>> responseInterceptor; 52 private Duration readTimeout; 53 54 private static String valueToString(Object value) { 55 if (value == null) { 56 return ""; 57 } 58 return value.toString(); 59 } 60 61 /** 62 * URL encode a string in the UTF-8 encoding. 63 * 64 * @param s String to encode. 65 * @return URL-encoded representation of the input string. 66 */ 67 public static String urlEncode(String s) { 68 return URLEncoder.encode(s, UTF_8); 69 } 70 71 /** 72 * Convert a URL query name/value parameter to a list of encoded {@link Pair} 73 * objects. 74 * 75 * <p>The value can be null, in which case an empty list is returned.</p> 76 * 77 * @param name The query name parameter. 78 * @param value The query value, which may not be a collection but may be 79 * null. 80 * @return A singleton list of the {@link Pair} objects representing the input 81 * parameters, which is encoded for use in a URL. If the value is null, an 82 * empty list is returned. 83 */ 84 public static List<Pair> parameterToPairs(String name, Object value) { 85 if (name == null || name.isEmpty() || value == null) { 86 return Collections.emptyList(); 87 } 88 return Collections.singletonList(new Pair(urlEncode(name), urlEncode(value.toString()))); 89 } 90 91 /** 92 * Convert a URL query name/collection parameter to a list of encoded 93 * {@link Pair} objects. 94 * 95 * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). 96 * @param name The query name parameter. 97 * @param values A collection of values for the given query name, which may be 98 * null. 99 * @return A list of {@link Pair} objects representing the input parameters, 100 * which is encoded for use in a URL. If the values collection is null, an 101 * empty list is returned. 102 */ 103 public static List<Pair> parameterToPairs( 104 String collectionFormat, String name, Collection<?> values) { 105 if (name == null || name.isEmpty() || values == null || values.isEmpty()) { 106 return Collections.emptyList(); 107 } 108 109 // get the collection format (default: csv) 110 String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; 111 112 // create the params based on the collection format 113 if ("multi".equals(format)) { 114 return values.stream() 115 .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) 116 .collect(Collectors.toList()); 117 } 118 119 String delimiter; 120 switch(format) { 121 case "csv": 122 delimiter = urlEncode(","); 123 break; 124 case "ssv": 125 delimiter = urlEncode(" "); 126 break; 127 case "tsv": 128 delimiter = urlEncode("\t"); 129 break; 130 case "pipes": 131 delimiter = urlEncode("|"); 132 break; 133 default: 134 throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); 135 } 136 137 StringJoiner joiner = new StringJoiner(delimiter); 138 for (Object value : values) { 139 joiner.add(urlEncode(valueToString(value))); 140 } 141 142 return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); 143 } 144 145 /** 146 * Ctor. 147 */ 148 public ApiClient() { 149 builder = HttpClient.newBuilder(); 150 mapper = new ObjectMapper(); 151 mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 152 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 153 mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); 154 mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 155 mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); 156 mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); 157 mapper.registerModule(new JavaTimeModule()); 158 JsonNullableModule jnm = new JsonNullableModule(); 159 mapper.registerModule(jnm); 160 URI baseURI = URI.create("{{{basePath}}}"); 161 scheme = baseURI.getScheme(); 162 host = baseURI.getHost(); 163 port = baseURI.getPort(); 164 basePath = baseURI.getRawPath(); 165 interceptor = null; 166 readTimeout = null; 167 responseInterceptor = null; 168 } 169 170 /** 171 * Set a custom {@link HttpClient.Builder} object to use when creating the 172 * {@link HttpClient} that is used by the API client. 173 * 174 * @param builder Custom client builder. 175 * @return This object. 176 */ 177 public ApiClient setHttpClientBuilder(HttpClient.Builder builder) { 178 this.builder = builder; 179 return this; 180 } 181 182 /** 183 * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. 184 * 185 * <p>The returned object is immutable and thread-safe.</p> 186 * 187 * @return The HTTP client. 188 */ 189 public HttpClient getHttpClient() { 190 return builder.build(); 191 } 192 193 /** 194 * Set a custom {@link ObjectMapper} to serialize and deserialize the request 195 * and response bodies. 196 * 197 * @param mapper Custom object mapper. 198 * @return This object. 199 */ 200 public ApiClient setObjectMapper(ObjectMapper mapper) { 201 this.mapper = mapper; 202 return this; 203 } 204 205 /** 206 * Get a copy of the current {@link ObjectMapper}. 207 * 208 * @return A copy of the current object mapper. 209 */ 210 public ObjectMapper getObjectMapper() { 211 return mapper.copy(); 212 } 213 214 /** 215 * Set a custom host name for the target service. 216 * 217 * @param host The host name of the target service. 218 * @return This object. 219 */ 220 public ApiClient setHost(String host) { 221 this.host = host; 222 return this; 223 } 224 225 /** 226 * Set a custom port number for the target service. 227 * 228 * @param port The port of the target service. Set this to -1 to reset the 229 * value to the default for the scheme. 230 * @return This object. 231 */ 232 public ApiClient setPort(int port) { 233 this.port = port; 234 return this; 235 } 236 237 /** 238 * Set a custom base path for the target service, for example '/v2'. 239 * 240 * @param basePath The base path against which the rest of the path is 241 * resolved. 242 * @return This object. 243 */ 244 public ApiClient setBasePath(String basePath) { 245 this.basePath = basePath; 246 return this; 247 } 248 249 /** 250 * Get the base URI to resolve the endpoint paths against. 251 * 252 * @return The complete base URI that the rest of the API parameters are 253 * resolved against. 254 */ 255 public String getBaseUri() { 256 return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; 257 } 258 259 /** 260 * Set a custom scheme for the target service, for example 'https'. 261 * 262 * @param scheme The scheme of the target service 263 * @return This object. 264 */ 265 public ApiClient setScheme(String scheme){ 266 this.scheme = scheme; 267 return this; 268 } 269 270 /** 271 * Set a custom request interceptor. 272 * 273 * <p>A request interceptor is a mechanism for altering each request before it 274 * is sent. After the request has been fully configured but not yet built, the 275 * request builder is passed into this function for further modification, 276 * after which it is sent out.</p> 277 * 278 * <p>This is useful for altering the requests in a custom manner, such as 279 * adding headers. It could also be used for logging and monitoring.</p> 280 * 281 * @param interceptor A function invoked before creating each request. A value 282 * of null resets the interceptor to a no-op. 283 * @return This object. 284 */ 285 public ApiClient setRequestInterceptor(Consumer<HttpRequest.Builder> interceptor) { 286 this.interceptor = interceptor; 287 return this; 288 } 289 290 /** 291 * Get the custom interceptor. 292 * 293 * @return The custom interceptor that was set, or null if there isn't any. 294 */ 295 public Consumer<HttpRequest.Builder> getRequestInterceptor() { 296 return interceptor; 297 } 298 299 /** 300 * Set a custom response interceptor. 301 * 302 * <p>This is useful for logging, monitoring or extraction of header variables</p> 303 * 304 * @param interceptor A function invoked before creating each request. A value 305 * of null resets the interceptor to a no-op. 306 * @return This object. 307 */ 308 public ApiClient setResponseInterceptor(Consumer<HttpResponse<InputStream>> interceptor) { 309 this.responseInterceptor = interceptor; 310 return this; 311 } 312 313 /** 314 * Get the custom response interceptor. 315 * 316 * @return The custom interceptor that was set, or null if there isn't any. 317 */ 318 public Consumer<HttpResponse<InputStream>> getResponseInterceptor() { 319 return responseInterceptor; 320 } 321 322 /** 323 * Set the read timeout for the http client. 324 * 325 * <p>This is the value used by default for each request, though it can be 326 * overridden on a per-request basis with a request interceptor.</p> 327 * 328 * @param readTimeout The read timeout used by default by the http client. 329 * Setting this value to null resets the timeout to an 330 * effectively infinite value. 331 * @return This object. 332 */ 333 public ApiClient setReadTimeout(Duration readTimeout) { 334 this.readTimeout = readTimeout; 335 return this; 336 } 337 338 /** 339 * Get the read timeout that was set. 340 * 341 * @return The read timeout, or null if no timeout was set. Null represents 342 * an infinite wait time. 343 */ 344 public Duration getReadTimeout() { 345 return readTimeout; 346 } 347 }