+++ title = "JSON-RPC 2.0" name = "jsonrpc2" repository = "https://git.neonxp.ru/jsonrpc2.git" description = "JSON-RPC 2.0 сервер на генериках" gomod = true +++ Реализация сервера JSON-RPC 2.0 на Go с использованием дженериков. Требуется версия Go 1.18+ Возможности: - [x] Транспорт HTTP/HTTPS - [x] Транспорт TCP - [ ] Транспорт WebSocket ## Использование (транспорт HTTP) 1. Создайте сервер JSON-RPC с параметрами: ```go import "neonxp.ru/go/jsonrpc2/rpc" ... s := rpc.New( rpc.WithTransport(&transport.HTTP{ Bind: ":8000", // Порт для привязки CORSOrigin: "*", // Источник CORS TLS: &tls.Config{}, // Опциональный конфигурационный файл TLS (по умолчанию nil) Parallel: true, // Разрешить параллельное выполнение пакетных методов (по умолчанию false) }), // Другие параметры, такие как транспорты/средства обработки промежуточного ПО... ) ``` 2. Добавьте необходимые транспорты: ```go import "neonxp.ru/go/jsonrpc2/transport" ... s.Use( rpc.WithTransport(&transport.TCP{Bind: ":3000"}), //... ) ``` 3. Напишите обработчики: ```go // Этот обработчик поддерживает параметры запроса func Multiply(ctx context.Context, args *Args) (int, error) { return args.A * args.B, nil } // Этот обработчик не имеет параметров запроса func Hello(ctx context.Context) (string, error) { return "Мир", nil } ``` Обработчик должен иметь контекст в качестве первого параметра и может иметь второй параметр, представляющий параметры запроса (вход любого типа, сериализуемого в JSON). Обработчик всегда возвращает ровно два значения (выход любого типа, сериализуемого в JSON, и ошибку). 4. Оберните обработчик одной из двух функций rpc.H (с поддержкой параметров запроса) или rpc.HS (без параметров) и зарегистрируйте его на сервере: ```go // обработчик с параметрами s.Register("multiply", rpc.H(Multiply)) // обработчик без параметров s.Register("hello", rpc.HS(Hello)) ``` 5. Запустите сервер RPC: ```go s.Run(ctx) ``` ## Пользовательский транспорт Любой транспорт должен реализовывать простой интерфейс transport.Transport: ```go type Transport interface { Run(ctx context.Context, resolver Resolver) error } ``` Полный пример ```go package main import ( "context" "neonxp.ru/go/jsonrpc2/rpc" "neonxp.ru/go/jsonrpc2/rpc/middleware" "neonxp.ru/go/jsonrpc2/transport" ) func main() { s := rpc.New( rpc.WithLogger(rpc.StdLogger), // Опциональный логгер rpc.WithTransport(&transport.HTTP{Bind: ":8000"}), // Транспорт HTTP ) // Установите параметры после конструктора s.Use( rpc.WithTransport(&transport.TCP{Bind: ":3000"}), // Транспорт TCP rpc.WithMiddleware(middleware.Logger(rpc.StdLogger)), // Логгер промежуточного ПО ) s.Register("multiply", rpc.H(Multiply)) s.Register("divide", rpc.H(Divide)) s.Register("hello", rpc.HS(Hello)) s.Run(context.Background()) } func Multiply(ctx context.Context, args *Args) (int, error) { //... } func Divide(ctx context.Context, args *Args) (*Quotient, error) { //... } func Hello(ctx context.Context) (string, error) { // ... } type Args struct { A int `json:"a"` B int `json:"b"` } type Quotient struct { Quo int `json:"quo"` Rem int `json:"rem"` } ```