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