JSON-RPC
JSON-RPC
POST /{prefix}/{database}/jsonrpc wywołuje funkcję PostgreSQL i zwraca jej wynik jako odpowiedź
JSON-RPC 2.0. Ta strona jest opisem referencyjnym;
pierwszy działający przykład znajdziesz w Szybkim starcie.
1. Żądanie
POST /db/my_database/jsonrpc
Authorization: Basic ... (lub Bearer <jwt / api token>)
Content-Type: application/json
{"jsonrpc": "2.0", "method": "api.hello_world", "params": {"name": "Alice"}, "id": 1}| Pole | Opis |
|---|---|
method | Wymagane. schema.function, najwyżej 256 znaków. Dozwolone są identyfikatory w cudzysłowie ("my schema"."my fn"). Schemat jest obowiązkowy: samo hello_world jest odrzucane kodem 400. capabilities to metoda wbudowana (sekcja 5). |
params | Dowolna wartość JSON, przekazywana funkcji bez zmian jako jej argument jsonb. Brak lub null staje się {}. Konwencją są obiekty; tablice i wartości skalarne również działają. |
id | Dowolna wartość JSON; jest kopiowana do odpowiedzi. Jeśli jej brak, odpowiedź zawiera "id": null (nie ma powiadomień typu fire-and-forget). |
jsonrpc | Zwykle "2.0"; nie jest walidowane na wejściu, odpowiedź zawsze niesie "2.0". |
idempotencyKey | Opcjonalne rozszerzenie (sekcja 7). Najwyżej 256 znaków. |
Żądania wsadowe (tablica JSON z wywołaniami) nie są obsługiwane i zwracają 400 — wysyłaj jedno wywołanie na żądanie HTTP.
2. Odpowiedź
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}W odróżnieniu od zwykłego JSON-RPC przez gniazdo, błędy ustawiają także sensowny status HTTP, więc klienci i proxy mogą reagować
bez parsowania treści. error.code wynosi 0, chyba że ma zastosowanie konkretny kod JSON-RPC
(-32601 nieznana funkcja, -32001 brak uprawnień, -32000 zduplikowane żądanie).
Pełną listę znajdziesz na stronie Kody błędów.
3. Pisanie funkcji
Metoda to funkcja PostgreSQL przyjmująca dokładnie jeden argument typu jsonb
i zwracająca json lub jsonb. Funkcje o innych sygnaturach nie są wymieniane przez
capabilities ani nie da się ich wywołać.
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;- Wartość zwracana. Wynik JSON jest wysyłany jako
result. SQL-oweNULL(jak wyżej, gdy żaden wiersz nie pasuje) staje się"result": null. Funkcja musi zwracać poprawny JSON: zwracany typtextkończy się błędem 500, chyba że tekst akurat jest JSON-em — dla wyniku w postaci napisu użyjto_json('hi'::text). - Błędy wewnątrz funkcji.
RAISE EXCEPTIONlub dowolny błąd SQL przerywa wywołanie kodem HTTP 500 i ogólnym komunikatemFunction call failed; prawdziwy komunikat PostgreSQL trafia tylko do logu serwera, więc szczegóły schematu nie wyciekają. Oczekiwane błędy biznesowe (nie znaleziono, walidacja) zgłaszaj raczej w wartości zwracanej, na przykład{"ok": false, "reason": "..."}. - Transakcje. Każde wywołanie działa w jednej transakcji, zatwierdzanej, gdy funkcja zwróci wynik, i wycofywanej przy każdym błędzie.
- Uprawnienia. Wywołanie działa jako uwierzytelniona rola PostgreSQL, więc
GRANT,REVOKEi Row-Level Security decydują, co wolno wywołującemu. Rola potrzebujeUSAGEna schemacie iEXECUTEna funkcji. PostgreSQL domyślnie nadajeEXECUTEna nowych funkcjach wszystkim, więc cofnij to (ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC) i trzymaj udostępniane funkcje w dedykowanym schemacie — zobacz Bezpieczeństwo i uwierzytelnianie.
4. Opisywanie funkcji dla klientów i agentów AI
Pierwsza linia komentarza funkcji jest jej opisem; obiekt JSON po --- PARAMS --- opisuje parametry
(properties w JSON Schema). Oba pojawiają się w capabilities, w specyfikacji OpenAPI i w MCP tools/list:
COMMENT ON FUNCTION api.find_user(jsonb) IS 'Looks up a user by id.
--- PARAMS ---
{"id": {"type": "integer", "description": "User id"}}';Komentarz z błędnym JSON-em po znaczniku jest ignorowany (funkcja wraca do ogólnego opisu parametrów) i nigdy nie psuje wykrywania.
5. Wbudowane metody
capabilities
Wyświetla funkcje, które uwierzytelniona rola może wywołać (EXECUTE i USAGE na schemacie); schematy systemowe i funkcje rozszerzeń są ukryte.
Każdy wpis ma method, description, parameters, http_method, endpoint oraz
kind (rpc lub file dla funkcji plikowych).
{"jsonrpc":"2.0","method":"capabilities","id":1}Logowanie po JWT nie jest metodą JSON-RPC: użyj POST /{prefix}/{database}/token z danymi HTTP Basic (sekcja 6).
Dawna metoda get_jwt, która przyjmowała hasło w params, została usunięta i odpowiada 404 / -32601 ze wskazaniem nowego endpointu.
6. Uwierzytelnianie
Każde żądanie wymaga nagłówka Authorization; żądanie bez niego jest odrzucane kodem 401, zanim zostanie otwarte jakiekolwiek połączenie z bazą danych.
| Nagłówek | Co się dzieje |
|---|---|
Basic <base64(user:password)> | Pula połączeń uwierzytelniona jako ten użytkownik PostgreSQL. Najprostsze; bez tokenów. Wysyłaj tylko przez HTTPS. |
Bearer <jwt> | Token z POST /{prefix}/{database}/token (lub z własnego dostawcy tożsamości). PgArachne przełącza się na rolę z tokenu przez SET LOCAL ROLE; rola serwisowa potrzebuje GRANT user TO pgarachne. |
Bearer <api token> | Długotrwały token utworzony przez pgarachne.add_api_token(...), powiązany z rolą. Dobry dla usług. |
Pobieranie JWT: POST /{prefix}/{database}/token
Wymienia login i hasło PostgreSQL, wysłane przez uwierzytelnianie HTTP Basic, na JWT. Dane logowania podróżują w nagłówku Authorization
— nigdy w treści JSON — a endpoint ma własny adres URL, więc reverse proxy może stosować surowsze limity dla logowań bez odczytywania treści żądań.
Wymaga JWT_SECRET; w przeciwnym razie zwraca 404. Każda próba wlicza się do limitu prób logowania, a odpowiedź nigdy nie może być cache’owana.
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}'Nieudane próby są ograniczane limitem (HTTP 429). Wszystkie szczegóły, czasy życia tokenów i zewnętrzny dostawca tożsamości są na stronie Bezpieczeństwo i uwierzytelnianie.
7. Idempotencja
Dodaj "idempotencyKey": "order-42", aby wywołanie można było bezpiecznie ponowić. Pierwsze wywołanie z danym kluczem wykonuje się normalnie; powtórzony klucz jest odrzucany
przed uruchomieniem funkcji kodem HTTP 409 i -32000 „This request has already been processed". Klucz jest zapisywany w tej samej
transakcji co wywołanie, więc wywołanie, które się nie powiodło (i zostało wycofane), można ponowić z tym samym kluczem. Klucze są rozdzielone per rola.
- Przy uwierzytelnianiu JWT lub tokenem API działa to od razu.
- Przy uwierzytelnianiu Basic klucz zapisuje sam użytkownik, więc potrzebuje
USAGEna schemaciepgarachneorazINSERTnapgarachne.requests(w przeciwnym razie wywołanie kończy się błędem 500Idempotency check failed). - Stare klucze nie są usuwane automatycznie — zaplanuj
pgarachne.cleanup_idempotency_keys()(zobacz Czyszczenie kluczy idempotencji).
8. Limity
- Treść żądania:
MAX_REQUEST_BYTES(domyślnie 2 MiB), w przeciwnym razie 413. methodiidempotencyKey: po 256 znaków.- Niepowodzenia uwierzytelniania:
LOGIN_RATE_LIMIT/LOGIN_RATE_LIMIT_PER_IPnaLOGIN_RATE_WINDOW(zobacz Konfiguracja).
9. Wywołanie
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}'Ze strony internetowej użyj fetch() z tym samym nagłówkiem i treścią; kompletna strona do skopiowania i wklejenia (wraz z SSE i pobieraniem plików) jest w
Szybkim starcie.