JSON-RPC
JSON-RPC
POST /{prefix}/{database}/jsonrpc викликає функцію PostgreSQL і повертає її результат як відповідь
JSON-RPC 2.0. Ця сторінка є довідником;
перший робочий приклад дивіться в розділі Швидкий старт.
1. Запит
POST /db/my_database/jsonrpc
Authorization: Basic ... (або Bearer <jwt / api token>)
Content-Type: application/json
{"jsonrpc": "2.0", "method": "api.hello_world", "params": {"name": "Alice"}, "id": 1}| Поле | Опис |
|---|---|
method | Обов’язкове. schema.function, не більше 256 символів. Допускаються ідентифікатори в лапках ("my schema"."my fn"). Схема обов’язкова: самотнє hello_world відхиляється з кодом 400. capabilities — вбудований метод (розділ 5). |
params | Будь-яке значення JSON, яке передається функції без змін як її аргумент jsonb. Відсутнє або null стає {}. Загальноприйняті об’єкти; масиви та скалярні значення також працюють. |
id | Будь-яке значення JSON; копіюється у відповідь. Якщо його немає, відповідь містить "id": null (сповіщень типу fire-and-forget не існує). |
jsonrpc | Зазвичай "2.0"; на вході не перевіряється, відповідь завжди містить "2.0". |
idempotencyKey | Необов’язкове розширення (розділ 7). Не більше 256 символів. |
Пакетні запити (масив JSON з викликами) не підтримуються й повертають 400 — надсилайте один виклик в одному HTTP-запиті.
2. Відповідь
HTTP 200 {"jsonrpc":"2.0","result":{"message":"Hello, Alice!"},"id":1}
HTTP 404 {"jsonrpc":"2.0","error":{"code":-32601,"message":"Function does not exist"},"id":1}На відміну від звичайного JSON-RPC через сокет, помилки також встановлюють змістовний HTTP-статус, тож клієнти й проксі можуть реагувати
без розбору тіла. error.code дорівнює 0, якщо не застосовується конкретний код JSON-RPC
(-32601 невідома функція, -32001 відмовлено в доступі, -32000 дубльований запит).
Повний список є на сторінці Коди помилок.
3. Написання функції
Метод — це функція PostgreSQL, яка приймає рівно один аргумент типу jsonb
і повертає json або jsonb. Функції з іншими сигнатурами не перелічуються в
capabilities і не можуть бути викликані.
CREATE OR REPLACE FUNCTION api.find_user(payload jsonb DEFAULT '{}'::jsonb)
RETURNS json LANGUAGE sql STABLE AS $$
SELECT row_to_json(u) FROM (
SELECT id, name FROM app.users WHERE id = (payload->>'id')::int
) u;
$$;
GRANT USAGE ON SCHEMA api TO web_user;
GRANT EXECUTE ON FUNCTION api.find_user(jsonb) TO web_user;- Значення, що повертається. Результат JSON надсилається як
result. SQL-значенняNULL(як вище, коли жоден рядок не підходить) стає"result": null. Функція має повертати коректний JSON: типtextпризводить до помилки 500, якщо текст випадково не є JSON — для рядкового результату використовуйтеto_json('hi'::text). - Помилки всередині функції.
RAISE EXCEPTIONабо будь-яка помилка SQL перериває виклик з HTTP 500 і загальним повідомленнямFunction call failed; справжнє повідомлення PostgreSQL записується лише в журнал сервера, тож подробиці схеми не витікають. Очікувані бізнес-помилки (не знайдено, валідація) повідомляйте радше в значенні, що повертається, наприклад{"ok": false, "reason": "..."}. - Транзакції. Кожен виклик виконується в одній транзакції, яка фіксується, коли функція повертає результат, і відкочується за будь-якої помилки.
- Права доступу. Виклик виконується від імені автентифікованої ролі PostgreSQL, тож
GRANT,REVOKEі Row-Level Security визначають, що дозволено викликачу. Ролі потрібніUSAGEна схему таEXECUTEна функцію. PostgreSQL за замовчуванням надаєEXECUTEна нові функції всім, тому скасуйте це (ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC) і тримайте відкриті функції в окремій схемі — див. Безпека та автентифікація.
4. Опис функції для клієнтів і ШІ-агентів
Перший рядок коментаря функції є її описом; об’єкт JSON після --- PARAMS --- описує параметри
(properties у JSON Schema). Обидва з’являються в capabilities, специфікації OpenAPI та MCP tools/list:
COMMENT ON FUNCTION api.find_user(jsonb) IS 'Looks up a user by id.
--- PARAMS ---
{"id": {"type": "integer", "description": "User id"}}';Коментар із некоректним JSON після маркера ігнорується (функція повертається до загального опису параметрів) і ніколи не ламає виявлення.
5. Вбудовані методи
capabilities
Перелічує функції, які автентифікована роль може викликати (EXECUTE і USAGE на схему); системні схеми та функції розширень приховані.
Кожен запис містить method, description, parameters, http_method, endpoint і
kind (rpc, або file для файлових функцій).
{"jsonrpc":"2.0","method":"capabilities","id":1}Отримання JWT не є методом JSON-RPC: використовуйте POST /{prefix}/{database}/token з обліковими даними HTTP Basic (розділ 6).
Старий метод get_jwt, що приймав пароль у params, видалено; він відповідає 404 / -32601 із вказівкою на новий endpoint.
6. Автентифікація
Кожен запит потребує заголовка Authorization; запит без нього відхиляється з кодом 401 ще до відкриття будь-якого з’єднання з базою даних.
| Заголовок | Що відбувається |
|---|---|
Basic <base64(user:password)> | Пул з’єднань, автентифікований як цей користувач PostgreSQL. Найпростіше; без токенів. Надсилайте лише через HTTPS. |
Bearer <jwt> | Токен із POST /{prefix}/{database}/token (або від вашого провайдера ідентичності). PgArachne перемикається на роль із токена через SET LOCAL ROLE; службовій ролі потрібен GRANT user TO pgarachne. |
Bearer <api token> | Довготривалий токен, створений через pgarachne.add_api_token(...) і прив’язаний до ролі. Добре підходить для сервісів. |
Отримання JWT: POST /{prefix}/{database}/token
Обмінює логін і пароль PostgreSQL, надіслані через автентифікацію HTTP Basic, на JWT. Облікові дані передаються в заголовку Authorization
— ніколи в тілі JSON — а endpoint має власну URL-адресу, тож зворотний проксі може застосовувати суворіші ліміти до входів, не читаючи тіла запитів.
Потребує JWT_SECRET; інакше повертає 404. Кожна спроба враховується в ліміті спроб входу, а відповідь ніколи не кешується.
curl -X POST http://localhost:8080/db/my_database/token -u web_user:password
→ {"token":"eyJhbGciOi...","token_type":"Bearer","expires_in":28800}
curl http://localhost:8080/db/my_database/jsonrpc -H "Authorization: Bearer eyJhbGciOi..." \
-H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"capabilities","id":1}'Невдалі спроби обмежуються лімітом (HTTP 429). Усі подробиці, строки дії токенів і зовнішній провайдер ідентичності описані на сторінці Безпека та автентифікація.
7. Ідемпотентність
Додайте "idempotencyKey": "order-42", щоб виклик можна було безпечно повторити. Перший виклик із ключем виконується як звичайно; повторений ключ відхиляється
до запуску функції з HTTP 409 і -32000 «This request has already been processed». Ключ зберігається в тій самій
транзакції, що й виклик, тож виклик, який завершився помилкою (і був відкочений), можна повторити з тим самим ключем. Ключі розділені за ролями.
- Із автентифікацією JWT або токеном API це працює з коробки.
- З автентифікацією Basic ключ записує сам користувач, тому йому потрібні
USAGEна схемуpgarachneтаINSERTнаpgarachne.requests(інакше виклик завершується помилкою 500Idempotency check failed). - Старі ключі не видаляються автоматично — заплануйте
pgarachne.cleanup_idempotency_keys()(див. Очищення ключів ідемпотентності).
8. Обмеження
- Тіло запиту:
MAX_REQUEST_BYTES(за замовчуванням 2 МіБ), інакше 413. methodтаidempotencyKey: по 256 символів.- Збої автентифікації:
LOGIN_RATE_LIMIT/LOGIN_RATE_LIMIT_PER_IPнаLOGIN_RATE_WINDOW(див. Конфігурація).
9. Виклик
curl -X POST http://localhost:8080/db/my_database/jsonrpc \
-u web_user:password -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"api.find_user","params":{"id":1},"id":1}'З веб-сторінки використовуйте fetch() з тим самим заголовком і тілом; повна сторінка для копіювання та вставлення (разом із SSE і завантаженням файлів) є в розділі
Швидкий старт.