good morning!!!!

Skip to content
Snippets Groups Projects
router_request.go 2.9 KiB
Newer Older
a's avatar
rpc
a committed
package jrpc

import (
	"context"
a's avatar
a committed
	"strings"
a's avatar
ok  
a committed

	json "github.com/goccy/go-json"
a's avatar
ok  
a committed
	jsoniter "github.com/json-iterator/go"
a's avatar
rpc
a committed
)

type Request struct {
a's avatar
a committed
	Version version         `json:"jsonrpc"`
	ID      *ID             `json:"id,omitempty"`
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params"`
a's avatar
a committed

	Peer PeerInfo `json:"-"`

a's avatar
rpc
a committed
	ctx context.Context
a's avatar
a committed
}
a's avatar
a committed
func NewMsgRequest(ctx context.Context, peer PeerInfo, msg jsonrpcMessage) *Request {
	r := &Request{ctx: ctx}
	r.ID = msg.ID
	r.Method = msg.Method
	r.Params = msg.Params
	r.Peer = peer
	r.ctx = ctx
	return r
a's avatar
rpc
a committed
}

a's avatar
a committed
func NewRequest(ctx context.Context, id string, method string, params any) *Request {
	r := &Request{ctx: ctx}
	pms, _ := json.Marshal(params)
a's avatar
a committed
	r.ID = NewStringIDPtr(id)
	r.Method = method
	r.Params = pms
a's avatar
a committed
	return r
}

func (r *Request) ParamSlice() []any {
	var params []any
a's avatar
a committed
	json.Unmarshal(r.Params, &params)
	return params
}

a's avatar
a committed
func (r *Request) makeError(err error) *jsonrpcMessage {
	m := r.Msg()
	return m.errorResponse(err)
}

// DEPRECATED
// TODO: use our router to do this? jrpc.Namespace(string) (string, string) maybe?
func (r *Request) namespace() string {
	elem := strings.SplitN(r.Method, serviceMethodSeparator, 2)
	return elem[0]
}
a's avatar
a committed
func (r *Request) errorResponse(err error) *Response {
	mw := NewReaderResponseWriterMsg(r)
	mw.Send(nil, err)
	return mw.Response()
}
a's avatar
a committed

func (r *Request) isSubscribe() bool {
	return strings.HasSuffix(r.Method, subscribeMethodSuffix)
}
func (r *Request) isUnsubscribe() bool {
	return strings.HasSuffix(r.Method, unsubscribeMethodSuffix)
}
func (r *Request) isNotification() bool {
	return r.ID == nil && len(r.Method) > 0
}
func (r *Request) isCall() bool {
	return r.hasValidID() && len(r.Method) > 0
}
func (r *Request) isResponse() bool {
	return false
}
func (r *Request) hasValidID() bool {
	return r.ID != nil && !r.ID.null
}

a's avatar
a committed
func (r *Request) ParamArray(a ...any) error {
	var params []json.RawMessage
a's avatar
a committed
	json.Unmarshal(r.Params, &params)
a's avatar
a committed
	for idx, v := range params {
		if len(v) > idx {
			err := json.Unmarshal(v, &a[idx])
a's avatar
a committed
			if err != nil {
				return err
			}
		} else {
			break
		}
	}
	return nil
}

func (r *Request) ParamInto(v any) error {
a's avatar
a committed
	return json.Unmarshal(r.Params, &v)
a's avatar
rpc
a committed
func (r *Request) Context() context.Context {
	return r.ctx
}

a's avatar
a committed
func (r *Request) Msg() jsonrpcMessage {
	return jsonrpcMessage{
		ID:     r.ID,
		Method: r.Method,
		Params: r.Params,
	}
a's avatar
a committed
func (r *Request) Remote() string {
	return r.Peer.RemoteAddr
a's avatar
rpc
a committed
func (r *Request) WithContext(ctx context.Context) *Request {
	if ctx == nil {
		panic("nil context")
	}
	r.ctx = ctx
	r2 := new(Request)
	*r2 = *r
	r2.ctx = ctx
a's avatar
a committed
	r2.ID = r.ID
	r2.Method = r.Method
	r2.Params = r.Params
	r2.Peer = r.Peer
a's avatar
rpc
a committed
	return r2
}
a's avatar
a committed
var jpool = jsoniter.NewIterator(jsoniter.ConfigCompatibleWithStandardLibrary).Pool()
a's avatar
a committed

a's avatar
a committed
func (r *Request) Iter(fn func(j *jsoniter.Iterator) error) error {
a's avatar
a committed
	it := jpool.BorrowIterator(r.Params)
a's avatar
a committed
	defer jpool.ReturnIterator(it)
	return fn(it)
a's avatar
a committed
}