Разработка HTTP-плагина
Как устроен Meridian Plugin API и как создать плагин в отдельном процессе на любом языке.
Обзор
HTTP-плагин — это обычный HTTP-сервер, который реализует Meridian Plugin API. Meridian подключается к нему по сети и передаёт вызовы тех же хуков, что и для in-process плагина: транспортных, LLM, MCP и наблюдаемости. Логика плагина выполняется в его собственном процессе, а в Meridian от плагина остаётся только адрес и список хуков.
Спецификация протокола опубликована в формате OpenAPI 3.1: Meridian Plugin API. Все сообщения — JSON, схемы описаны в JSON Schema 2020-12, поэтому по ним можно сгенерировать типы для любого языка.
Когда выбирать HTTP-плагин вместо разделяемой библиотеки:
- Любой язык — Go, Python, Node.js, Rust: достаточно HTTP-сервера с поддержкой WebSocket.
- Без бинарной совместимости — не нужно совпадение версии Go, зависимостей и флагов сборки с Meridian; стандартные образы Meridian подходят без изменений.
- Изоляция — сбой или утечка памяти в плагине не затрагивает процесс шлюза; плагин можно обновлять и перезапускать независимо.
- Кластер — один экземпляр плагина обслуживает все узлы Meridian; регистрация выполняется один раз, каждый узел подключается сам.
- Выборочный вызов — условие вызова задаётся CEL-выражением по атрибутам запроса, поэтому плагин получает только нужный трафик.
Цена — сетевой вызов на каждый хук. Для потоковых ответов это вызов на каждый фрагмент, поэтому объявляйте только те хуки, которые действительно нужны.
Предварительные требования
- Любой стек, на котором можно поднять HTTP/1.1-сервер с поддержкой WebSocket (RFC 6455) и JSON.
- Сетевая доступность плагина с каждого узла Meridian: адрес вида
http(s)://host:port. - Meridian установлен и настроен; для регистрации плагина нужны права глобального администратора.
Как устроен протокол
Операции
Каждый вызов — это POST /api/meridian/plugin/v1/{method}, где {method} — имя хука в нижнем регистре (prellmhook, httptransportprehook, init). Тело запроса и ответа — JSON-сообщения из спецификации. Кроме хуков плагин отвечает на четыре вызова жизненного цикла и две пробы:
| Вызов | Назначение |
|---|---|
POST /capabilities | Список реализованных хуков, версия протокола (сейчас 1) и признак поддержки HookStream. Meridian вызывает его первым при каждом подключении |
POST /init | Передача конфигурации плагина (поле config его записи). Вызывается один раз после capabilities, если конфигурация задана; ошибка в ответе прерывает загрузку |
POST /getname | Системный идентификатор плагина |
POST /cleanup | Освобождение ресурсов перед остановкой |
GET /health | Состояние процесса: 200 со статусом ok или degraded, 503 — unavailable. Необязательна: при 404 Meridian использует POST /capabilities |
GET /status | Имя, версия, список хуков, время работы и счётчики. Необязательна: при 404 Meridian сохраняет ответ capabilities, полученный при загрузке |
Ответ capabilities для плагина, который реализует один хук:
{
"hooks": ["PreLLMHook"],
"protocol_version": 1,
"stream_supported": true
}Meridian никогда не вызывает хук, которого нет в этом списке. Также он отказывается загружать плагин с другой версией протокола или без stream_supported: true.
HookStream
GET /api/meridian/plugin/v1/hookstream переводит соединение в WebSocket. После этого каждый двоичный кадр от Meridian — одно сообщение HookStreamRequest, каждый кадр от плагина — HookStreamResponse с тем же id. Именно по этому каналу Meridian вызывает все хуки; POST-маршруты остаются для capabilities, инструментов и отладки.
Сообщение-конверт содержит id, имя вызова call и ровно одно свойство с полезной нагрузкой, имя которого — имя вызова в snake_case:
{
"id": 42,
"call": "PreLLMHook",
"pre_llm_hook": {
"ctx": { "request_id": "8d1c…", "deadline_unix_nano": 1790000000000000000, "values": {} },
"request": { "request_type": "chat_completion", "request": { "provider": "openai", "model": "gpt-4o-mini", "input": [ { "role": "user", "content": "Hello!" } ] } }
}
}Ответ повторяет id и несёт ответное сообщение под тем же свойством:
{ "id": 42, "call": "PreLLMHook", "pre_llm_hook": {} }Если вызов невозможно выполнить вовсе (неизвестный call, нечитаемое сообщение, плагин останавливается), плагин отвечает transport_error вместо полезной нагрузки:
{ "id": 42, "transport_error": "unknown call PreFooHook" }Meridian держит отдельное соединение на каждый одновременный вызов и не перемежает запросы в одном соединении, поэтому обработчик кадров может быть простым циклом «прочитал — ответил». Неиспользуемые соединения остаются в пуле; закрывать их со стороны плагина безопасно, повторный вызов уйдёт по новому соединению.
Флаг body_changed
Каждый ответ хука несёт флаг body_changed. По умолчанию он false: Meridian сохраняет свои объекты без изменений и даже не декодирует полезную нагрузку ответа, поэтому её можно не отправлять. Это самый дешёвый ответ — пустой объект {}.
При body_changed: true полезная нагрузка ответа заменяет объекты Meridian на месте. Отсутствующее свойство при этом означает null: пустое тело, снятую ошибку, отброшенный фрагмент. Для LLM-запросов ответ можно сделать частичным: Meridian накладывает присланный JSON на свою типизированную структуру, поэтому достаточно вернуть только изменённые поля.
{
"request": { "request_type": "chat_completion", "request": { "provider": "openrouter", "model": "deepseek/deepseek-v4-flash" } },
"body_changed": true
}Транспортные метаданные пересланного запроса или ответа (method, path, headers, query, status_code) применяются всегда, когда объект присутствует в ответе, независимо от флага.
Контекст запроса
Meridian передаёт в каждом хуке проекцию контекста запроса — ctx:
request_id— идентификатор запроса;deadline_unix_nano— абсолютный срок обработки в наносекундах Unix,0— без срока;values— значения контекста по ключам Meridian: виртуальный ключ, команда, клиент, идентификатор пользователя, тип запроса и другие. Учётные данные (ключи провайдеров, токены сессии, значение виртуального ключа) не передаются никогда;plugin_scope— имя плагина, для которого сформирован контекст.
Плагин записывает в контекст через ctx в ответе — ContextDelta с полями set (установить ключи) и clear (удалить ключи). Meridian применяет их к настоящему контексту, поэтому значение, записанное в PreLLMHook, доступно тому же плагину в PostLLMHook. Зарезервированные ключи Meridian отбрасывает так же, как для in-process плагина.
{ "ctx": { "set": { "my-plugin-tenant": "acme" }, "clear": ["my-plugin-tmp"] } }Ошибки хука и ошибки транспорта
Протокол различает три вида ошибок:
| Вид | Как передаётся | Что делает Meridian |
|---|---|---|
| Ошибка хука | Поле error: {"message": "…"} в ответном сообщении — аналог error, который возвращает Go-хук | Та же семантика, что для in-process плагина: журналируется, для PreRequestHook не блокирует запрос |
| Ошибка Meridian как результат | BifrostError в short_circuit.error (pre-хуки) или plugin_error (post-хуки): status_code, error.type, error.message, allow_fallbacks | Возвращается клиенту как ответ шлюза; allow_fallbacks: false запрещает переход на резервных провайдеров |
| Ошибка транспорта | HTTP-статус 4xx/5xx POST-вызова, transport_error в кадре, таймаут, разрыв соединения | Считается сбоем плагина: учитывается в circuit breaker и обрабатывается по политике on_error |
Для отказа в обработке запроса используйте short_circuit.error со статусом 4xx и типом ошибки, а не HTTP-статус POST-ответа. HTTP-статусы зарезервированы под сбои транспорта: такой ответ Meridian воспримет как недоступность плагина, а не как решение по запросу.
Здоровье и отказоустойчивость
Каждый узел Meridian опрашивает плагин с периодом health_interval_seconds (по умолчанию 15 с): GET /health, а каждый N-й раз — GET /status, откуда обновляется список заявленных хуков и версия плагина. После failure_threshold (по умолчанию 5) сбоев транспорта подряд узел открывает circuit breaker и перестаёт вызывать плагин; закрывает его только успешная проба, пробных вызовов на пути запроса нет.
Политика on_error определяет поведение при сбое транспорта в pre-хуке: fail_closed (по умолчанию) отклоняет запрос с кодом 503 plugin <name> unavailable, fail_open пропускает запрос дальше с предупреждением в трассе. Post-хуки, хуки фрагментов, Inject и PreRequestHook при сбое транспорта всегда пропускают запрос: ответ уже сформирован либо хук по контракту не блокирует.
Состояние плагина ведётся на каждом узле отдельно: active, unhealthy (breaker открыт или последняя проба не прошла), error (загрузка не удалась: недоступен, другая версия протокола, нет HookStream, ошибка Init, конфликт имён), disabled, loading.
Хуки и их сообщения
Каждый хук принимает ctx и данные своего этапа и отвечает сообщением с необязательными error, ctx и body_changed. Ниже — специфичные для хуков поля. Порядок выполнения и различие фаз описаны в разделе Начало работы.
Транспортные хуки
HTTPTransportPreHook получает HTTP-запрос до входа в ядро Meridian, HTTPTransportPostHook — запрос и ответ после выхода, HTTPTransportStreamChunkHook — каждый фрагмент потокового ответа.
Запрос описывается объектом RequestDetails: method, path, headers, query, path_params, client_ip, attempt (номер попытки, начиная с 1) и тело — body (JSON как есть), либо body_b64 (base64 для тела, не являющегося JSON). Ответ — ResponseDetails: status_code, headers, body или body_b64.
Ответ HTTPTransportPreHook:
requestсbody_changed: true— изменённый запрос;response— досрочное завершение с готовым HTTP-ответом:
{
"response": { "status_code": 429, "headers": { "Content-Type": "application/json" }, "body": { "error": { "message": "quota exceeded" } } }
}Ответ HTTPTransportStreamChunkHook несёт chunk — объект StreamChunk с полями index (порядковый номер фрагмента), request_type и chunk (JSON фрагмента в формате Meridian). body_changed: true без chunk отбрасывает фрагмент.
HTTPTransportPostHook не вызывается для потоковых ответов, а HTTPTransportStreamChunkHook вызывается для каждого фрагмента. Для длинного потокового ответа это сотни сетевых вызовов; объявляйте хук фрагментов только тогда, когда плагин действительно изменяет поток.
Хуки LLM
PreRequestHook, PreLLMHook и PostLLMHook работают с типизированным запросом Meridian: объект LLMRequest содержит request_type (chat_completion, chat_completion_stream, embedding, responses и другие) и request — JSON запроса этого типа, например provider, model, input и params для chat completion.
PreRequestHook — фаза маршрутизации, один раз на запрос. Ответ содержит только request с body_changed; досрочного завершения нет, ошибка хука не блокирует запрос. Пример из плагина маршрутизации, который меняет провайдера и модель:
{
"request": { "request_type": "chat_completion", "request": { "provider": "openrouter", "model": "deepseek/deepseek-v4-flash" } },
"body_changed": true
}PreLLMHook — перед каждой попыткой обращения к провайдеру. Ответ может изменить запрос (request + body_changed) или завершить обработку досрочно через short_circuit с одним из двух полей: response (готовый ответ типа request_type) или error. Пример отказа guardrail-плагина:
{
"short_circuit": {
"error": {
"status_code": 400,
"allow_fallbacks": false,
"error": { "type": "guardrail_violation", "message": "request contains a phone number" }
}
}
}PostLLMHook получает response (объект LLMResponse: request_type и response) и/или error (BifrostError провайдера). При body_changed: true ответ плагина заменяет оба объекта: response и plugin_error; отсутствующее поле означает null, так что плагин может снять ошибку провайдера, вернув только response.
Хуки MCP
PreMCPHook и PostMCPHook вызываются для каждой операции MCP-шлюза: объект MCPRequest содержит request_type (ping, list_tools, execute_tool, chat_tool_call, responses_tool_call), client_name и request. PreMCPConnectionHook и PostMCPConnectionHook — при установлении транспорта MCP-клиента: MCPConnectRequest с client_name, connection_type, auth_type, connection_string, headers. Ответы устроены так же, как у LLM-хуков: request/response с body_changed, short_circuit с response или error, plugin_error в post-хуках. В PreMCPConnectionHook заменяются только изменяемые поля — connection_string и headers.
Наблюдаемость и конфигурация
Inject получает завершённую трассу запроса: атрибуты, заголовки, записи плагинов и спаны. Хук не имеет контекста запроса и вызывается после отправки ответа клиенту, поэтому подходит для экспорта в системы трассировки, но не для изменения данных.
MarshalConfigForStorage и RedactConfig получают объект config и возвращают преобразованный: первый — перед сохранением конфигурации в хранилище (например, шифрование секретов), второй — перед отдачей конфигурации в API и интерфейс (маскирование).
Фильтр запросов (CEL)
Условие вызова плагина задаётся CEL-выражением при регистрации; пустое выражение означает каждый запрос. Meridian вычисляет его один раз на запрос до транспортных хуков, и один результат действует для всех хуков плагина. Запрос, не прошедший фильтр, не порождает ни одного сетевого вызова.
| Переменная | Тип | Описание |
|---|---|---|
method, path | string | HTTP-метод и путь |
headers, query | map | Заголовки (имена в нижнем регистре) и query-параметры |
client_ip | string | Адрес клиента |
request_type | string | Тип запроса Meridian, например chat_completion_stream |
provider, model | string | Провайдер и модель из тела запроса |
virtual_key_id, virtual_key_name | string | Виртуальный ключ запроса |
team_id, team_name, customer_id, customer_name, user_id | string | Владелец виртуального ключа |
Примеры:
request_type.startsWith("chat_completion")
path == "/v1/chat/completions" && customer_name == "acme"
headers["x-tenant"] == "premium"Переменная, для которой нет источника (например, team_id в запросе без виртуального ключа), не вызывает ошибку: сравнение с ней просто не совпадает. Синтаксически неверное выражение отклоняется при сохранении с кодом 400. В веб-интерфейсе выражение можно собрать конструктором правил, как для правил маршрутизации.
Шаг 1. Реализуйте плагин
Минимальный плагин отвечает на четыре вызова жизненного цикла, отдаёт GET /health, обслуживает HookStream и реализует один хук. Рекомендуемый порядок работы:
- Сгенерируйте типы сообщений из спецификации или опишите вручную только те, что нужны вашим хукам: имена свойств — snake_case, как в схемах.
- Реализуйте диспетчер по имени вызова и используйте его и для POST-маршрутов, и для кадров HookStream: сообщения одинаковы, различается только конверт.
- Отвечайте
{}(body_changed: false) всегда, когда плагин ничего не изменил; отправляйте полезную нагрузку только при изменении. - Для решений по запросу используйте
short_circuit, для сбоев самого плагина —errorв сообщении. Не используйте HTTP-статусы для бизнес-логики. - Печатайте при запуске строку
MERIDIAN|1|tcp|<адрес>— по ней инструменты и будущий управляемый режим находят плагин.
Готовые реализации на Go, которые можно взять за основу: минимальный http-plugin-example-go, а также плагин guardrail и плагин маршрутизации, разобранные в отдельных руководствах.
Шаг 2. Проверьте плагин без Meridian
POST-маршруты позволяют проверить плагин обычным curl:
curl -s -X POST http://localhost:18081/api/meridian/plugin/v1/capabilities -d '{}'
curl -s -X POST http://localhost:18081/api/meridian/plugin/v1/prellmhook -d '{
"ctx": {"request_id": "r1"},
"request": {"request_type": "chat_completion",
"request": {"provider": "openai", "model": "gpt-4o-mini", "input": [{"role": "user", "content": "hi"}]}}
}'
curl -s http://localhost:18081/api/meridian/plugin/v1/healthПервый вызов должен вернуть список хуков с protocol_version: 1 и stream_supported: true, второй — ответ хука ({} для плагина, который ничего не меняет), третий — {"status":"ok"}.
Шаг 3. Зарегистрируйте плагин в Meridian
- Перейдите в Settings → Plugins.
- Нажмите Add HTTP plugin.

- Укажите Name и URL — схему, хост и порт плагина без пути.
- В поле Hooks выберите хуки, которые реализует плагин. Вызываются только хуки, объявленные здесь и заявленные плагином в
capabilities. - При необходимости задайте Request filter — конструктором или CEL-выражением.
- Выберите On transport error:
Fail closedилиFail open, и Placement относительно встроенных плагинов. - В свёрнутых разделах доступны лимиты (таймаут вызова, число соединений, порядок), заголовки, которые Meridian отправляет плагину, и параметры TLS.
- Нажмите Add. Meridian сразу подключается к плагину; статус, заявленные и эффективные хуки и здоровье по узлам видны в деталях плагина.
curl -X POST http://localhost:8080/api/plugins \
-H "Content-Type: application/json" \
-d '{
"plugin_architecture": "http",
"name": "my-http-plugin",
"enabled": true,
"url": "http://plugin-host:18081",
"capabilities": ["PreLLMHook", "PostLLMHook"],
"cel": "request_type.startsWith(\"chat_completion\")",
"on_error": "fail_closed",
"placement": "post_builtin",
"headers": { "Authorization": "Bearer ${PLUGIN_TOKEN}" },
"config": { "mode": "block" }
}'Ответ:
{
"message": "Plugin created successfully",
"plugin": {
"name": "my-http-plugin",
"enabled": true,
"plugin_architecture": "http",
"placement": "post_builtin",
"http": {
"url": "http://plugin-host:18081",
"cel": "request_type.startsWith(\"chat_completion\")",
"capabilities_declared": ["PreLLMHook", "PostLLMHook"],
"capabilities_reported": ["PreLLMHook", "PostLLMHook"],
"capabilities_effective": ["PreLLMHook", "PostLLMHook"],
"on_error": "fail_closed",
"protocol_version": 1,
"plugin_version": "1.1.0",
"reported_name": "MyPlugin",
"headers": { "Authorization": "***" },
"health": { "status": "active", "breaker": "closed", "consecutive_failures": 0, "open_conns": 1 }
}
}
}| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
plugin_architecture | string | Да | http |
name | string | Да | Имя записи; под ним плагин виден в API, интерфейсе и Plugin Logs |
url | string | Да | http(s)://host[:port] без пути |
capabilities | array | Да | Объявляемые хуки |
cel | string | Нет | Фильтр запросов; пусто — каждый запрос |
on_error | string | Нет | fail_closed (по умолчанию) или fail_open |
placement, order | string, integer | Нет | Место относительно встроенных плагинов и порядок внутри группы |
call_timeout_ms | integer | Нет | Таймаут одного вызова; ограничен сроком запроса |
max_conns | integer | Нет | Предел одновременных вызовов плагина с одного узла |
headers | object | Нет | Заголовки, которые Meridian отправляет при открытии HookStream и в пробах; хранятся зашифрованно, в ответах API маскируются |
tls | object | Нет | insecure_skip_verify, ca_pem — для https с собственным центром сертификации |
config | object | Нет | Конфигурация, передаваемая в init |
Другие операции: GET /api/plugins, GET /api/plugins/{name}, PUT /api/plugins/{name} (полная замена записи), DELETE /api/plugins/{name}, POST /api/plugins/{name}/probe — проба немедленно. В кластере параметр ?target=<узел> показывает состояние плагина на другом узле. Архитектуру существующего плагина изменить нельзя.
{
"plugins_http": {
"health_interval_seconds": 15,
"call_timeout_ms": 2000,
"failure_threshold": 5,
"plugins": [
{
"name": "my-http-plugin",
"enabled": true,
"version": 1,
"url": "http://plugin-host:18081",
"capabilities": ["PreLLMHook", "PostLLMHook"],
"cel": "request_type.startsWith(\"chat_completion\")",
"on_error": "fail_closed",
"placement": "post_builtin",
"headers": { "Authorization": "Bearer ${PLUGIN_TOKEN}" },
"config": { "mode": "block" }
}
]
}
}Записи plugins_http.plugins[] имеют те же поля, что и API, плюс version: увеличение номера при следующем запуске принудительно обновляет запись в базе. В значениях headers раскрываются переменные окружения ${ENV}.
Параметры блока plugins_http действуют на все HTTP-плагины узла:
| Поле | По умолчанию | Описание |
|---|---|---|
health_interval_seconds | 15 | Период проб /health на каждом узле |
health_timeout_seconds | 3 | Таймаут пробы |
status_every_n_probes | 4 | Каждая N-я проба обновляет /status |
dial_timeout_seconds | 5 | Таймаут установления соединения |
call_timeout_ms | 2000 | Таймаут вызова хука по умолчанию |
load_timeout_seconds | 10 | Таймаут загрузки плагина (capabilities, init, getname) |
cleanup_timeout_seconds | 2 | Таймаут cleanup при остановке |
max_idle_conns | 16 | Соединений HookStream в пуле на плагин |
failure_threshold | 5 | Сбоев транспорта подряд до открытия circuit breaker |
max_frame_bytes | 64 МиБ | Максимальный размер кадра |
HTTP-плагины описываются только в plugins_http.plugins[]. Запись HTTP-плагина в общем массиве plugins[] Meridian воспримет как неизвестный встроенный плагин.
Шаг 4. Проверьте работу
Выполните запрос, который проходит фильтр плагина:
curl -X POST http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <virtual key>" \
-d '{
"model": "openai/gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello!"}]
}'Затем проверьте:
- Детали плагина на странице Settings → Plugins: статус
active, эффективные хуки, таблица здоровья по узлам, кнопка Probe now. - Plugin Logs в деталях запроса (LLM Logs → запрос): Meridian записывает строку под именем плагина для каждого вызова, в котором плагин что-то изменил —
PreLLMHook: request changed,PreLLMHook: short-circuit 400 guardrail_violation: …,PostLLMHook: response changed; для потоковых ответов одна итоговая строка на поток. Вызов, который ничего не изменил, строки не оставляет. - Лог самого плагина: примеры печатают входящее и исходящее сообщение каждого вызова.
Эксплуатация
- Аутентификация плагина. Meridian отправляет настроенные
headersпри открытии HookStream и в пробах; плагин сам решает, требовать ли их. Для сетей общего доступа задайтеAuthorization: Bearer <токен>и проверяйте его на upgrade-запросе. - TLS. Для
https-адреса с сертификатом собственного центра укажитеtls.ca_pem;insecure_skip_verifyдопустим только в тестовых средах. - Таймауты. Вызов хука ограничен
call_timeout_msи сроком самого запроса. Плагин, который не укладывается в лимит, считается сбойным: следите, чтобы медленная работа (обращения к внешним сервисам, тяжёлые модели) не открывала circuit breaker. - Кластер. Регистрация выполняется один раз; каждый узел подключается к тому же адресу и ведёт собственное состояние здоровья. Плагин должен быть готов к нескольким одновременным соединениям с разных узлов.
- Идентификатор. Имя записи в Meridian — это имя, под которым плагин виден везде; имя, возвращаемое
getname, сохраняется какreported_nameи служит для сверки. - Обновление. Плагин можно перезапускать независимо от Meridian: соединения переустанавливаются, а на время недоступности действует политика
on_error. Изменение записи (PUT) заново загружает плагин:capabilities→init→getname.
Диагностика
Статус error сразу после регистрации
Причины: адрес недоступен с узла Meridian; capabilities вернул protocol_version, отличный от 1, или stream_supported: false; init ответил ошибкой; другой плагин уже использует то же имя.
Решение: проверьте POST /capabilities с узла Meridian (curl из контейнера или хоста шлюза), исправьте ответ плагина, при необходимости выполните Probe now — узел повторяет загрузку при следующей пробе.
Хук не вызывается
Причины: хук не объявлен в записи плагина; хук не заявлен плагином в capabilities (в деталях плагина он есть в capabilities_declared, но отсутствует в capabilities_reported и capabilities_effective); запрос не проходит CEL-фильтр; хук HTTPTransportPreAuthHook не вызывается в текущей версии.
Решение: сверьте три списка в деталях плагина и проверьте выражение фильтра на запросе, который должен проходить.
Клиент получает 503 plugin <name> unavailable
Причина: сбой транспорта в pre-хуке при политике fail_closed: таймаут, разрыв соединения, кадр больше max_frame_bytes, ответ transport_error, открытый circuit breaker.
Решение: смотрите last_probe_error и consecutive_failures в здоровье плагина, лог плагина на предмет ошибок разбора сообщения; на время устранения переключите плагин в fail_open, если пропуск запросов допустим.
Статус unhealthy
Причина: circuit breaker открыт после серии сбоев или последняя проба /health не прошла.
Решение: breaker закрывает только успешная проба; после восстановления плагина статус вернётся к active в течение health_interval_seconds.
Изменение запроса не применяется
Причина: в ответе нет body_changed: true — Meridian не декодирует полезную нагрузку, если флаг не установлен.
Решение: возвращайте body_changed: true вместе с изменённым объектом; помните, что при этом отсутствующие свойства означают null.
Что дальше
- Начало работы — виды плагинов, жизненный цикл и порядок хуков.
- Разработка Go-плагина — in-process плагин в виде разделяемой библиотеки.
- Как собрать плагин маршрутизации — HTTP-плагин, который меняет провайдера и модель в
PreRequestHook. - Как собрать плагин guardrail — HTTP-плагин, который блокирует и маскирует данные в запросах и ответах.
- Meridian Plugin API — полная спецификация OpenAPI.