1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
+++
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"`
}
```
|