<commit_before>---
layout: post
ref: swagger_openapi_documentation_ru
title: "Swagger API документация"
categories: api, web, swagger
comments: true
locale: ru_RU
lang: ru
summary: ...Swagger API документация...
tags: [api, web, swagger]
---

Нам потребовалось одно моменто согласовать с заказчиком и реализовать более дюжины API.
Каждое всего из нескольких вызовов, но общий объем заставлвл задуматься о стандартизации этого процесса.

Мы попробовали использовать [swagger](http://swagger.io) (он же [OpenAPI](http://swagger.io/specification/)).
Впечатления получились неоднозначные.

1. Нам необходимо было использовать swagger в направлении от документации к коду. Возможно, в обратном направлении
swagger и хорош (по готовому коду создать описание), но генерировать из swagger-описания код на java у нас не получилось.

Мы попробовали все имеющиеся варианты, и поняли, что проще написать руками, чем чистить потом, что получается.

2. Поддержка XML в swagger очень условная. По крайней мере, когда мы попробовали сгенерировать по swagger-описанию
сервер python, чтобы написать эумлятор, мы обнаружили, что в этом сервере вообще нет работы с XML.

Мы на скорую руку что-то впилили (не в таком состоянии, чтобы закинуть это патчем в
[swagger codegen](http://swagger.io/swagger-codegen/)).

3. Сервер для Python генерится на [tornado](http://www.tornadoweb.org/en/stable/) +
[connexion](https://pypi.python.org/pypi/connexion).

Казалось бы, все ок.

Но я обнаружил, что торнадо при этом невозможно использовать в асинхронном режиме.
Что как бы очень печально для эмулятора - эмулируем, например, паузу, и привет, все соедиенения ждут эту паузу.

Задал [вопрос в connexion](https://waffle.io/zalando/connexion), и получил изумительный ответ
giving it more though we would need to actually do quite some changes in other parts of the Connexion code to
support Tornado async. For now the answer is "not possible". :/

И дело не только в режиме использования сервера.

Черт с ней, с паузой, допустим нам надо во время обработки вызова сделать асинхронно другой вызов, через
сгенерированный swagger codegen клиент. На python генерится код, который вроде поддерживает асинхронность.

Смотрим внутрь него и видим, что в асинхронном режиме единственное что он делает - стартует еще одну нитку.
Прекрасно, а если в нитке exception? Это никак не обрабатывается.

4. Жесткая формализация и верификация описания это все-таки большое благо.

Так что не смотря на все эти фейлы, используя swagger мы получили четкое орписание, многие ошибки в котором
обнаруживаются на фазе проверки swagger.

И из которого мы генерим код для эмуляторов и тестовых клиентов, что позволяет существенно экономить усилия на фазе
активного изменения API.

Но при этом инструмент настолько крив, что с удовольствием взяли бы что-то иное, но вот что?


<commit_msg>Swagger article<commit_after>---
layout: post
ref: swagger_openapi_documentation_ru
title: "Swagger API документация"
categories: api, web, swagger
comments: true
locale: ru_RU
lang: ru
summary: ...Swagger API документация...
tags: [api, web, swagger]
---

Нам потребовалось согласовать с заказчиком и реализовать более дюжины API.
Каждое всего из нескольких вызовов, но общий объем заставлял задуматься о стандартизации этого процесса.

Мы попробовали использовать [swagger](http://swagger.io) (он же [OpenAPI](http://swagger.io/specification/)).
Впечатления получились неоднозначные.

### 1
Нам необходимо было использовать swagger в направлении от документации к коду. Возможно, в обратном направлении
swagger и хорош (по готовому коду создать описание), но генерировать из swagger-описания код на java у нас не получилось.

Перебрали все имеющиеся в [swagger codegen](http://swagger.io/swagger-codegen/) варианты, и поняли, что проще написать
руками, чем чистить то, что генерирует codegen.

### 2
Поддержка XML в swagger очень условная. По крайней мере, когда мы попробовали сгенерировать по swagger-описанию
сервер python, чтобы написать эмулятор, мы обнаружили, что в этом сервере вообще нет работы с XML.

Мы на скорую руку добавили работу с XML, но не в таком состоянии, чтобы закинуть это патчем в
swagger codegen.
Так что теперь у нас локально патченный код и нельзя просто брать свежие codegen.

### 3
Сервер для Python генерится на [tornado](http://www.tornadoweb.org/en/stable/) +
[connexion](https://pypi.python.org/pypi/connexion).

Казалось бы, все ок.

Но обнаружилось, что торнадо при этом невозможно использовать в асинхронном режиме.
Что как бы очень печально для эмулятора. Эмулируем, например, паузу - и привет, все соединения ждут эту паузу.

Задал [вопрос в connexion](https://waffle.io/zalando/connexion), и получил изумительный ответ:
> giving it more though we would need to actually do quite some changes in other parts of the Connexion code to
support Tornado async. For now the answer is "not possible". :/

И дело не только в режиме использования tornado.

Допустим, нам надо во время обработки вызова сервера эмулятора сделать асинхронно другой вызов, через
сгенерированный swagger codegen клиент.

На python в swagger генерится код клиента, который вроде поддерживает асинхронность.
Смотрим внутрь него и видим, что в асинхронном режиме единственное что он делает - стартует еще одну нитку.
Прекрасно, а если в нитке exception? Это никак не обрабатывается.

### 4
Жесткая формализация и верификация описания это безусловно большое благо.

Не смотря на все описанные выше проблемы, используя swagger мы получили четкое орписание, многие ошибки в котором
обнаруживаются на фазе проверки swagger.

Которое легко рефакторить.

И из которого мы генерим код для эмуляторов и тестовых клиентов, что позволяло нам существенно экономить усилия на фазе
активного изменения API.
По сути, мы могли макетировать - а давайте попробуем вот сюда добавить вызов, перенести параметры из этого вызова в тот,
и посмотрим, что получится, попробуем это использовать.

Swagger настолько крив, что с удовольствием взяли бы что-то иное, но вот что?



{'fraction_non_alphanumeric': 0.05993322203672788, 'fraction_numerical': 0.001335559265442404, 'mean_word_length': 4.914116485686081, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2490808', 'n_tokens_mistral': 2300, 'n_tokens_neox': 2702, 'n_words': 798}