JSON-RPC 2.0
Реализация сервера JSON-RPC 2.0 на Go с использованием дженериков.
Требуется версия Go 1.18+
Возможности:
- Транспорт HTTP/HTTPS
- Транспорт TCP
- Транспорт WebSocket
Использование (транспорт HTTP)
- Создайте сервер JSON-RPC с параметрами:
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) }), // Другие параметры, такие как транспорты/средства обработки промежуточного ПО... )
- Добавьте необходимые транспорты:
import "neonxp.ru/go/jsonrpc2/transport" ... s.Use( rpc.WithTransport(&transport.TCP{Bind: ":3000"}), //... )
- Напишите обработчики:
Обработчик должен иметь контекст в качестве первого параметра и может иметь второй параметр, представляющий параметры запроса (вход любого типа, сериализуемого в JSON). Обработчик всегда возвращает ровно два значения (выход любого типа, сериализуемого в JSON, и ошибку).
// Этот обработчик поддерживает параметры запроса func Multiply(ctx context.Context, args *Args) (int, error) { return args.A * args.B, nil } // Этот обработчик не имеет параметров запроса func Hello(ctx context.Context) (string, error) { return "Мир", nil }
- Оберните обработчик одной из двух функций rpc.H (с поддержкой параметров запроса) или rpc.HS (без параметров) и зарегистрируйте его на сервере:
// обработчик с параметрами s.Register("multiply", rpc.H(Multiply)) // обработчик без параметров s.Register("hello", rpc.HS(Hello))
- Запустите сервер RPC:
s.Run(ctx)
Пользовательский транспорт
Любой транспорт должен реализовывать простой интерфейс transport.Transport:
type Transport interface {
Run(ctx context.Context, resolver Resolver) error
}
Полный пример
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"`
}