validate.go raw

   1  // Copyright 2018 Adam S Levy
   2  //
   3  // Permission is hereby granted, free of charge, to any person obtaining a copy
   4  // of this software and associated documentation files (the "Software"), to
   5  // deal in the Software without restriction, including without limitation the
   6  // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   7  // sell copies of the Software, and to permit persons to whom the Software is
   8  // furnished to do so, subject to the following conditions:
   9  //
  10  // The above copyright notice and this permission notice shall be included in
  11  // all copies or substantial portions of the Software.
  12  //
  13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18  // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19  // IN THE SOFTWARE.
  20  
  21  package jsonrpc2
  22  
  23  import (
  24  	"encoding/json"
  25  	"fmt"
  26  )
  27  
  28  // validateID assumes that id is valid JSON and returns true if len(id) == 0,
  29  // or id represents a JSON Number, String or Null.
  30  //
  31  // From the JSONRPC 2.0 Spec:
  32  //
  33  // id
  34  //      An identifier established by the Client that MUST contain a String,
  35  //      Number, or NULL value if included.
  36  //
  37  // Below is the JSON grammar for String, Number and Null from JSON.org.
  38  //      value
  39  //          string
  40  //          number
  41  //          "null"
  42  //
  43  //      string
  44  //          '"' characters '"'
  45  //
  46  //      number
  47  //          integer fraction exponent
  48  //
  49  //      integer
  50  //          digit
  51  //          onenine digits
  52  //          '-' digit
  53  //          '-' onenine digits
  54  //
  55  //      digits
  56  //          digit
  57  //          digit digits
  58  //
  59  //      digit
  60  //          '0'
  61  //          onenine
  62  //
  63  //      onenine
  64  //          '1' . '9'
  65  //
  66  //      fraction
  67  //          ""
  68  //          '.' digits
  69  //
  70  //      exponent
  71  //          ""
  72  //          'E' sign digits
  73  //          'e' sign digits
  74  //
  75  // Thus if we know that we are working with valid JSON, we can determine the
  76  // JSON type by the first byte alone.
  77  func validateID(id json.RawMessage) error {
  78  	if len(id) == 0 {
  79  		return fmt.Errorf(`invalid "id": empty`)
  80  	}
  81  	b := id[0]
  82  	if b == 'n' || // null
  83  		b == '"' || // string
  84  		isNumber(b) {
  85  		return nil
  86  	}
  87  	return fmt.Errorf(`invalid "id": not a number, string, or null`)
  88  }
  89  
  90  func isNumber(b byte) bool {
  91  	if b == '-' || ('0' <= b && b <= '9') || // integer
  92  		b == 'E' || b == 'e' || // exponent
  93  		b == '.' { // fraction
  94  		return true
  95  	}
  96  	return false
  97  }
  98  
  99  // validateParams assumes that params is valid JSON and returns true if params is
 100  // nil, or if it represents a structured value (Array or Object), or Null.
 101  //
 102  // From the JSONRPC 2.0 Spec:
 103  //
 104  // params
 105  //      A Structured value that holds the parameter values to be used during
 106  //      the invocation of the method. This member MAY be omitted.
 107  //
 108  // Below is the JSON grammar for Object, Array and Null from JSON.org.
 109  //      value
 110  //          object
 111  //          array
 112  //          "null"
 113  //
 114  //      object
 115  //          '{' ws '}'
 116  //          '{' members '}'
 117  //
 118  //      array
 119  //          '[' ws ']'
 120  //          '[' elements ']'
 121  //
 122  // Thus if we know that we are working with valid JSON, we can determine the
 123  // JSON type by the first byte alone.
 124  func validateParams(params json.RawMessage) error {
 125  	if len(params) == 0 {
 126  		return fmt.Errorf(`invalid "params": empty`)
 127  	}
 128  	b := params[0]
 129  	if b == 'n' || // null
 130  		b == '[' || // array
 131  		b == '{' { // object
 132  		return nil
 133  	}
 134  	return fmt.Errorf(`invalid "params": not an object, array, or null`)
 135  }
 136