github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/java/libraries/feign/ApiClient.mustache (about) 1 package {{invokerPackage}}; 2 3 import java.util.LinkedHashMap; 4 import java.util.Map; 5 6 {{#hasOAuthMethods}} 7 import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; 8 import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; 9 {{/hasOAuthMethods}} 10 11 {{#threetenbp}} 12 import org.threeten.bp.*; 13 {{/threetenbp}} 14 15 import com.fasterxml.jackson.databind.DeserializationFeature; 16 import com.fasterxml.jackson.databind.ObjectMapper; 17 import com.fasterxml.jackson.databind.SerializationFeature; 18 import org.openapitools.jackson.nullable.JsonNullableModule; 19 {{#joda}} 20 import com.fasterxml.jackson.datatype.joda.JodaModule; 21 {{/joda}} 22 {{#java8}} 23 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 24 {{/java8}} 25 {{#threetenbp}} 26 import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; 27 {{/threetenbp}} 28 29 import feign.Feign; 30 import feign.RequestInterceptor; 31 import feign.form.FormEncoder; 32 import feign.jackson.JacksonDecoder; 33 import feign.jackson.JacksonEncoder; 34 import feign.slf4j.Slf4jLogger; 35 import {{invokerPackage}}.auth.*; 36 {{#hasOAuthMethods}} 37 import {{invokerPackage}}.auth.OAuth.AccessTokenListener; 38 {{/hasOAuthMethods}} 39 40 {{>generatedAnnotation}} 41 public class ApiClient { 42 public interface Api {} 43 44 protected ObjectMapper objectMapper; 45 private String basePath = "{{{basePath}}}"; 46 private Map<String, RequestInterceptor> apiAuthorizations; 47 private Feign.Builder feignBuilder; 48 49 public ApiClient() { 50 objectMapper = createObjectMapper(); 51 apiAuthorizations = new LinkedHashMap<String, RequestInterceptor>(); 52 feignBuilder = Feign.builder() 53 .encoder(new FormEncoder(new JacksonEncoder(objectMapper))) 54 .decoder(new JacksonDecoder(objectMapper)) 55 .logger(new Slf4jLogger()); 56 } 57 58 public ApiClient(String[] authNames) { 59 this(); 60 for(String authName : authNames) { 61 {{#hasAuthMethods}} 62 RequestInterceptor auth; 63 {{#authMethods}}if ("{{name}}".equals(authName)) { 64 {{#isBasic}} 65 {{#isBasicBasic}} 66 auth = new HttpBasicAuth(); 67 {{/isBasicBasic}} 68 {{^isBasicBasic}} 69 auth = new HttpBearerAuth("{{scheme}}"); 70 {{/isBasicBasic}} 71 {{/isBasic}} 72 {{#isApiKey}} 73 auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); 74 {{/isApiKey}} 75 {{#isOAuth}} 76 auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); 77 {{/isOAuth}} 78 } else {{/authMethods}}{ 79 throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); 80 } 81 addAuthorization(authName, auth); 82 {{/hasAuthMethods}} 83 {{^hasAuthMethods}} 84 throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); 85 {{/hasAuthMethods}} 86 } 87 } 88 89 /** 90 * Basic constructor for single auth name 91 * @param authName 92 */ 93 public ApiClient(String authName) { 94 this(new String[]{authName}); 95 } 96 97 /** 98 * Helper constructor for single api key 99 * @param authName 100 * @param apiKey 101 */ 102 public ApiClient(String authName, String apiKey) { 103 this(authName); 104 this.setApiKey(apiKey); 105 } 106 107 /** 108 * Helper constructor for single basic auth or password oauth2 109 * @param authName 110 * @param username 111 * @param password 112 */ 113 public ApiClient(String authName, String username, String password) { 114 this(authName); 115 this.setCredentials(username, password); 116 } 117 118 {{#hasOAuthMethods}} 119 /** 120 * Helper constructor for single password oauth2 121 * @param authName 122 * @param clientId 123 * @param secret 124 * @param username 125 * @param password 126 */ 127 public ApiClient(String authName, String clientId, String secret, String username, String password) { 128 this(authName); 129 this.getTokenEndPoint() 130 .setClientId(clientId) 131 .setClientSecret(secret) 132 .setUsername(username) 133 .setPassword(password); 134 } 135 136 {{/hasOAuthMethods}} 137 public String getBasePath() { 138 return basePath; 139 } 140 141 public ApiClient setBasePath(String basePath) { 142 this.basePath = basePath; 143 return this; 144 } 145 146 public Map<String, RequestInterceptor> getApiAuthorizations() { 147 return apiAuthorizations; 148 } 149 150 public void setApiAuthorizations(Map<String, RequestInterceptor> apiAuthorizations) { 151 this.apiAuthorizations = apiAuthorizations; 152 } 153 154 public Feign.Builder getFeignBuilder() { 155 return feignBuilder; 156 } 157 158 public ApiClient setFeignBuilder(Feign.Builder feignBuilder) { 159 this.feignBuilder = feignBuilder; 160 return this; 161 } 162 163 private ObjectMapper createObjectMapper() { 164 ObjectMapper objectMapper = new ObjectMapper(); 165 objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); 166 objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); 167 objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 168 objectMapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); 169 objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 170 objectMapper.setDateFormat(new RFC3339DateFormat()); 171 {{#joda}} 172 objectMapper.registerModule(new JodaModule()); 173 {{/joda}} 174 {{#java8}} 175 objectMapper.registerModule(new JavaTimeModule()); 176 {{/java8}} 177 {{#threetenbp}} 178 ThreeTenModule module = new ThreeTenModule(); 179 module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); 180 module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); 181 module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); 182 objectMapper.registerModule(module); 183 {{/threetenbp}} 184 JsonNullableModule jnm = new JsonNullableModule(); 185 objectMapper.registerModule(jnm); 186 return objectMapper; 187 } 188 189 public ObjectMapper getObjectMapper(){ 190 return objectMapper; 191 } 192 193 /** 194 * Creates a feign client for given API interface. 195 * 196 * Usage: 197 * ApiClient apiClient = new ApiClient(); 198 * apiClient.setBasePath("http://localhost:8080"); 199 * XYZApi api = apiClient.buildClient(XYZApi.class); 200 * XYZResponse response = api.someMethod(...); 201 * @param <T> Type 202 * @param clientClass Client class 203 * @return The Client 204 */ 205 public <T extends Api> T buildClient(Class<T> clientClass) { 206 return feignBuilder.target(clientClass, basePath); 207 } 208 209 /** 210 * Select the Accept header's value from the given accepts array: 211 * if JSON exists in the given array, use it; 212 * otherwise use all of them (joining into a string) 213 * 214 * @param accepts The accepts array to select from 215 * @return The Accept header to use. If the given array is empty, 216 * null will be returned (not to set the Accept header explicitly). 217 */ 218 public String selectHeaderAccept(String[] accepts) { 219 if (accepts.length == 0) return null; 220 if (StringUtil.containsIgnoreCase(accepts, "application/json")) return "application/json"; 221 return StringUtil.join(accepts, ","); 222 } 223 224 /** 225 * Select the Content-Type header's value from the given array: 226 * if JSON exists in the given array, use it; 227 * otherwise use the first one of the array. 228 * 229 * @param contentTypes The Content-Type array to select from 230 * @return The Content-Type header to use. If the given array is empty, 231 * JSON will be used. 232 */ 233 public String selectHeaderContentType(String[] contentTypes) { 234 if (contentTypes.length == 0) return "application/json"; 235 if (StringUtil.containsIgnoreCase(contentTypes, "application/json")) return "application/json"; 236 return contentTypes[0]; 237 } 238 239 240 /** 241 * Helper method to configure the bearer token. 242 * @param bearerToken the bearer token. 243 */ 244 public void setBearerToken(String bearerToken) { 245 for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { 246 if (apiAuthorization instanceof HttpBearerAuth) { 247 ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); 248 return; 249 } 250 } 251 throw new RuntimeException("No Bearer authentication configured!"); 252 } 253 254 /** 255 * Helper method to configure the first api key found 256 * @param apiKey API key 257 */ 258 public void setApiKey(String apiKey) { 259 for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { 260 if (apiAuthorization instanceof ApiKeyAuth) { 261 ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; 262 keyAuth.setApiKey(apiKey); 263 return ; 264 } 265 } 266 throw new RuntimeException("No API key authentication configured!"); 267 } 268 269 /** 270 * Helper method to configure the username/password for basic auth or password OAuth 271 * @param username Username 272 * @param password Password 273 */ 274 public void setCredentials(String username, String password) { 275 for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { 276 if (apiAuthorization instanceof HttpBasicAuth) { 277 HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; 278 basicAuth.setCredentials(username, password); 279 return; 280 } 281 {{#hasOAuthMethods}} 282 if (apiAuthorization instanceof OAuth) { 283 OAuth oauth = (OAuth) apiAuthorization; 284 oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); 285 return; 286 } 287 {{/hasOAuthMethods}} 288 } 289 throw new RuntimeException("No Basic authentication or OAuth configured!"); 290 } 291 292 {{#hasOAuthMethods}} 293 /** 294 * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) 295 * @return Token request builder 296 */ 297 public TokenRequestBuilder getTokenEndPoint() { 298 for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { 299 if (apiAuthorization instanceof OAuth) { 300 OAuth oauth = (OAuth) apiAuthorization; 301 return oauth.getTokenRequestBuilder(); 302 } 303 } 304 return null; 305 } 306 307 /** 308 * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) 309 * @return Authentication request builder 310 */ 311 public AuthenticationRequestBuilder getAuthorizationEndPoint() { 312 for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { 313 if (apiAuthorization instanceof OAuth) { 314 OAuth oauth = (OAuth) apiAuthorization; 315 return oauth.getAuthenticationRequestBuilder(); 316 } 317 } 318 return null; 319 } 320 321 /** 322 * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) 323 * @param accessToken Access Token 324 * @param expiresIn Validity period in seconds 325 */ 326 public void setAccessToken(String accessToken, Long expiresIn) { 327 for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { 328 if (apiAuthorization instanceof OAuth) { 329 OAuth oauth = (OAuth) apiAuthorization; 330 oauth.setAccessToken(accessToken, expiresIn); 331 return; 332 } 333 } 334 } 335 336 /** 337 * Helper method to configure the oauth accessCode/implicit flow parameters 338 * @param clientId Client ID 339 * @param clientSecret Client secret 340 * @param redirectURI Redirect URI 341 */ 342 public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { 343 for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { 344 if (apiAuthorization instanceof OAuth) { 345 OAuth oauth = (OAuth) apiAuthorization; 346 oauth.getTokenRequestBuilder() 347 .setClientId(clientId) 348 .setClientSecret(clientSecret) 349 .setRedirectURI(redirectURI); 350 oauth.getAuthenticationRequestBuilder() 351 .setClientId(clientId) 352 .setRedirectURI(redirectURI); 353 return; 354 } 355 } 356 } 357 358 /** 359 * Configures a listener which is notified when a new access token is received. 360 * @param accessTokenListener Acesss token listener 361 */ 362 public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { 363 for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { 364 if (apiAuthorization instanceof OAuth) { 365 OAuth oauth = (OAuth) apiAuthorization; 366 oauth.registerAccessTokenListener(accessTokenListener); 367 return; 368 } 369 } 370 } 371 372 {{/hasOAuthMethods}} 373 /** 374 * Gets request interceptor based on authentication name 375 * @param authName Authentiation name 376 * @return Request Interceptor 377 */ 378 public RequestInterceptor getAuthorization(String authName) { 379 return apiAuthorizations.get(authName); 380 } 381 382 /** 383 * Adds an authorization to be used by the client 384 * @param authName Authentication name 385 * @param authorization Request interceptor 386 */ 387 public void addAuthorization(String authName, RequestInterceptor authorization) { 388 if (apiAuthorizations.containsKey(authName)) { 389 throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); 390 } 391 apiAuthorizations.put(authName, authorization); 392 feignBuilder.requestInterceptor(authorization); 393 } 394 395 }