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 πάνω από socket, τα σφάλματα ορίζουν επίσης ουσιαστικό κωδικό HTTP, ώστε πελάτες και proxies να αντιδρούν
χωρίς να αναλύουν το σώμα. Το 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. Ένα SQLNULL(όπως παραπάνω, όταν καμία γραμμή δεν ταιριάζει) γίνεται"result": null. Η συνάρτηση πρέπει να επιστρέφει έγκυρο JSON: ένας τύπος επιστροφήςtextαποτυγχάνει με 500 εκτός αν το κείμενο τυχαίνει να είναι JSON — χρησιμοποιήστεto_json('hi'::text)για αποτέλεσμα συμβολοσειράς. - Σφάλματα μέσα στη συνάρτηση. Το
RAISE EXCEPTIONή οποιοδήποτε σφάλμα SQL διακόπτει την κλήση με HTTP 500 και το γενικό μήνυμαFunction call failed· το πραγματικό μήνυμα της PostgreSQL γράφεται μόνο στο αρχείο καταγραφής του διακομιστή, ώστε να μη διαρρέουν λεπτομέρειες του σχήματος. Αναφέρετε τα αναμενόμενα επιχειρησιακά σφάλματα (δεν βρέθηκε, επικύρωση) μάλλον στην τιμή επιστροφής, για παράδειγμα{"ok": false, "reason": "..."}. - Συναλλαγές. Κάθε κλήση εκτελείται σε μία συναλλαγή που επικυρώνεται (commit) όταν η συνάρτηση επιστρέψει και ακυρώνεται (rollback) σε οποιοδήποτε σφάλμα.
- Δικαιώματα. Η κλήση εκτελείται ως ο πιστοποιημένος ρόλος PostgreSQL, επομένως τα
GRANT,REVOKEκαι το Row-Level Security καθορίζουν τι μπορεί να κάνει ο καλών. Ένας ρόλος χρειάζεταιUSAGEστο σχήμα καιEXECUTEστη συνάρτηση. Η PostgreSQL δίνει από προεπιλογήEXECUTEστις νέες συναρτήσεις σε όλους, γι’ αυτό ανακαλέστε το (ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC) και κρατήστε τις εκτεθειμένες συναρτήσεις σε ξεχωριστό σχήμα — δείτε Ασφάλεια & Πιστοποίηση.
4. Περιγραφή μιας συνάρτησης για πελάτες και πράκτορες AI
Η πρώτη γραμμή του σχολίου της συνάρτησης είναι η περιγραφή της· ένα αντικείμενο 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. Το απλούστερο· χωρίς tokens. Στείλτε το μόνο μέσω HTTPS. |
Bearer <jwt> | Token από το POST /{prefix}/{database}/token (ή από τον δικό σας πάροχο ταυτότητας). Το PgArachne αλλάζει στον ρόλο του token με SET LOCAL ROLE· ο ρόλος υπηρεσίας χρειάζεται GRANT user TO pgarachne. |
Bearer <api token> | Μακράς διάρκειας token που δημιουργείται με pgarachne.add_api_token(...), δεμένο σε έναν ρόλο. Κατάλληλο για υπηρεσίες. |
Λήψη JWT: POST /{prefix}/{database}/token
Ανταλλάσσει ένα login και κωδικό PostgreSQL, που στέλνονται με πιστοποίηση HTTP Basic, με ένα JWT. Τα διαπιστευτήρια ταξιδεύουν στην κεφαλίδα Authorization
— ποτέ σε σώμα JSON — και το endpoint έχει δικό του URL, ώστε ένας reverse proxy να μπορεί να εφαρμόζει αυστηρότερα όρια στις συνδέσεις χωρίς να διαβάζει τα σώματα των αιτημάτων.
Απαιτεί 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). Όλες οι λεπτομέρειες, η διάρκεια ζωής των tokens και ένας εξωτερικός πάροχος ταυτότητας βρίσκονται στη σελίδα Ασφάλεια & Πιστοποίηση.
7. Ιδεμποτεντία
Προσθέστε "idempotencyKey": "order-42" για να μπορεί μια κλήση να επαναληφθεί με ασφάλεια. Η πρώτη κλήση με ένα κλειδί εκτελείται κανονικά· ένα επαναλαμβανόμενο κλειδί απορρίπτεται
πριν εκτελεστεί η συνάρτηση με HTTP 409 και -32000 «This request has already been processed». Το κλειδί αποθηκεύεται στην ίδια
συναλλαγή με την κλήση, οπότε μια κλήση που απέτυχε (και ακυρώθηκε) μπορεί να επαναληφθεί με το ίδιο κλειδί. Τα κλειδιά ανήκουν ανά ρόλο.
- Με πιστοποίηση JWT ή token API λειτουργεί αμέσως.
- Με πιστοποίηση Basic το κλειδί το γράφει ο ίδιος ο χρήστης, άρα χρειάζεται
USAGEστο σχήμαpgarachneκαιINSERTστοpgarachne.requests(διαφορετικά η κλήση αποτυγχάνει με 500Idempotency check failed). - Τα παλιά κλειδιά δεν αφαιρούνται αυτόματα — προγραμματίστε το
pgarachne.cleanup_idempotency_keys()(δείτε Εκκαθάριση Κλειδιών Ιδεμποτεντίας).
8. Όρια
- Σώμα αιτήματος:
MAX_REQUEST_BYTES(προεπιλογή 2 MiB), διαφορετικά 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 και της λήψης αρχείων) υπάρχει στη
Γρήγορη εκκίνηση.