Пример проекта
outry-example-gin — небольшой API магазина на
Gin: логин, пользователи, заказы и асинхронная оплата. В папке api/
каждый роут описан .outry-файлом, и вместе они используют все возможности формата — это ещё и экскурсия.
-
Установите CLI (другие платформы) и склонируйте проект:
Окно терминала curl -fsSL https://raw.githubusercontent.com/1rowvy/outry/master/install.sh | shgit clone https://github.com/1rowvy/outry-example-gin && cd outry-example-gin -
Запустите сервис — он всё хранит в памяти, пароль администратора
admin:Окно терминала go run . & -
Передайте Outry пароль.
admin_passwordобъявлен секретом вapi/env.toml, поэтому берётся из хранилища паролей или переменнойOUTRY_*, но не из файла:Окно терминала export OUTRY_ADMIN_PASSWORD=admin # или: outry secret set admin_password -
Запустите все запросы и сценарии:
Окно терминала outry run api✓ api/flows/checkout.outry Checkout flow↳ CreateUser 201 0ms↳ Login cached↳ CreateOrder 201 0ms↳ PayOrder 202 0ms↳ WaitUntilPaid 200 1ms✓ paid.body.total == 45.5✓ paid.body.user_id == user.body.id→ saved last_order…22 passed, 0 failedУ
DeleteUserстоитconfirm: true, поэтому Outry спросит перед отправкой;--yesотвечает за вас.
Поменяйте код
Заголовок раздела «Поменяйте код»Каждый созданный запрос знает свой обработчик (handler: s.CreateUser). Переименуйте поле структуры
запроса в internal/model/model.go:
type CreateUser struct { Name string `json:"name" binding:"required"` // full name FullName string `json:"full_name" binding:"required"` // full nameoutry check читает исходники Go — компилировать и запускать ничего не нужно:
api/v1/users/post.outry:17:8: error: required field `full_name` (string) is missing from body ← internal/api/users.go:13api/v1/users/post.outry:17:10: error: body field `name` is not in model.CreateUser ← internal/api/users.go:1314 files, 2 environments, 12 Go routes: 2 errors, 0 warnings; 2 fixable with `outry import go --fix`outry import go . --fix перепишет тело. В пулл-реквесте workflow проекта (outry check --format github)
покажет те же ошибки на изменённых строках. Добавьте роут — outry import go . создаст для него запрос
с уже заполненными телом, query, заголовками и проверкой ответа.
Что где
Заголовок раздела «Что где»| Возможность | Файл |
|---|---|
| Окружения, общие переменные, секрет, middleware → заголовки | api/env.toml |
| Проверки статуса, полей, заголовков, времени; JSON Schema | api/health.outry |
Параметры со значениями по умолчанию, cache: 50m между прогонами, негативный тест |
api/auth/login/post.outry |
Тело form, cookie jar, cookies.session |
api/auth/session.outry |
Вызовы: Login().body.token, CreateUser().body.id, один раз за прогон |
api/v1/users/get-by-id.outry |
Вызовы с аргументами, only: [dev], confirm: true |
api/v1/users/delete-by-id.outry |
Загрузка файла через multipart |
api/v1/users/avatar/post.outry |
let на уровне файла, uuid(), арифметика, all / map, save |
api/v1/orders/post.outry |
query-параметры со значением null не отправляются |
api/v1/orders/get.outry |
poll до подтверждения оплаты |
api/v1/orders/pay/post.outry |
Сценарии; идемпотентный повтор с fresh |
api/flows/checkout.outry |
| Shape из структур Go, ужесточённые вручную | api/shapes.outry |
outry check и outry run в GitHub Actions |
.github/workflows/api.yml |
Коллекция началась с outry init и outry import go .; потом запросы получили проверки, параметры и
вызовы, часть файлов переехала — outry import всё равно узнаёт их по handler:.