简体   繁体   English

Swagger Codegen CLI Java 客户端 - 如何正确使用它

[英]Swagger Codegen CLI Java Client - How to use it right

I'm currently playing around with my jersey2 rest service.我目前正在玩我的 jersey2 休息服务。 For a better overview of the given service (description, types and so on) I make heavily use of swagger (swagger-jersey2-jaxrs).为了更好地概述给定的服务(描述、类型等),我大量使用了 swagger (swagger-jersey2-jaxrs)。 So I'm able to genereate my service description (swagger.json) and I can view and explore them via swagger ui.所以我能够生成我的服务描述 (swagger.json),我可以通过 swagger ui 查看和探索它们。

Now I'm at the point that I need to create some clients to make use of these services.现在我需要创建一些客户端来使用这些服务。 I came across swagger codegen cli which is a nice tool to generate your client and many different languages (java in my case).我遇到了 swagger codegen cli,这是一个很好的工具来生成你的客户端和许多不同的语言(在我的例子中是 java)。 I'm able to generate the api client and the model in use.我能够生成 api 客户端和正在使用的模型。

Here I face the first problem.在这里,我面临着第一个问题。 The REST services and the swagger description are http basic auth protected. REST 服务和 swagger 描述受 http 基本身份验证保护。 I read the documentation which gave me some hint that there is a possibility to use basic auth.我阅读了文档,它给了我一些提示,即可以使用基本身份验证。 At this point I have to mention that from my point of view the documentation is very poor.在这一点上,我不得不提到,从我的角度来看,文档非常糟糕。 It says:它说:

-a , --auth adds authorization headers when fetching the swagger definitions remotely. -a , --auth 在远程获取 swagger 定义时添加授权标头。 Pass in a URL-encoded string of name:header with a comma separating multiple values.传入一个 URL 编码的 name:header 字符串,用逗号分隔多个值。

First thing I thought of is to pass a string like in an http header but that doesn't work and even googling how to use basic auth with swagger cli didn't result in some clear answer.我想到的第一件事是传递一个像 http 标头中的字符串,但这不起作用,甚至谷歌搜索如何使用带有 swagger cli 的基本身份验证也没有得到一些明确的答案。 After a lot of try and errors I (I'm using CLI 2.1.2) I finally came across the right format:经过多次尝试和错误,我(我使用的是 CLI 2.1.2)终于找到了正确的格式:

java -jar swagger-codegen-cli-2.1.2.jar generate -a "Authorization: Basic YWRtaW46YWRtaW4=" -i http://localhost:8080/webproject/restapi/swagger.json -l java -o restclient java -jar swagger-codegen-cli-2.1.2.jar generate -a "Authorization: Basic YWRtaW46YWRtaW4=" -i http://localhost:8080/webproject/restapi/swagger.json -l java -o restclient

where YWRtaW46YWRtaW4= is the the base64 encoded value of admin:admin in my case.在我的例子中,YWRtaW46YWRtaW4= 是 admin:admin 的 base64 编码值。

So far so good.到现在为止还挺好。 The generated java client have to make use of basic auth as well.生成的 Java 客户端也必须使用基本身份验证。 I took a look at the methods from the ApiClient and found setUsername and setPassword.我查看了 ApiClient 中的方法,发现了 setUsername 和 setPassword。 I thought that this methods empowers the client to use basic auth but no luck.我认为这种方法使客户能够使用基本身份验证,但没有运气。

So I took a deeper look at the generated classes especially the ApiClient and the several generated ApiService Classes.所以我更深入地研究了生成的类,尤其是 ApiClient 和几个生成的 ApiService 类。 I found out that the setUsername and setPassword have no effect because of the following:我发现 setUsername 和 setPassword 由于以下原因无效:

/**
   * Helper method to set username for the first HTTP basic authentication.
   */
  public void setUsername(String username) {
    for (Authentication auth : authentications.values()) {
      if (auth instanceof HttpBasicAuth) {
        ((HttpBasicAuth) auth).setUsername(username);
        return;
      }
    }
    throw new RuntimeException("No HTTP basic authentication configured!");
  }

where at the same time the HashMap is defined as the following:同时 HashMap 定义如下:

// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap<String, Authentication>();
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);

The authentication hashmap becomes immutable, but why?身份验证哈希映射变得不可变,但为什么呢? What is the purpose?什么目的? Furthermore there are no helper methods inside the ApiClinet which generates the needed auth object so I did the following:此外,ApiClinet 中没有生成所需身份验证对象的辅助方法,因此我执行了以下操作:

1) comment out the line authentications Collections.unmodifiableMap(authentications) so the hashmap becomes modifiable again 1) 注释掉 authentications Collections.unmodifiableMap(authentications) 行,以便哈希图再次可修改

2) create needed auth object manually 2)手动创建所需的身份验证对象

HttpBasicAuth authentication = new HttpBasicAuth(); 
authentication.setUsername("admin");
authentication.setPassword("admin");

3) add the auth object to the apiClients authentication hashmap: 3) 将 auth 对象添加到 apiClients 身份验证哈希图中:

ApiClient apiClient = new ApiClient();
apiClient.setBasePath(basePath);
apiClient.getAuthentications().put("basic", authentication);

4) modifying invokeApi Method (ApiClient.java) 4)修改invokeApi方法(ApiClient.java)

public String invokeAPI(String path, String method, Map<String, String> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType, String[] authNames) throws ApiException {
String authNames2[] = {"basic"};
updateParamsForAuth(authNames2, queryParams, headerParams);
//updateParamsForAuth(authNames, queryParams, headerParams);
...

Step 4 is necessary because the ApiServices invoke the apiClient method like the following:第 4 步是必要的,因为 ApiServices 调用 apiClient 方法,如下所示:

String[] authNames = new String[] {  };
String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames);

An other possible solution would be to define the Key of the authentications hashmap in every apiService like:另一种可能的解决方案是在每个 apiService 中定义身份验证哈希映射的密钥,例如:

String[] authNames = new String[] { "basic" };

After doing all the modifications everything works as expected but I cant think that this is the idea behind an autogenerated rest client.完成所有修改后,一切都按预期工作,但我不认为这是自动生成的休息客户端背后的想法。 So my question is: Am I missing some point or should I think of the swagger generated client (java in this case) more of a beta solution which is under development?所以我的问题是:我是否遗漏了某些点,或者我应该将 swagger 生成的客户端(在这种情况下为 java)更多地视为正在开发的 beta 解决方案? Please get me right, I think the whole swagger framework (jersey2 support, openapi, swaggerui, codegen) is a great thing and I appreciate the developers effort but I want to use the codegen right and I don't think that the idea behind is so have to customize the generated ApiClient and ApiServices in such a way.请让我正确,我认为整个 swagger 框架(jersey2 支持、openapi、swaggerui、codegen)是一件很棒的事情,我感谢开发人员的努力,但我想正确使用 codegen,我不认为背后的想法是所以必须以这种方式自定义生成的 ApiClient 和 ApiServices。

The issue is that your specification does not mention the types of Security you want to use (aka Security Definitions) or which Security Definition applies to which end point.问题是您的规范没有提到您要使用的安全类型(又名安全定义)或哪个安全定义适用于哪个端点。

The swagger specification is here , but it doesn't tell the whole story. swagger 规范在这里,但它并没有说明整个故事。

What you need to do is 1. Set up the Security Definitions.您需要做的是 1. 设置安全定义。 Here is a simple basic http auth definition:这是一个简单的基本 http 身份验证定义:

securityDefinitions:
  basic:
    type: basic
    description: HTTP Basic Authentication. 

and 2. Use that security definition in the end point.和 2. 在终点使用该安全定义。

paths:
  /:
    get:
      security:
       - basic: []
      responses:
        200:
          description:  OK

Then regenerate your swagger client code.然后重新生成您的 swagger 客户端代码。 It should set up the immutable map correctly and the authNames array.它应该正确设置不可变映射和 authNames 数组。

As already suggested, if you don't want to modify existing code, you can extend the ApiClient in your custom configuration, eg如前所述,如果您不想修改现有代码,则可以在自定义配置中扩展ApiClient ,例如

@Configuration
public class Config {

  @Value("${baseUrl}")
  private String baseUrl;

  protected class AuthApiClient extends ApiClient {

    public AuthApiClient() {
      super();
    }

    @Override
    public <T> T invokeAPI(final String path, final HttpMethod method,
            final MultiValueMap<String, String> queryParams, final Object body,
            final HttpHeaders headerParams, final MultiValueMap<String, Object> formParams,
            final List<MediaType> accept, final MediaType contentType,
            final String[] authNames, final ParameterizedTypeReference<T> returnType)
            throws RestClientException {

            final HttpBasicAuth auth = new HttpBasicAuth();
            auth.setUsername("myUsername");
            auth.setPassword("myPassword");
            auth.applyToParams(queryParams, headerParams);

      return super.invokeAPI(path, method, queryParams, body, headerParams, formParams,
                accept, contentType, authNames, returnType);
    }
  }

  @Bean
  @Primary
  @Qualifier("MyApiClient")
  public AuthApiClient myApiClient() {
    final AuthApiClient apiClient = new AuthApiClient();
    apiClient.setBasePath(this.baseUrl);
    return apiClient;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Gradle for OpenAPI 3.0 中使用 Swagger Codegen? - How to use Swagger Codegen in Gradle for OpenAPI 3.0? Java REST Client的swagger-codegen头参数 - swagger-codegen header parameter for Java REST Client Swagger - 如何使用swagger-codegen并长期构建项目 - Swagger - how to use swagger-codegen and build a project on the long term Swagger 字典类型(Java 代码生成)使用 LinkedHashMap 而不是 HashMap? - Use LinkedHashMap instead of HashMap for Swagger dictionary type (Java codegen)? swagger-codegen 客户端:如何在模型上包含 jackson 注释 - swagger-codegen client: How to include jackson annotations on models 如何使用 Swagger 代码生成器开发一个简单的 REST 客户端? - How to develop a simple REST Client using Swagger codegen? 如何使用 swagger-codegen-plugin (maven) 生成客户端代码? - How to generate client code using with swagger-codegen-plugin (maven)? 如何使用 swagger-codegen 为 Java 生成具有不同控制器名称的 API? - How to generate API with swagger-codegen with a different controller name for Java? 如何禁用 swagger-codegen java.io.InputStream 转换 - How to disable swagger-codegen java.io.InputStream convertation 如何生成 Swagger codegen Java 模型作为 JPA 实体 - How to generate Swagger codegen Java models as JPA Entities
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM