github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/java/libraries/webclient/ApiClient.mustache (about)

     1  package {{invokerPackage}};
     2  
     3  import com.fasterxml.jackson.databind.DeserializationFeature;
     4  import com.fasterxml.jackson.databind.ObjectMapper;
     5  import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
     6  import org.openapitools.jackson.nullable.JsonNullableModule;
     7  import org.apache.commons.logging.Log;
     8  import org.apache.commons.logging.LogFactory;
     9  import org.springframework.core.ParameterizedTypeReference;
    10  import org.springframework.http.HttpHeaders;
    11  import org.springframework.http.HttpMethod;
    12  import org.springframework.http.HttpRequest;
    13  import org.springframework.http.HttpStatus;
    14  import org.springframework.http.InvalidMediaTypeException;
    15  import org.springframework.http.MediaType;
    16  import org.springframework.http.RequestEntity;
    17  import org.springframework.http.RequestEntity.BodyBuilder;
    18  import org.springframework.http.ResponseEntity;
    19  import org.springframework.http.client.BufferingClientHttpRequestFactory;
    20  import org.springframework.http.client.ClientHttpRequestExecution;
    21  import org.springframework.http.client.ClientHttpRequestInterceptor;
    22  import org.springframework.http.client.ClientHttpResponse;
    23  import org.springframework.http.codec.json.Jackson2JsonDecoder;
    24  import org.springframework.http.codec.json.Jackson2JsonEncoder;
    25  import org.springframework.util.LinkedMultiValueMap;
    26  import org.springframework.util.MultiValueMap;
    27  import org.springframework.util.StringUtils;
    28  import org.springframework.http.client.reactive.ClientHttpRequest;
    29  import org.springframework.web.client.RestClientException;
    30  import org.springframework.web.util.UriComponentsBuilder;
    31  import org.springframework.web.reactive.function.client.WebClient;
    32  import org.springframework.web.reactive.function.client.ClientResponse;
    33  import org.springframework.web.reactive.function.BodyInserter;
    34  import org.springframework.web.reactive.function.BodyInserters;
    35  import org.springframework.web.reactive.function.client.ExchangeStrategies;
    36  import reactor.core.publisher.Mono;
    37  import reactor.core.publisher.Flux;
    38  import java.util.Optional;
    39  
    40  import java.io.BufferedReader;
    41  import java.io.IOException;
    42  import java.io.InputStream;
    43  import java.io.InputStreamReader;
    44  import java.io.UnsupportedEncodingException;
    45  import java.net.URLEncoder;
    46  import java.nio.charset.StandardCharsets;
    47  import java.text.DateFormat;
    48  import java.text.ParseException;
    49  import java.util.Arrays;
    50  import java.util.ArrayList;
    51  import java.util.Collection;
    52  import java.util.Collections;
    53  import java.util.Date;
    54  import java.util.HashMap;
    55  import java.util.Iterator;
    56  import java.util.List;
    57  import java.util.Map;
    58  import java.util.Map.Entry;
    59  import java.util.TimeZone;
    60  
    61  import {{invokerPackage}}.auth.Authentication;
    62  import {{invokerPackage}}.auth.HttpBasicAuth;
    63  import {{invokerPackage}}.auth.HttpBearerAuth;
    64  import {{invokerPackage}}.auth.ApiKeyAuth;
    65  {{#hasOAuthMethods}}
    66  import {{invokerPackage}}.auth.OAuth;
    67  {{/hasOAuthMethods}}
    68  
    69  {{>generatedAnnotation}}
    70  public class ApiClient {
    71      public enum CollectionFormat {
    72          CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null);
    73  
    74          private final String separator;
    75          private CollectionFormat(String separator) {
    76              this.separator = separator;
    77          }
    78  
    79          private String collectionToString(Collection<?> collection) {
    80              return StringUtils.collectionToDelimitedString(collection, separator);
    81          }
    82      }
    83  
    84      private HttpHeaders defaultHeaders = new HttpHeaders();
    85      private MultiValueMap<String, String> defaultCookies = new LinkedMultiValueMap<String, String>();
    86  
    87      private String basePath = "{{basePath}}";
    88  
    89      private final WebClient webClient;
    90      private final DateFormat dateFormat;
    91  
    92      private Map<String, Authentication> authentications;
    93  
    94  
    95      public ApiClient() {
    96          this.dateFormat = createDefaultDateFormat();
    97          ObjectMapper mapper = new ObjectMapper();
    98          mapper.setDateFormat(dateFormat);
    99          mapper.registerModule(new JavaTimeModule());
   100          mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
   101          JsonNullableModule jnm = new JsonNullableModule();
   102          mapper.registerModule(jnm);
   103  
   104          this.webClient = buildWebClient(mapper);
   105          this.init();
   106      }
   107  
   108      public ApiClient(ObjectMapper mapper, DateFormat format) {
   109          this(buildWebClient(mapper.copy()), format);
   110      }
   111  
   112      public ApiClient(WebClient webClient, ObjectMapper mapper, DateFormat format) {
   113          this(Optional.ofNullable(webClient).orElseGet(() ->buildWebClient(mapper.copy())), format);
   114      }
   115  
   116      private ApiClient(WebClient webClient, DateFormat format) {
   117          this.webClient = webClient;
   118          this.dateFormat = format;
   119          this.init();
   120      }
   121  
   122      public DateFormat createDefaultDateFormat() {
   123          DateFormat dateFormat = new RFC3339DateFormat();
   124          dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
   125          return dateFormat;
   126      }
   127  
   128      protected void init() {
   129          // Setup authentications (key: authentication name, value: authentication).
   130          authentications = new HashMap<String, Authentication>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
   131          authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}}
   132          authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}}
   133          authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
   134          authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
   135          // Prevent the authentications from being modified.
   136          authentications = Collections.unmodifiableMap(authentications);
   137      }
   138  
   139      /**
   140      * Build the RestTemplate used to make HTTP requests.
   141      * @return RestTemplate
   142      */
   143      public static WebClient buildWebClient(ObjectMapper mapper) {
   144          ExchangeStrategies strategies = ExchangeStrategies
   145              .builder()
   146              .codecs(clientDefaultCodecsConfigurer -> {
   147                  clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(mapper, MediaType.APPLICATION_JSON));
   148                  clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(mapper, MediaType.APPLICATION_JSON));
   149              }).build();
   150          WebClient.Builder webClient = WebClient.builder().exchangeStrategies(strategies);
   151          return webClient.build();
   152      }
   153  
   154  
   155      /**
   156       * Get the current base path
   157       * @return String the base path
   158       */
   159      public String getBasePath() {
   160          return basePath;
   161      }
   162  
   163      /**
   164       * Set the base path, which should include the host
   165       * @param basePath the base path
   166       * @return ApiClient this client
   167       */
   168      public ApiClient setBasePath(String basePath) {
   169          this.basePath = basePath;
   170          return this;
   171      }
   172  
   173      /**
   174       * Get authentications (key: authentication name, value: authentication).
   175       * @return Map the currently configured authentication types
   176       */
   177      public Map<String, Authentication> getAuthentications() {
   178          return authentications;
   179      }
   180  
   181      /**
   182       * Get authentication for the given name.
   183       *
   184       * @param authName The authentication name
   185       * @return The authentication, null if not found
   186       */
   187      public Authentication getAuthentication(String authName) {
   188          return authentications.get(authName);
   189      }
   190  
   191      /**
   192       * Helper method to set access token for the first Bearer authentication.
   193       * @param bearerToken Bearer token
   194       */
   195      public void setBearerToken(String bearerToken) {
   196          for (Authentication auth : authentications.values()) {
   197              if (auth instanceof HttpBearerAuth) {
   198                  ((HttpBearerAuth) auth).setBearerToken(bearerToken);
   199                  return;
   200              }
   201          }
   202          throw new RuntimeException("No Bearer authentication configured!");
   203      }
   204  
   205      /**
   206       * Helper method to set username for the first HTTP basic authentication.
   207       * @param username the username
   208       */
   209      public void setUsername(String username) {
   210          for (Authentication auth : authentications.values()) {
   211              if (auth instanceof HttpBasicAuth) {
   212                  ((HttpBasicAuth) auth).setUsername(username);
   213                  return;
   214              }
   215          }
   216          throw new RuntimeException("No HTTP basic authentication configured!");
   217      }
   218  
   219      /**
   220       * Helper method to set password for the first HTTP basic authentication.
   221       * @param password the password
   222       */
   223      public void setPassword(String password) {
   224          for (Authentication auth : authentications.values()) {
   225              if (auth instanceof HttpBasicAuth) {
   226                  ((HttpBasicAuth) auth).setPassword(password);
   227                  return;
   228              }
   229          }
   230          throw new RuntimeException("No HTTP basic authentication configured!");
   231      }
   232  
   233      /**
   234       * Helper method to set API key value for the first API key authentication.
   235       * @param apiKey the API key
   236       */
   237      public void setApiKey(String apiKey) {
   238          for (Authentication auth : authentications.values()) {
   239              if (auth instanceof ApiKeyAuth) {
   240                  ((ApiKeyAuth) auth).setApiKey(apiKey);
   241                  return;
   242              }
   243          }
   244          throw new RuntimeException("No API key authentication configured!");
   245      }
   246  
   247      /**
   248       * Helper method to set API key prefix for the first API key authentication.
   249       * @param apiKeyPrefix the API key prefix
   250       */
   251      public void setApiKeyPrefix(String apiKeyPrefix) {
   252          for (Authentication auth : authentications.values()) {
   253              if (auth instanceof ApiKeyAuth) {
   254                  ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
   255                  return;
   256              }
   257          }
   258          throw new RuntimeException("No API key authentication configured!");
   259      }
   260  
   261      {{#hasOAuthMethods}}
   262      /**
   263       * Helper method to set access token for the first OAuth2 authentication.
   264       * @param accessToken the access token
   265       */
   266      public void setAccessToken(String accessToken) {
   267          for (Authentication auth : authentications.values()) {
   268              if (auth instanceof OAuth) {
   269                  ((OAuth) auth).setAccessToken(accessToken);
   270                  return;
   271              }
   272          }
   273          throw new RuntimeException("No OAuth2 authentication configured!");
   274      }
   275  
   276      {{/hasOAuthMethods}}
   277      /**
   278       * Set the User-Agent header's value (by adding to the default header map).
   279       * @param userAgent the user agent string
   280       * @return ApiClient this client
   281       */
   282      public ApiClient setUserAgent(String userAgent) {
   283          addDefaultHeader("User-Agent", userAgent);
   284          return this;
   285      }
   286  
   287      /**
   288       * Add a default header.
   289       *
   290       * @param name The header's name
   291       * @param value The header's value
   292       * @return ApiClient this client
   293       */
   294      public ApiClient addDefaultHeader(String name, String value) {
   295          if (defaultHeaders.containsKey(name)) {
   296              defaultHeaders.remove(name);
   297          }
   298          defaultHeaders.add(name, value);
   299          return this;
   300      }
   301  
   302      /**
   303       * Add a default cookie.
   304       *
   305       * @param name The cookie's name
   306       * @param value The cookie's value
   307       * @return ApiClient this client
   308       */
   309      public ApiClient addDefaultCookie(String name, String value) {
   310          if (defaultCookies.containsKey(name)) {
   311              defaultCookies.remove(name);
   312          }
   313          defaultCookies.add(name, value);
   314          return this;
   315      }
   316  
   317      /**
   318       * Get the date format used to parse/format date parameters.
   319       * @return DateFormat format
   320       */
   321      public DateFormat getDateFormat() {
   322          return dateFormat;
   323      }
   324  
   325      /**
   326       * Parse the given string into Date object.
   327       */
   328      public Date parseDate(String str) {
   329          try {
   330              return dateFormat.parse(str);
   331          } catch (ParseException e) {
   332              throw new RuntimeException(e);
   333          }
   334      }
   335  
   336      /**
   337       * Format the given Date object into string.
   338       */
   339      public String formatDate(Date date) {
   340          return dateFormat.format(date);
   341      }
   342  
   343      /**
   344       * Format the given parameter object into string.
   345       * @param param the object to convert
   346       * @return String the parameter represented as a String
   347       */
   348      public String parameterToString(Object param) {
   349          if (param == null) {
   350              return "";
   351          } else if (param instanceof Date) {
   352              return formatDate( (Date) param);
   353          } else if (param instanceof Collection) {
   354              StringBuilder b = new StringBuilder();
   355              for(Object o : (Collection<?>) param) {
   356                  if(b.length() > 0) {
   357                      b.append(",");
   358                  }
   359                  b.append(String.valueOf(o));
   360              }
   361              return b.toString();
   362          } else {
   363              return String.valueOf(param);
   364          }
   365      }
   366  
   367      /**
   368       * Converts a parameter to a {@link MultiValueMap} for use in REST requests
   369       * @param collectionFormat The format to convert to
   370       * @param name The name of the parameter
   371       * @param value The parameter's value
   372       * @return a Map containing the String value(s) of the input parameter
   373       */
   374      public MultiValueMap<String, String> parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) {
   375          final MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
   376  
   377          if (name == null || name.isEmpty() || value == null) {
   378              return params;
   379          }
   380  
   381          if(collectionFormat == null) {
   382              collectionFormat = CollectionFormat.CSV;
   383          }
   384  
   385          Collection<?> valueCollection = null;
   386          if (value instanceof Collection) {
   387              valueCollection = (Collection<?>) value;
   388          } else {
   389              params.add(name, parameterToString(value));
   390              return params;
   391          }
   392  
   393          if (valueCollection.isEmpty()){
   394              return params;
   395          }
   396  
   397          if (collectionFormat.equals(CollectionFormat.MULTI)) {
   398              for (Object item : valueCollection) {
   399                  params.add(name, parameterToString(item));
   400              }
   401              return params;
   402          }
   403  
   404          List<String> values = new ArrayList<String>();
   405          for(Object o : valueCollection) {
   406              values.add(parameterToString(o));
   407          }
   408          params.add(name, collectionFormat.collectionToString(values));
   409  
   410          return params;
   411      }
   412  
   413      /**
   414      * Check if the given {@code String} is a JSON MIME.
   415      * @param mediaType the input MediaType
   416      * @return boolean true if the MediaType represents JSON, false otherwise
   417      */
   418      public boolean isJsonMime(String mediaType) {
   419          // "* / *" is default to JSON
   420          if ("*/*".equals(mediaType)) {
   421              return true;
   422          }
   423  
   424          try {
   425              return isJsonMime(MediaType.parseMediaType(mediaType));
   426          } catch (InvalidMediaTypeException e) {
   427          }
   428          return false;
   429      }
   430  
   431      /**
   432       * Check if the given MIME is a JSON MIME.
   433       * JSON MIME examples:
   434       *     application/json
   435       *     application/json; charset=UTF8
   436       *     APPLICATION/JSON
   437       * @param mediaType the input MediaType
   438       * @return boolean true if the MediaType represents JSON, false otherwise
   439       */
   440      public boolean isJsonMime(MediaType mediaType) {
   441          return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$"));
   442      }
   443  
   444      /**
   445       * Select the Accept header's value from the given accepts array:
   446       *     if JSON exists in the given array, use it;
   447       *     otherwise use all of them (joining into a string)
   448       *
   449       * @param accepts The accepts array to select from
   450       * @return List The list of MediaTypes to use for the Accept header
   451       */
   452      public List<MediaType> selectHeaderAccept(String[] accepts) {
   453          if (accepts.length == 0) {
   454              return null;
   455          }
   456          for (String accept : accepts) {
   457              MediaType mediaType = MediaType.parseMediaType(accept);
   458              if (isJsonMime(mediaType)) {
   459                  return Collections.singletonList(mediaType);
   460              }
   461          }
   462          return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(accepts));
   463      }
   464  
   465      /**
   466       * Select the Content-Type header's value from the given array:
   467       *     if JSON exists in the given array, use it;
   468       *     otherwise use the first one of the array.
   469       *
   470       * @param contentTypes The Content-Type array to select from
   471       * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used.
   472       */
   473      public MediaType selectHeaderContentType(String[] contentTypes) {
   474          if (contentTypes.length == 0) {
   475              return MediaType.APPLICATION_JSON;
   476          }
   477          for (String contentType : contentTypes) {
   478              MediaType mediaType = MediaType.parseMediaType(contentType);
   479              if (isJsonMime(mediaType)) {
   480                  return mediaType;
   481              }
   482          }
   483          return MediaType.parseMediaType(contentTypes[0]);
   484      }
   485  
   486      /**
   487       * Select the body to use for the request
   488       * @param obj the body object
   489       * @param formParams the form parameters
   490       * @param contentType the content type of the request
   491       * @return Object the selected body
   492       */
   493      protected BodyInserter<?, ? super ClientHttpRequest> selectBody(Object obj, MultiValueMap<String, Object> formParams, MediaType contentType) {
   494          if(MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {
   495              MultiValueMap<String, String> map = new LinkedMultiValueMap();
   496  
   497              formParams
   498                      .toSingleValueMap()
   499                      .entrySet()
   500                      .forEach(es -> map.add(es.getKey(), String.valueOf(es.getValue())));
   501  
   502              return BodyInserters.fromFormData(map);
   503          } else if(MediaType.MULTIPART_FORM_DATA.equals(contentType)) {
   504              return BodyInserters.fromMultipartData(formParams);
   505          } else {
   506              return obj != null ? BodyInserters.fromObject(obj) : null;
   507          }
   508      }
   509  
   510      /**
   511       * Invoke API by sending HTTP request with the given options.
   512       *
   513       * @param <T> the return type to use
   514       * @param path The sub-path of the HTTP URL
   515       * @param method The request method
   516       * @param pathParams The path parameters
   517       * @param queryParams The query parameters
   518       * @param body The request body object
   519       * @param headerParams The header parameters
   520       * @param formParams The form parameters
   521       * @param accept The request's Accept header
   522       * @param contentType The request's Content-Type header
   523       * @param authNames The authentications to apply
   524       * @param returnType The return type into which to deserialize the response
   525       * @return The response body in chosen type
   526       */
   527      public <T> Mono<T> invokeAPI(String path, HttpMethod method, Map<String, Object> pathParams, MultiValueMap<String, String> queryParams, Object body, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams, MultiValueMap<String, Object> formParams, List<MediaType> accept, MediaType contentType, String[] authNames, ParameterizedTypeReference<T> returnType) throws RestClientException {
   528          final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames);
   529          return requestBuilder.retrieve().bodyToMono(returnType);
   530      }
   531  
   532      /**
   533       * Invoke API by sending HTTP request with the given options.
   534       *
   535       * @param <T> the return type to use
   536       * @param path The sub-path of the HTTP URL
   537       * @param method The request method
   538       * @param pathParams The path parameters
   539       * @param queryParams The query parameters
   540       * @param body The request body object
   541       * @param headerParams The header parameters
   542       * @param formParams The form parameters
   543       * @param accept The request's Accept header
   544       * @param contentType The request's Content-Type header
   545       * @param authNames The authentications to apply
   546       * @param returnType The return type into which to deserialize the response
   547       * @return The response body in chosen type
   548       */
   549      public <T> Flux<T> invokeFluxAPI(String path, HttpMethod method, Map<String, Object> pathParams, MultiValueMap<String, String> queryParams, Object body, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams, MultiValueMap<String, Object> formParams, List<MediaType> accept, MediaType contentType, String[] authNames, ParameterizedTypeReference<T> returnType) throws RestClientException {
   550          final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames);
   551          return requestBuilder.retrieve().bodyToFlux(returnType);
   552      }
   553  
   554      private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, Map<String, Object> pathParams, MultiValueMap<String, String> queryParams, Object body, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams, MultiValueMap<String, Object> formParams, List<MediaType> accept, MediaType contentType, String[] authNames) {
   555          updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);
   556  
   557          final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path);
   558          if (queryParams != null) {
   559              builder.queryParams(queryParams);
   560          }
   561  
   562          final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(false).toUriString(), pathParams);
   563          if(accept != null) {
   564              requestBuilder.accept(accept.toArray(new MediaType[accept.size()]));
   565          }
   566          if(contentType != null) {
   567              requestBuilder.contentType(contentType);
   568          }
   569  
   570          addHeadersToRequest(headerParams, requestBuilder);
   571          addHeadersToRequest(defaultHeaders, requestBuilder);
   572          addCookiesToRequest(cookieParams, requestBuilder);
   573          addCookiesToRequest(defaultCookies, requestBuilder);
   574  
   575          requestBuilder.body(selectBody(body, formParams, contentType));
   576          return requestBuilder;
   577      }
   578  
   579      /**
   580       * Add headers to the request that is being built
   581       * @param headers The headers to add
   582       * @param requestBuilder The current request
   583       */
   584      protected void addHeadersToRequest(HttpHeaders headers, WebClient.RequestBodySpec requestBuilder) {
   585          for (Entry<String, List<String>> entry : headers.entrySet()) {
   586              List<String> values = entry.getValue();
   587              for(String value : values) {
   588                  if (value != null) {
   589                      requestBuilder.header(entry.getKey(), value);
   590                  }
   591              }
   592          }
   593      }
   594  
   595      /**
   596       * Add cookies to the request that is being built
   597       * @param cookies The cookies to add
   598       * @param requestBuilder The current request
   599       */
   600      protected void addCookiesToRequest(MultiValueMap<String, String> cookies, WebClient.RequestBodySpec requestBuilder) {
   601          for (Entry<String, List<String>> entry : cookies.entrySet()) {
   602              List<String> values = entry.getValue();
   603              for(String value : values) {
   604                  if (value != null) {
   605                      requestBuilder.cookie(entry.getKey(), value);
   606                  }
   607              }
   608          }
   609      }
   610  
   611      /**
   612       * Update query and header parameters based on authentication settings.
   613       *
   614       * @param authNames The authentications to apply
   615       * @param queryParams The query parameters
   616       * @param headerParams The header parameters
   617       * @param cookieParams the cookie parameters
   618       */
   619      private void updateParamsForAuth(String[] authNames, MultiValueMap<String, String> queryParams, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams) {
   620          for (String authName : authNames) {
   621              Authentication auth = authentications.get(authName);
   622              if (auth == null) {
   623                  throw new RestClientException("Authentication undefined: " + authName);
   624              }
   625              auth.applyToParams(queryParams, headerParams, cookieParams);
   626          }
   627      }
   628  
   629      /**
   630      * Formats the specified collection path parameter to a string value.
   631      *
   632      * @param collectionFormat The collection format of the parameter.
   633      * @param values The values of the parameter.
   634      * @return String representation of the parameter
   635      */
   636      public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection<?> values) {
   637          // create the value based on the collection format
   638          if (CollectionFormat.MULTI.equals(collectionFormat)) {
   639              // not valid for path params
   640              return parameterToString(values);
   641          }
   642  
   643           // collectionFormat is assumed to be "csv" by default
   644           if(collectionFormat == null) {
   645               collectionFormat = CollectionFormat.CSV;
   646           }
   647  
   648           return collectionFormat.collectionToString(values);
   649      }
   650  
   651      private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
   652          private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class);
   653  
   654          @Override
   655          public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
   656              logRequest(request, body);
   657              ClientHttpResponse response = execution.execute(request, body);
   658              logResponse(response);
   659              return response;
   660          }
   661  
   662          private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException {
   663              log.info("URI: " + request.getURI());
   664              log.info("HTTP Method: " + request.getMethod());
   665              log.info("HTTP Headers: " + headersToString(request.getHeaders()));
   666              log.info("Request Body: " + new String(body, StandardCharsets.UTF_8));
   667          }
   668  
   669          private void logResponse(ClientHttpResponse response) throws IOException {
   670              log.info("HTTP Status Code: " + response.getRawStatusCode());
   671              log.info("Status Text: " + response.getStatusText());
   672              log.info("HTTP Headers: " + headersToString(response.getHeaders()));
   673              log.info("Response Body: " + bodyToString(response.getBody()));
   674          }
   675  
   676          private String headersToString(HttpHeaders headers) {
   677              StringBuilder builder = new StringBuilder();
   678              for(Entry<String, List<String>> entry : headers.entrySet()) {
   679                  builder.append(entry.getKey()).append("=[");
   680                  for(String value : entry.getValue()) {
   681                      builder.append(value).append(",");
   682                  }
   683                  builder.setLength(builder.length() - 1); // Get rid of trailing comma
   684                  builder.append("],");
   685              }
   686              builder.setLength(builder.length() - 1); // Get rid of trailing comma
   687              return builder.toString();
   688          }
   689  
   690          private String bodyToString(InputStream body) throws IOException {
   691              StringBuilder builder = new StringBuilder();
   692              BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8));
   693              String line = bufferedReader.readLine();
   694              while (line != null) {
   695                  builder.append(line).append(System.lineSeparator());
   696                  line = bufferedReader.readLine();
   697              }
   698              bufferedReader.close();
   699              return builder.toString();
   700          }
   701      }
   702  }