Swagger Codegen CLI Java Client - как использовать его правильно
в настоящее время я играю с моим сервисом отдыха jersey2. Для лучшего обзора данной услуги (описание, типы и т. д.) Я сильно использую swagger (swagger-jersey2-jaxrs). Таким образом, я могу генерировать свое описание службы (swagger.json), и я могу просматривать и исследовать их через Swagger ui.
теперь я нахожусь в том, что мне нужно создать некоторых клиентов, чтобы использовать эти услуги. Я пришел accrooss swagger codegen cli, который является хорошим инструментом для создания вашего клиента и много разных языков (java в моем случае). Я могу создать клиент api и используемую модель.
здесь я подошел к первой проблеме. Службы REST и описание swagger являются http basic auth protected. Я прочитал документация что дало мне некоторый намек на то, что есть возможность использовать basic auth. В этот момент я должен упомянуть, что с моей точки зрения doucmentation очень плохое. Он говорит:
- a, --auth добавляет заголовки авторизации при удаленном извлечении определений swagger. Передайте строку name:header в кодировке URL с запятой, разделяющей несколько значений.
Первое, что я thoght, это передать строку, как в HTTP-заголовке, но это не работает, и даже поиск в гугле, как использовать basic auth с swagger cli, не привел к некоторому четкому ответчику. После многих попыток и ошибок я (я использую CLI 2.1.2), я, наконец, пришел к правильному формату, например:
java-jar swagger-codegen-cli-2.1.2.jar generate - a "авторизация: базовая YWRtaW46YWRtaW4=" - i http://localhost:8080/webproject/restapi/swagger.в JSON - L java-o restclient
где YWRtaW46YWRtaW4= - это значение, закодированное в base64 admin: admin в моем случае.
пока все хорошо. Сгенерированный клиент java также должен использовать базовую аутентификацию. Я взглянул на методы из ApiClient и нашел setUsername и setPassword. Я думал, что это методы empoweres клиенту использовать базовую аутентификацию, но не повезло.
поэтому я более подробно рассмотрел сгенерированные классы, особенно ApiClient и несколько сгенерированных классов ApiService. Я обнаружил, что 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!");
}
где в то же время HashMap определяется следующим образом:
// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap<String, Authentication>();
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
аутентификация hashmap становится неизменяемой, но почему? Что является целью? Кроме того нет вспомогательные методы внутри ApiClinet, который генерирует необходимый объект auth, поэтому я сделал следующее:
1) прокомментируйте коллекции аутентификаций строк.unmodifiableMap (аутентификации), поэтому hashmap снова становится модифицируемым
2) Создайте необходимый объект auth вручную
HttpBasicAuth authentication = new HttpBasicAuth();
authentication.setUsername("admin");
authentication.setPassword("admin");
3) Добавьте объект auth в HashMap аутентификации apiClients:
ApiClient apiClient = new ApiClient();
apiClient.setBasePath(basePath);
apiClient.getAuthentications().put("basic", authentication);
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);
...
Шаг 4 необходимо, потому что ApiServices вызывают метод apiClient следующим образом:
String[] authNames = new String[] { };
String response = apiClient.invokeAPI(path, "POST", queryParams, postBody, headerParams, formParams, accept, contentType, authNames);
другим возможным решением было бы определить ключ для проверки подлинности hashmap в каждом apiService, например:
String[] authNames = new String[] { "basic" };
после выполнения всех изменений, все работает как надо, но я не могу думать, что это идея автоматически REST-клиента. Поэтому мой вопрос: я пропустил какой-то момент или я должен думать о клиенте, сгенерированном swagger (java в этот случай) больше бета-решения, которое находится в разработке? Пожалуйста, поймите меня правильно, я думаю, что вся структура swagger (поддержка jersey2, openapi, swaggerui, codegen) - отличная вещь, и я ценю усилия разработчиков, но я хочу использовать codegen правильно, и я не думаю, что идея позади так должна настроить сгенерированные ApiClient и ApiServices таким образом.
1 ответов
проблема в том, что в вашей спецификации не упоминаются типы безопасности, которые вы хотите использовать (a.к. a. Определения безопасности) или какое определение безопасности применяется к какой конечной точке.
спецификация swagger является здесь, но это не рассказать всю историю.
что вам нужно сделать, это 1. Настройте определения безопасности. Вот простое базовое определение http auth:
securityDefinitions:
basic:
type: basic
description: HTTP Basic Authentication.
и 2. Используйте это определение безопасности в конце точка.
paths:
/:
get:
security:
- basic: []
responses:
200:
description: OK
затем восстановите свой клиентский код swagger. Он должен правильно настроить неизменяемую карту и массив authNames.