Реализация сервера JSON-RPC 2.0 на Go с использованием дженериков.
Требуется версия Go 1.18+ Возможности:
- 🗹 Транспорт HTTP/HTTPS
- 🗹 Транспорт TCP
- ☐ Транспорт WebSocket
Использование (транспорт HTTP)
-
Создайте сервер JSON-RPC с параметрами:
1import "neonxp.ru/go/jsonrpc2/rpc" 2... 3s := rpc.New( 4 rpc.WithTransport(&transport.HTTP{ 5 Bind: ":8000", // Порт для привязки 6 CORSOrigin: "*", // Источник CORS 7 TLS: &tls.Config{}, // Опциональный конфигурационный файл TLS (по умолчанию nil) 8 Parallel: true, // Разрешить параллельное выполнение пакетных методов (по умолчанию false) 9 }), 10 // Другие параметры, такие как транспорты/средства обработки промежуточного ПО... 11)
-
Добавьте необходимые транспорты:
1import "neonxp.ru/go/jsonrpc2/transport" 2... 3s.Use( 4 rpc.WithTransport(&transport.TCP{Bind: ":3000"}), 5 //... 6)
-
Напишите обработчики:
1// Этот обработчик поддерживает параметры запроса 2func Multiply(ctx context.Context, args *Args) (int, error) { 3 return args.A * args.B, nil 4} 5 6// Этот обработчик не имеет параметров запроса 7func Hello(ctx context.Context) (string, error) { 8 return "Мир", nil 9}
Обработчик должен иметь контекст в качестве первого параметра и может иметь второй параметр, представляющий параметры запроса (вход любого типа, сериализуемого в JSON). Обработчик всегда возвращает ровно два значения (выход любого типа, сериализуемого в JSON, и ошибку).
-
Оберните обработчик одной из двух функций rpc.H (с поддержкой параметров запроса) или rpc.HS (без параметров) и зарегистрируйте его на сервере:
1// обработчик с параметрами 2s.Register("multiply", rpc.H(Multiply)) 3 4// обработчик без параметров 5s.Register("hello", rpc.HS(Hello))
-
Запустите сервер RPC:
1s.Run(ctx)
Пользовательский транспорт
Любой транспорт должен реализовывать простой интерфейс transport.Transport:
1type Transport interface {
2 Run(ctx context.Context, resolver Resolver) error
3}
Полный пример
1package main
2
3import (
4 "context"
5
6 "neonxp.ru/go/jsonrpc2/rpc"
7 "neonxp.ru/go/jsonrpc2/rpc/middleware"
8 "neonxp.ru/go/jsonrpc2/transport"
9)
10
11func main() {
12 s := rpc.New(
13 rpc.WithLogger(rpc.StdLogger), // Опциональный логгер
14 rpc.WithTransport(&transport.HTTP{Bind: ":8000"}), // Транспорт HTTP
15 )
16
17 // Установите параметры после конструктора
18 s.Use(
19 rpc.WithTransport(&transport.TCP{Bind: ":3000"}), // Транспорт TCP
20 rpc.WithMiddleware(middleware.Logger(rpc.StdLogger)), // Логгер промежуточного ПО
21 )
22
23 s.Register("multiply", rpc.H(Multiply))
24 s.Register("divide", rpc.H(Divide))
25 s.Register("hello", rpc.HS(Hello))
26
27 s.Run(context.Background())
28}
29
30func Multiply(ctx context.Context, args *Args) (int, error) {
31 //...
32}
33
34func Divide(ctx context.Context, args *Args) (*Quotient, error) {
35 //...
36}
37
38func Hello(ctx context.Context) (string, error) {
39 // ...
40}
41
42type Args struct {
43 A int `json:"a"`
44 B int `json:"b"`
45}
46
47type Quotient struct {
48 Quo int `json:"quo"`
49 Rem int `json:"rem"`
50}