package jsonrpc import ( "encoding/json" "io" "net/http" "github.com/gorilla/websocket" ) const ( rpcParseError = -32700 rpcMethodNotFound = -32601 rpcInvalidParams = -32602 ) // RPCServer provides a jsonrpc 2.0 http server handler type RPCServer struct { methods handlers } // NewServer creates new RPCServer instance func NewServer() *RPCServer { return &RPCServer{ methods: map[string]rpcHandler{}, } } var upgrader = websocket.Upgrader{} func (s *RPCServer) handleWS(w http.ResponseWriter, r *http.Request) { c, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Error(err) w.WriteHeader(500) return } defer c.Close() handleWsConn(r.Context(), c, s.methods, nil, nil) } // TODO: return errors to clients per spec func (s *RPCServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Connection") == "Upgrade" { s.handleWS(w, r) return } s.methods.handleReader(r.Context(), r.Body, w, s.rpcError) } func (s *RPCServer) rpcError(w io.Writer, req *request, code int, err error) { w.(http.ResponseWriter).WriteHeader(500) if req.ID == nil { // notification return } resp := response{ Jsonrpc: "2.0", ID: *req.ID, Error: &respError{ Code: code, Message: err.Error(), }, } _ = json.NewEncoder(w).Encode(resp) } // Register registers new RPC handler // // Handler is any value with methods defined func (s *RPCServer) Register(namespace string, handler interface{}) { s.methods.register(namespace, handler) } var _ error = &respError{}