JSON-RPC

5 min čtení

JSON-RPC

POST /{prefix}/{database}/jsonrpc zavolá funkci PostgreSQL a vrátí její výsledek jako odpověď JSON-RPC 2.0. Tato stránka je referenční; první funkční příklad najdete v Rychlém startu.

1. Požadavek

POST /db/my_database/jsonrpc
Authorization: Basic ...            (or Bearer <jwt / api token>)
Content-Type: application/json

{"jsonrpc": "2.0", "method": "api.hello_world", "params": {"name": "Alice"}, "id": 1}
PolePopis
methodPovinné. schema.function, nejvýše 256 znaků. Povoleny jsou i uvozené identifikátory ("my schema"."my fn"). Schéma je povinné: samotné hello_world je zamítnuto s kódem 400. capabilities je vestavěná metoda (sekce 5).
paramsLibovolná hodnota JSON, která se funkci předá beze změny jako její argument jsonb. Chybějící hodnota nebo null se změní na {}. Zvykem jsou objekty; fungují i pole a skalární hodnoty.
idLibovolná hodnota JSON; zkopíruje se do odpovědi. Pokud chybí, odpověď obsahuje "id": null (neexistují notifikace typu „vyšli a zapomeň“).
jsonrpcObvykle "2.0"; na vstupu se nevaliduje, odpověď vždy obsahuje "2.0".
idempotencyKeyVolitelné rozšíření (sekce 7). Nejvýše 256 znaků.

Dávkové požadavky (pole volání v JSON) nejsou podporovány a vrací 400 — posílejte jedno volání na jeden HTTP požadavek.

2. Odpověď

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}

Na rozdíl od běžného JSON-RPC přes socket nastavují chyby také smysluplný HTTP stavový kód, takže klienti a proxy mohou reagovat bez parsování těla. Hodnota error.code je 0, pokud se neuplatňuje konkrétní kód JSON-RPC (-32601 neznámá funkce, -32001 přístup odepřen, -32000 duplicitní požadavek). Úplný seznam je na stránce Chybové kódy.

3. Psaní funkce

Metoda je funkce PostgreSQL, která přijímá přesně jeden argument typu jsonb a vrací json nebo jsonb. Funkce s jinou signaturou capabilities nevypisuje a nelze je zavolat.

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;
  • Návratová hodnota. Výsledek JSON se odešle jako result. SQL NULL (jako výše, když nevyhovuje žádný řádek) se změní na "result": null. Funkce musí vracet platný JSON: návratový typ text skončí chybou 500, pokud text shodou okolností není JSON — pro řetězcový výsledek použijte to_json('hi'::text).
  • Chyby uvnitř funkce. RAISE EXCEPTION nebo jakákoli chyba SQL přeruší volání s HTTP 500 a obecnou zprávou Function call failed; skutečná zpráva PostgreSQL se zapíše jen do logu serveru, takže detaily schématu nikam neunikají. Očekávané obchodní chyby (nenalezeno, validace) hlaste raději v návratové hodnotě, například {"ok": false, "reason": "..."}.
  • Transakce. Každé volání běží v jedné transakci, která se při návratu funkce potvrdí a při jakékoli chybě vrátí zpět.
  • Oprávnění. Volání běží jako autentizovaná role PostgreSQL, takže o tom, co volající smí, rozhodují GRANT, REVOKE a Row-Level Security. Role potřebuje USAGE na schématu a EXECUTE na funkci. PostgreSQL ve výchozím stavu uděluje EXECUTE na nové funkce všem, proto toto oprávnění odeberte (ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC) a vystavené funkce držte ve vyhrazeném schématu — viz Bezpečnost a autentizace.

4. Popis funkce pro klienty a AI agenty

První řádek komentáře funkce je její popis; objekt JSON za --- PARAMS --- popisuje parametry (properties podle JSON Schema). Obojí se objeví v capabilities, ve specifikaci OpenAPI a v MCP tools/list:

COMMENT ON FUNCTION api.find_user(jsonb) IS 'Looks up a user by id.
--- PARAMS ---
{"id": {"type": "integer", "description": "User id"}}';

Komentář s chybným JSON za značkou se ignoruje (funkce se vrátí k obecnému popisu parametrů) a nikdy nenaruší vyhledávání funkcí.

5. Vestavěné metody

capabilities

Vypíše funkce, které autentizovaná role smí volat (EXECUTE a USAGE na schématu); systémová schémata a funkce rozšíření jsou skryté. Každá položka obsahuje method, description, parameters, http_method, endpoint a kind (rpc, nebo file pro souborové funkce).

{"jsonrpc":"2.0","method":"capabilities","id":1}

Přihlášení pro získání JWT není metoda JSON-RPC: použijte POST /{prefix}/{database}/token s přihlašovacími údaji HTTP Basic (sekce 6). Původní metoda get_jwt, která přijímala heslo v params, byla odstraněna a odpovídá 404 / -32601 s odkazem na nový endpoint.

6. Autentizace

Každý požadavek potřebuje hlavičku Authorization; požadavek bez ní je zamítnut s 401 dříve, než se otevře jakékoli připojení k databázi.

HlavičkaCo se stane
Basic <base64(user:password)>Pool připojení autentizovaný jako daný uživatel PostgreSQL. Nejjednodušší; žádné tokeny. Posílejte jen přes HTTPS.
Bearer <jwt>Token z POST /{prefix}/{database}/token (nebo od vašeho poskytovatele identity). PgArachne přepne na roli z tokenu pomocí SET LOCAL ROLE; servisní role potřebuje GRANT user TO pgarachne.
Bearer <api token>Dlouhodobý token vytvořený přes pgarachne.add_api_token(...), svázaný s rolí. Vhodný pro služby.

Získání JWT: POST /{prefix}/{database}/token

Vymění přihlašovací jméno a heslo PostgreSQL, odeslané pomocí HTTP Basic autentizace, za JWT. Přihlašovací údaje putují v hlavičce Authorization — nikdy v těle JSON — a endpoint má vlastní URL, takže reverzní proxy může na přihlášení uplatnit přísnější limity, aniž by četla těla požadavků. Vyžaduje JWT_SECRET; jinak vrací 404. Každý pokus se počítá do limitu přihlášení a odpověď nelze nikdy cachovat.

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}'

Neúspěšné pokusy jsou omezovány (HTTP 429). Všechny podrobnosti, platnost tokenů a externí poskytovatel identity jsou na stránce Bezpečnost a autentizace.

7. Idempotence

Přidejte "idempotencyKey": "order-42", aby bylo volání bezpečné opakovat. První volání s daným klíčem proběhne normálně; opakovaný klíč je zamítnut před spuštěním funkce s HTTP 409 a -32000 „This request has already been processed“. Klíč se ukládá ve stejné transakci jako volání, takže volání, které selhalo (a bylo vráceno zpět), lze zopakovat se stejným klíčem. Klíče jsou odděleny podle rolí.

  • S autentizací JWT nebo API tokenem to funguje bez další konfigurace.
  • S autentizací Basic klíč zapisuje samotný uživatel, takže potřebuje USAGE na schématu pgarachne a INSERT na pgarachne.requests (jinak volání skončí chybou 500 Idempotency check failed).
  • Staré klíče se automaticky neodstraňují — naplánujte pgarachne.cleanup_idempotency_keys() (viz Údržba idempotency klíčů).

8. Limity

  • Tělo požadavku: MAX_REQUEST_BYTES (výchozí 2 MiB), jinak 413.
  • method a idempotencyKey: každé 256 znaků.
  • Selhání autentizace: LOGIN_RATE_LIMIT / LOGIN_RATE_LIMIT_PER_IP na LOGIN_RATE_WINDOW (viz Konfigurace).

9. Volání

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}'

Z webové stránky použijte fetch() se stejnou hlavičkou a tělem; kompletní stránku pro zkopírování (včetně SSE a stahování souborů) najdete v Rychlém startu.