aboutsummaryrefslogblamecommitdiff
path: root/content/go/jsonrpc2.md
blob: 471c4c990dc92984e30375e0add8acf0cd9889df (plain) (tree)

































































































































                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
+++
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"`
}
```