• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 The Go Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package jsonrpc2
16
17import (
18	"encoding/json"
19	"fmt"
20	"strconv"
21)
22
23// this file contains the go forms of the wire specification
24// see http://www.jsonrpc.org/specification for details
25
26const (
27	// CodeUnknownError should be used for all non coded errors.
28	CodeUnknownError = -32001
29	// CodeParseError is used when invalid JSON was received by the server.
30	CodeParseError = -32700
31	//CodeInvalidRequest is used when the JSON sent is not a valid Request object.
32	CodeInvalidRequest = -32600
33	// CodeMethodNotFound should be returned by the handler when the method does
34	// not exist / is not available.
35	CodeMethodNotFound = -32601
36	// CodeInvalidParams should be returned by the handler when method
37	// parameter(s) were invalid.
38	CodeInvalidParams = -32602
39	// CodeInternalError is not currently returned but defined for completeness.
40	CodeInternalError = -32603
41
42	//CodeServerOverloaded is returned when a message was refused due to a
43	//server being temporarily unable to accept any new messages.
44	CodeServerOverloaded = -32000
45)
46
47// WireRequest is sent to a server to represent a Call or Notify operation.
48type WireRequest struct {
49	// VersionTag is always encoded as the string "2.0"
50	VersionTag VersionTag `json:"jsonrpc"`
51	// Method is a string containing the method name to invoke.
52	Method string `json:"method"`
53	// Params is either a struct or an array with the parameters of the method.
54	Params *json.RawMessage `json:"params,omitempty"`
55	// The id of this request, used to tie the Response back to the request.
56	// Will be either a string or a number. If not set, the Request is a notify,
57	// and no response is possible.
58	ID *ID `json:"id,omitempty"`
59}
60
61// WireResponse is a reply to a Request.
62// It will always have the ID field set to tie it back to a request, and will
63// have either the Result or Error fields set depending on whether it is a
64// success or failure response.
65type WireResponse struct {
66	// VersionTag is always encoded as the string "2.0"
67	VersionTag VersionTag `json:"jsonrpc"`
68	// Result is the response value, and is required on success.
69	Result *json.RawMessage `json:"result,omitempty"`
70	// Error is a structured error response if the call fails.
71	Error *Error `json:"error,omitempty"`
72	// ID must be set and is the identifier of the Request this is a response to.
73	ID *ID `json:"id,omitempty"`
74}
75
76// Error represents a structured error in a Response.
77type Error struct {
78	// Code is an error code indicating the type of failure.
79	Code int64 `json:"code"`
80	// Message is a short description of the error.
81	Message string `json:"message"`
82	// Data is optional structured data containing additional information about the error.
83	Data *json.RawMessage `json:"data"`
84}
85
86// VersionTag is a special 0 sized struct that encodes as the jsonrpc version
87// tag.
88// It will fail during decode if it is not the correct version tag in the
89// stream.
90type VersionTag struct{}
91
92// ID is a Request identifier.
93// Only one of either the Name or Number members will be set, using the
94// number form if the Name is the empty string.
95type ID struct {
96	Name   string
97	Number int64
98}
99
100func (err *Error) Error() string {
101	if err == nil {
102		return ""
103	}
104	return err.Message
105}
106
107func (VersionTag) MarshalJSON() ([]byte, error) {
108	return json.Marshal("2.0")
109}
110
111func (VersionTag) UnmarshalJSON(data []byte) error {
112	version := ""
113	if err := json.Unmarshal(data, &version); err != nil {
114		return err
115	}
116	if version != "2.0" {
117		return fmt.Errorf("Invalid RPC version %v", version)
118	}
119	return nil
120}
121
122// String returns a string representation of the ID.
123// The representation is non ambiguous, string forms are quoted, number forms
124// are preceded by a #
125func (id *ID) String() string {
126	if id == nil {
127		return ""
128	}
129	if id.Name != "" {
130		return strconv.Quote(id.Name)
131	}
132	return "#" + strconv.FormatInt(id.Number, 10)
133}
134
135func (id *ID) MarshalJSON() ([]byte, error) {
136	if id.Name != "" {
137		return json.Marshal(id.Name)
138	}
139	return json.Marshal(id.Number)
140}
141
142func (id *ID) UnmarshalJSON(data []byte) error {
143	*id = ID{}
144	if err := json.Unmarshal(data, &id.Number); err == nil {
145		return nil
146	}
147	return json.Unmarshal(data, &id.Name)
148}
149