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

     1  package {{invokerPackage}};
     2  
     3  import {{invokerPackage}}.auth.Authentication;
     4  import {{invokerPackage}}.auth.HttpBasicAuth;
     5  import {{invokerPackage}}.auth.HttpBearerAuth;
     6  import {{invokerPackage}}.auth.ApiKeyAuth;
     7  {{#hasOAuthMethods}}
     8  import {{invokerPackage}}.auth.OAuth;
     9  {{/hasOAuthMethods}}
    10  
    11  import com.fasterxml.jackson.annotation.JsonInclude;
    12  import com.fasterxml.jackson.core.type.TypeReference;
    13  import com.fasterxml.jackson.databind.DeserializationFeature;
    14  import com.fasterxml.jackson.databind.ObjectMapper;
    15  import com.fasterxml.jackson.databind.SerializationFeature;
    16  import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
    17  import org.openapitools.jackson.nullable.JsonNullableModule;
    18  import io.vertx.core.*;
    19  import io.vertx.core.buffer.Buffer;
    20  import io.vertx.core.file.AsyncFile;
    21  import io.vertx.core.file.FileSystem;
    22  import io.vertx.core.file.OpenOptions;
    23  import io.vertx.core.http.HttpHeaders;
    24  import io.vertx.core.http.HttpMethod;
    25  import io.vertx.core.json.DecodeException;
    26  import io.vertx.core.json.Json;
    27  import io.vertx.core.json.JsonObject;
    28  import io.vertx.ext.web.client.HttpRequest;
    29  import io.vertx.ext.web.client.HttpResponse;
    30  import io.vertx.ext.web.client.WebClient;
    31  import io.vertx.ext.web.client.WebClientOptions;
    32  
    33  import java.text.DateFormat;
    34  import java.util.*;
    35  import java.util.function.Consumer;
    36  import java.util.regex.Matcher;
    37  import java.util.regex.Pattern;
    38  
    39  import static java.util.stream.Collectors.toMap;
    40  
    41  {{>generatedAnnotation}}
    42  public class ApiClient {
    43  
    44      private static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?");
    45      private static final OpenOptions FILE_DOWNLOAD_OPTIONS = new OpenOptions().setCreate(true).setTruncateExisting(true);
    46  
    47      private final Vertx vertx;
    48      private final JsonObject config;
    49      private final String identifier;
    50  
    51      private MultiMap defaultHeaders = MultiMap.caseInsensitiveMultiMap();
    52      private MultiMap defaultCookies = MultiMap.caseInsensitiveMultiMap();
    53      private Map<String, Authentication> authentications;
    54      private String basePath = "{{{basePath}}}";
    55      private DateFormat dateFormat;
    56      private ObjectMapper objectMapper;
    57      private String downloadsDir = "";
    58  
    59      public ApiClient(Vertx vertx, JsonObject config) {
    60          Objects.requireNonNull(vertx, "Vertx must not be null");
    61          Objects.requireNonNull(config, "Config must not be null");
    62  
    63          this.vertx = vertx;
    64  
    65          // Use RFC3339 format for date and datetime.
    66          // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
    67          this.dateFormat = new RFC3339DateFormat();
    68  
    69          // Use UTC as the default time zone.
    70          this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    71  
    72          // Build object mapper
    73          this.objectMapper = new ObjectMapper();
    74          this.objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    75          this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    76          this.objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
    77          this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    78          this.objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
    79          this.objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
    80          this.objectMapper.registerModule(new JavaTimeModule());
    81          this.objectMapper.setDateFormat(dateFormat);
    82          JsonNullableModule jnm = new JsonNullableModule();
    83          this.objectMapper.registerModule(jnm);
    84  
    85          // Setup authentications (key: authentication name, value: authentication).
    86          this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
    87          authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}}
    88          authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}}
    89          authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
    90          authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
    91          // Prevent the authentications from being modified.
    92          this.authentications = Collections.unmodifiableMap(authentications);
    93  
    94          // Configurations
    95          this.basePath = config.getString("basePath", this.basePath);
    96          this.downloadsDir = config.getString("downloadsDir", this.downloadsDir);
    97          this.config = config;
    98          this.identifier = UUID.randomUUID().toString();
    99      }
   100  
   101      public Vertx getVertx() {
   102          return vertx;
   103      }
   104  
   105      public ObjectMapper getObjectMapper() {
   106          return objectMapper;
   107      }
   108  
   109      public ApiClient setObjectMapper(ObjectMapper objectMapper) {
   110          this.objectMapper = objectMapper;
   111          return this;
   112      }
   113  
   114      public synchronized WebClient getWebClient() {
   115          String webClientIdentifier = "web-client-" + identifier;
   116          WebClient webClient = Vertx.currentContext().get(webClientIdentifier);
   117          if (webClient == null) {
   118              webClient = buildWebClient(vertx, config);
   119              Vertx.currentContext().put(webClientIdentifier, webClient);
   120          }
   121          return webClient;
   122      }
   123  
   124      public String getBasePath() {
   125          return basePath;
   126      }
   127  
   128      public ApiClient setBasePath(String basePath) {
   129          this.basePath = basePath;
   130          return this;
   131      }
   132  
   133      public String getDownloadsDir() {
   134          return downloadsDir;
   135      }
   136  
   137      public ApiClient setDownloadsDir(String downloadsDir) {
   138          this.downloadsDir = downloadsDir;
   139          return this;
   140      }
   141  
   142      public MultiMap getDefaultHeaders() {
   143          return defaultHeaders;
   144      }
   145  
   146      public ApiClient addDefaultHeader(String key, String value) {
   147          defaultHeaders.add(key, value);
   148          return this;
   149      }
   150  
   151      public MultiMap getDefaultCookies() {
   152          return defaultHeaders;
   153      }
   154  
   155      public ApiClient addDefaultCookie(String key, String value) {
   156          defaultCookies.add(key, value);
   157          return this;
   158      }
   159  
   160      /**
   161       * Get authentications (key: authentication name, value: authentication).
   162       *
   163       * @return Map of authentication object
   164       */
   165      public Map<String, Authentication> getAuthentications() {
   166          return authentications;
   167      }
   168  
   169      /**
   170       * Get authentication for the given name.
   171       *
   172       * @param authName The authentication name
   173       * @return The authentication, null if not found
   174       */
   175      public Authentication getAuthentication(String authName) {
   176          return authentications.get(authName);
   177      }
   178  
   179      /**
   180       * Helper method to set access token for the first Bearer authentication.
   181       * @param bearerToken Bearer token
   182       */
   183      public ApiClient setBearerToken(String bearerToken) {
   184          for (Authentication auth : authentications.values()) {
   185              if (auth instanceof HttpBearerAuth) {
   186                  ((HttpBearerAuth) auth).setBearerToken(bearerToken);
   187                  return this;
   188              }
   189          }
   190          throw new RuntimeException("No Bearer authentication configured!");
   191      }
   192  
   193      /**
   194       * Helper method to set username for the first HTTP basic authentication.
   195       *
   196       * @param username Username
   197       */
   198      public ApiClient setUsername(String username) {
   199          for (Authentication auth : authentications.values()) {
   200              if (auth instanceof HttpBasicAuth) {
   201                  ((HttpBasicAuth) auth).setUsername(username);
   202                  return this;
   203              }
   204          }
   205          throw new RuntimeException("No HTTP basic authentication configured!");
   206      }
   207  
   208      /**
   209       * Helper method to set password for the first HTTP basic authentication.
   210       *
   211       * @param password Password
   212       */
   213      public ApiClient setPassword(String password) {
   214          for (Authentication auth : authentications.values()) {
   215              if (auth instanceof HttpBasicAuth) {
   216                  ((HttpBasicAuth) auth).setPassword(password);
   217                  return this;
   218              }
   219          }
   220          throw new RuntimeException("No HTTP basic authentication configured!");
   221      }
   222  
   223      /**
   224       * Helper method to set API key value for the first API key authentication.
   225       *
   226       * @param apiKey API key
   227       */
   228      public ApiClient setApiKey(String apiKey) {
   229          for (Authentication auth : authentications.values()) {
   230              if (auth instanceof ApiKeyAuth) {
   231                  ((ApiKeyAuth) auth).setApiKey(apiKey);
   232                  return this;
   233              }
   234          }
   235          throw new RuntimeException("No API key authentication configured!");
   236      }
   237  
   238      /**
   239       * Helper method to set API key prefix for the first API key authentication.
   240       *
   241       * @param apiKeyPrefix API key prefix
   242       */
   243      public ApiClient setApiKeyPrefix(String apiKeyPrefix) {
   244          for (Authentication auth : authentications.values()) {
   245              if (auth instanceof ApiKeyAuth) {
   246                  ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
   247                  return this;
   248              }
   249          }
   250          throw new RuntimeException("No API key authentication configured!");
   251      }
   252  
   253      {{#hasOAuthMethods}}
   254      /**
   255       * Helper method to set access token for the first OAuth2 authentication.
   256       *
   257       * @param accessToken Access token
   258       */
   259      public ApiClient setAccessToken(String accessToken) {
   260          for (Authentication auth : authentications.values()) {
   261              if (auth instanceof OAuth) {
   262                  ((OAuth) auth).setAccessToken(accessToken);
   263                  return this;
   264              }
   265          }
   266          throw new RuntimeException("No OAuth2 authentication configured!");
   267      }
   268  
   269      {{/hasOAuthMethods}}
   270      /**
   271       * Format the given Date object into string.
   272       *
   273       * @param date Date
   274       * @return Date in string format
   275       */
   276      public String formatDate(Date date) {
   277          return dateFormat.format(date);
   278      }
   279  
   280      /**
   281       * Format the given parameter object into string.
   282       *
   283       * @param param Object
   284       * @return Object in string format
   285       */
   286      public String parameterToString(Object param) {
   287          if (param == null) {
   288              return "";
   289          } else if (param instanceof Date) {
   290              return formatDate((Date) param);
   291          } else if (param instanceof Collection) {
   292              StringBuilder b = new StringBuilder();
   293              for (Object o : (Collection) param) {
   294                  if (b.length() > 0) {
   295                      b.append(',');
   296                  }
   297                  b.append(String.valueOf(o));
   298              }
   299              return b.toString();
   300          } else {
   301              return String.valueOf(param);
   302          }
   303      }
   304  
   305      /*
   306       * Format to {@code Pair} objects.
   307       * @param collectionFormat Collection format
   308       * @param name Name
   309       * @param value Value
   310       * @return List of pairs
   311       */
   312      public List<Pair> parameterToPairs(String collectionFormat, String name, Object value) {
   313          List<Pair> params = new ArrayList<Pair>();
   314  
   315          // preconditions
   316          if (name == null || name.isEmpty() || value == null) return params;
   317  
   318          Collection valueCollection;
   319          if (value instanceof Collection) {
   320              valueCollection = (Collection) value;
   321          } else {
   322              params.add(new Pair(name, parameterToString(value)));
   323              return params;
   324          }
   325  
   326          if (valueCollection.isEmpty()) {
   327              return params;
   328          }
   329  
   330          // get the collection format (default: csv)
   331          String format = (collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat);
   332  
   333          // create the params based on the collection format
   334          if ("multi".equals(format)) {
   335              for (Object item : valueCollection) {
   336                  params.add(new Pair(name, parameterToString(item)));
   337              }
   338              return params;
   339          }
   340  
   341          String delimiter = ",";
   342          if ("csv".equals(format)) {
   343              delimiter = ",";
   344          } else if ("ssv".equals(format)) {
   345              delimiter = " ";
   346          } else if ("tsv".equals(format)) {
   347              delimiter = "\t";
   348          } else if ("pipes".equals(format)) {
   349              delimiter = "|";
   350          }
   351  
   352          StringBuilder sb = new StringBuilder();
   353          for (Object item : valueCollection) {
   354              sb.append(delimiter);
   355              sb.append(parameterToString(item));
   356          }
   357  
   358          params.add(new Pair(name, sb.substring(1)));
   359  
   360          return params;
   361      }
   362  
   363      /**
   364       * Check if the given MIME is a JSON MIME.
   365       * JSON MIME examples:
   366       * application/json
   367       * application/json; charset=UTF8
   368       * APPLICATION/JSON
   369       * application/vnd.company+json
   370       *
   371       * @param mime MIME
   372       * @return True if the MIME type is JSON
   373       */
   374      private boolean isJsonMime(String mime) {
   375          String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
   376          return mime != null && (mime.matches(jsonMime) || mime.equalsIgnoreCase("application/json-patch+json"));
   377      }
   378  
   379      /**
   380       * Select the Accept header's value from the given accepts array:
   381       * if JSON exists in the given array, use it;
   382       * otherwise use all of them (joining into a string)
   383       *
   384       * @param accepts The accepts array to select from
   385       * @return The Accept header to use. If the given array is empty,
   386       * null will be returned (not to set the Accept header explicitly).
   387       */
   388      protected String selectHeaderAccept(String[] accepts) {
   389          if (accepts.length == 0) {
   390              return null;
   391          }
   392          for (String accept : accepts) {
   393              if (isJsonMime(accept)) {
   394                  return accept;
   395              }
   396          }
   397          return StringUtil.join(accepts, ",");
   398      }
   399  
   400      /**
   401       * Select the Content-Type header's value from the given array:
   402       * if JSON exists in the given array, use it;
   403       * otherwise use the first one of the array.
   404       *
   405       * @param contentTypes The Content-Type array to select from
   406       * @return The Content-Type header to use. If the given array is empty,
   407       * JSON will be used.
   408       */
   409      protected String selectHeaderContentType(String[] contentTypes) {
   410          if (contentTypes.length == 0) {
   411              return "application/json";
   412          }
   413          for (String contentType : contentTypes) {
   414              if (isJsonMime(contentType)) {
   415                  return contentType;
   416              }
   417          }
   418          return contentTypes[0];
   419      }
   420  
   421      public void sendBody(HttpRequest<Buffer> request,
   422                           Handler<AsyncResult<HttpResponse<Buffer>>> responseHandler,
   423                           Object body) {
   424          if (body instanceof byte[]) {
   425              Buffer buffer = Buffer.buffer((byte[]) body);
   426              request.sendBuffer(buffer, responseHandler);
   427          } else if (body instanceof AsyncFile) {
   428              AsyncFile file = (AsyncFile) body;
   429              request.sendStream(file, responseHandler);
   430          } else {
   431              request.sendJson(body, responseHandler);
   432          }
   433      }
   434  
   435      /**
   436       * Invoke API by sending HTTP request with the given options.
   437       *
   438       * @param <T> Type
   439       * @param path The sub-path of the HTTP URL
   440       * @param method The request method, one of "GET", "POST", "PUT", "HEAD" and "DELETE"
   441       * @param queryParams The query parameters
   442       * @param body The request body object
   443       * @param headerParams The header parameters
   444       * @param cookieParams The cookie parameters
   445       * @param formParams The form parameters
   446       * @param accepts The request's Accept headers
   447       * @param contentTypes The request's Content-Type headers
   448       * @param authNames The authentications to apply
   449       * @param returnType The return type into which to deserialize the response
   450       * @param resultHandler The asynchronous response handler
   451       */
   452      public <T> void invokeAPI(String path, String method, List<Pair> queryParams, Object body, MultiMap headerParams,
   453                                MultiMap cookieParams, Map<String, Object> formParams, String[] accepts, String[] contentTypes, String[] authNames,
   454                                TypeReference<T> returnType, Handler<AsyncResult<T>> resultHandler) {
   455  
   456          updateParamsForAuth(authNames, queryParams, headerParams, cookieParams);
   457  
   458          if (accepts != null && accepts.length > 0) {
   459              headerParams.add(HttpHeaders.ACCEPT, selectHeaderAccept(accepts));
   460          }
   461  
   462          if (contentTypes != null) {
   463              headerParams.add(HttpHeaders.CONTENT_TYPE, selectHeaderContentType(contentTypes));
   464          }
   465  
   466          HttpMethod httpMethod = HttpMethod.valueOf(method);
   467          HttpRequest<Buffer> request = getWebClient().requestAbs(httpMethod, basePath + path);
   468  
   469          if (httpMethod == HttpMethod.PATCH) {
   470              request.putHeader("X-HTTP-Method-Override", "PATCH");
   471          }
   472  
   473          queryParams.forEach(entry -> {
   474              if (entry.getValue() != null) {
   475                  request.addQueryParam(entry.getName(), entry.getValue());
   476              }
   477          });
   478  
   479          headerParams.forEach(entry -> {
   480              if (entry.getValue() != null) {
   481                  request.putHeader(entry.getKey(), entry.getValue());
   482              }
   483          });
   484  
   485          defaultHeaders.forEach(entry -> {
   486              if (entry.getValue() != null) {
   487                  request.putHeader(entry.getKey(), entry.getValue());
   488              }
   489          });
   490  
   491          final MultiMap cookies = MultiMap.caseInsensitiveMultiMap().addAll(cookieParams).addAll(defaultCookies);
   492          request.putHeader("Cookie", buildCookieHeader(cookies));
   493  
   494          Handler<AsyncResult<HttpResponse<Buffer>>> responseHandler = buildResponseHandler(returnType, resultHandler);
   495          if (body != null) {
   496              sendBody(request, responseHandler, body);
   497          } else if (formParams != null && !formParams.isEmpty()) {
   498              Map<String, String> formMap = formParams.entrySet().stream().collect(toMap(Map.Entry::getKey, entry -> parameterToString(entry.getValue())));
   499              MultiMap form = MultiMap.caseInsensitiveMultiMap().addAll(formMap);
   500              request.sendForm(form, responseHandler);
   501          } else {
   502              request.send(responseHandler);
   503          }
   504      }
   505  
   506      private String buildCookieHeader(MultiMap cookies) {
   507        final StringBuilder cookieValue = new StringBuilder();
   508        String delimiter = "";
   509        for (final Map.Entry<String, String> entry : cookies.entries()) {
   510            if (entry.getValue() != null) {
   511                cookieValue.append(String.format("%s%s=%s", delimiter, entry.getKey(), entry.getValue()));
   512                delimiter = "; ";
   513            }
   514        }
   515        return cookieValue.toString();
   516      }
   517  
   518      /**
   519       * Sanitize filename by removing path.
   520       * e.g. ../../sun.gif becomes sun.gif
   521       *
   522       * @param filename The filename to be sanitized
   523       * @return The sanitized filename
   524       */
   525      protected String sanitizeFilename(String filename) {
   526          return filename.replaceAll(".*[/\\\\]", "");
   527      }
   528  
   529      /**
   530       * Create a filename from the given headers.
   531       * When the headers have no "Content-Disposition" information, a random UUID name is generated.
   532       *
   533       * @param headers The HTTP response headers
   534       * @return The filename
   535       */
   536      protected String generateFilename(MultiMap headers) {
   537          String filename = UUID.randomUUID().toString();
   538          String contentDisposition = headers.get("Content-Disposition");
   539          if (contentDisposition != null && !contentDisposition.isEmpty()) {
   540              Matcher matcher = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition);
   541              if (matcher.find()) {
   542                  filename = sanitizeFilename(matcher.group(1));
   543              }
   544          }
   545          return filename;
   546      }
   547  
   548      /**
   549       * File Download handling.
   550       *
   551       * @param response The HTTP response
   552       * @param handler The response handler
   553       */
   554      protected <T> void handleFileDownload(HttpResponse<Buffer> response, Handler<AsyncResult<T>> handler) {
   555          FileSystem fs = getVertx().fileSystem();
   556  
   557          String filename = generateFilename(response.headers());
   558          Consumer<String> fileHandler = directory -> {
   559              fs.open(directory + filename, FILE_DOWNLOAD_OPTIONS, asyncFileResult -> {
   560                  if (asyncFileResult.succeeded()) {
   561                      AsyncFile asyncFile = asyncFileResult.result();
   562                      asyncFile.write(response.bodyAsBuffer());
   563                      //noinspection unchecked
   564                      handler.handle(Future.succeededFuture((T) asyncFile));
   565                  } else {
   566                      handler.handle(ApiException.fail(asyncFileResult.cause()));
   567                  }
   568              });
   569          };
   570  
   571          String dir = getDownloadsDir();
   572          if (dir != null && !dir.isEmpty()) {
   573              fs.mkdirs(dir, mkdirResult -> {
   574                  String sanitizedFolder = dir.endsWith("/") ? dir : dir + "/";
   575                  fileHandler.accept(sanitizedFolder);
   576              });
   577          } else {
   578              fileHandler.accept("");
   579          }
   580      }
   581  
   582      /**
   583       * Build a response handler for the HttpResponse.
   584       *
   585       * @param returnType The return type
   586       * @param handler The response handler
   587       * @return The HTTP response handler
   588       */
   589      protected <T> Handler<AsyncResult<HttpResponse<Buffer>>> buildResponseHandler(TypeReference<T> returnType,
   590                                                                                    Handler<AsyncResult<T>> handler) {
   591          return response -> {
   592              AsyncResult<T> result;
   593              if (response.succeeded()) {
   594                  HttpResponse<Buffer> httpResponse = response.result();
   595                  if (httpResponse.statusCode() / 100 == 2) {
   596                      if (httpResponse.statusCode() == 204 || returnType == null) {
   597                          result = Future.succeededFuture(null);
   598                      } else {
   599                          T resultContent = null;
   600                          if ("byte[]".equals(returnType.getType().toString())) {
   601                              resultContent = (T) httpResponse.body().getBytes();
   602                              result = Future.succeededFuture(resultContent);
   603                          } else if (AsyncFile.class.equals(returnType.getType())) {
   604                              handleFileDownload(httpResponse, handler);
   605                              return;
   606                          } else {
   607                              try {
   608                                  resultContent = this.objectMapper.readValue(httpResponse.bodyAsString(), returnType);
   609                                  result = Future.succeededFuture(resultContent);
   610                              } catch (Exception e) {
   611                                  result =  ApiException.fail(new DecodeException("Failed to decode:" + e.getMessage(), e));
   612                              }
   613                          }
   614                      }
   615                  } else {
   616                      result = ApiException.fail(httpResponse.statusMessage(), httpResponse.statusCode(), httpResponse.headers(), httpResponse.bodyAsString());
   617                  }
   618              } else if (response.cause() instanceof ApiException) {
   619                  result = Future.failedFuture(response.cause());
   620              } else {
   621                  result = ApiException.fail(500, response.cause() != null ? response.cause().getMessage() : null);
   622              }
   623              handler.handle(result);
   624          };
   625      }
   626  
   627      /**
   628       * Build the WebClient used to make HTTP requests.
   629       *
   630       * @param vertx Vertx
   631       * @return WebClient
   632       */
   633      protected WebClient buildWebClient(Vertx vertx, JsonObject config) {
   634  
   635          if (!config.containsKey("userAgent")) {
   636              config.put("userAgent", "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
   637          }
   638  
   639          return WebClient.create(vertx, new WebClientOptions(config));
   640      }
   641  
   642  
   643      /**
   644       * Update query and header parameters based on authentication settings.
   645       *
   646       * @param authNames The authentications to apply
   647       */
   648      protected void updateParamsForAuth(String[] authNames, List<Pair> queryParams, MultiMap headerParams, MultiMap cookieParams) {
   649          for (String authName : authNames) {
   650              Authentication auth = authentications.get(authName);
   651              if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);
   652              auth.applyToParams(queryParams, headerParams, cookieParams);
   653          }
   654      }
   655  }