good morning!!!!

Skip to content
Snippets Groups Projects
router_response.go 2.35 KiB
Newer Older
a's avatar
a committed
package jrpc

import (
	"encoding/json"
	"errors"
	"net/http"
)

a's avatar
a committed
type Response struct {
	Version version         `json:"jsonrpc,omitempty"`
a's avatar
a committed
	ID      *ID             `json:"id,omitempty"`
a's avatar
a committed
	Result  json.RawMessage `json:"result,omitempty"`
	Error   *jsonError      `json:"error,omitempty"`
}

func (r *Response) Msg() *jsonrpcMessage {
a's avatar
a committed
	out := &jsonrpcMessage{}
	if r.ID != nil {
		out.ID = r.ID
a's avatar
a committed
	}
	if r.Error != nil {
		out.Error = r.Error
		return out
	}
	out.Result = r.Result
	return out
}
a's avatar
a committed

a's avatar
a committed
type ResponseWriterMsg struct {
	r    *Request
	resp *Response
	n    *Notifier
	s    *Subscription
a's avatar
a committed

	//TODO: add options
	// currently there are no useful options so i havent added any
	// find a use case to add
	options options
}

type options struct {
}

func UpgradeToSubscription(w ResponseWriter, r *Request) (*Subscription, error) {
	not, ok := NotifierFromContext(r.ctx)
	if !ok || not == nil {
		return nil, errors.New("subscription not supported")
	}
	return not.CreateSubscription(), nil
}

func NewReaderResponseWriterMsg(r *Request) *ResponseWriterMsg {
	rw := &ResponseWriterMsg{
		r: r,
a's avatar
a committed
		resp: &Response{
			ID: r.ID,
		},
a's avatar
a committed
	}
	rw.n, _ = NotifierFromContext(r.ctx)
	return rw
}

func (w *ResponseWriterMsg) Header() http.Header {
a's avatar
a committed
	wh := w.r.Peer.HTTP.WriteHeaders
a's avatar
a committed
	if wh == nil {
		wh = http.Header{}
	}
a's avatar
a committed
	return wh
}

func (w *ResponseWriterMsg) Option(k string, v any) {
}

func (w *ResponseWriterMsg) Send(args any, e error) (err error) {
	if e != nil {
a's avatar
a committed
		if c, ok := e.(*jsonError); ok {
			w.resp.Error = c
		} else {
			w.resp.Error = &jsonError{
				Code:    applicationErrorCode,
				Message: e.Error(),
			}
		}
		ec, ok := e.(Error)
		if ok {
			w.resp.Error.Code = ec.ErrorCode()
		}
		de, ok := e.(DataError)
		if ok {
			w.resp.Error.Data = de.ErrorData()
		}
a's avatar
a committed
		return nil
	}
	switch c := args.(type) {
	case *Subscription:
		w.s = c
	default:
	}
a's avatar
a committed
	w.resp.Result, err = jzon.Marshal(args)
	if err != nil {
		w.resp.Error = &jsonError{
			Code:    -32603,
			Message: err.Error(),
		}
		return nil
	}
a's avatar
a committed
	return nil
}

func (w *ResponseWriterMsg) Notify(args any) (err error) {
	if w.s == nil || w.n == nil {
		return ErrSubscriptionNotFound
	}
	bts, _ := json.Marshal(args)
	err = w.n.send(w.s, bts)
	if err != nil {
		return err
	}
	return nil
}

a's avatar
a committed
func (w *ResponseWriterMsg) Response() *Response {
	return w.resp
}
func (w *ResponseWriterMsg) Msg() *jsonrpcMessage {
	return w.resp.Msg()
a's avatar
a committed
}