|
1 |
| -# JSONRPC-JSON-Http-Handler |
| 1 | + |
| 2 | +# JSONRPC + JSONCPP |
| 3 | + |
| 4 | +JSONRPC Specification : http://www.jsonrpc.org/specification |
| 5 | + |
| 6 | +- Start with JSONRPC V2.0 and made some adjustment for my use. |
| 7 | +- Focus on Web Application rather than typical Clinet/Server Applicaiton. |
| 8 | +- Auto-Generated Code as much as possible. More can be done. |
| 9 | + |
| 10 | +## Example |
| 11 | + |
| 12 | +> **run::req** --> data sent to Server |
| 13 | +> **run::res** <-- data sent to Client |
| 14 | +
|
| 15 | +#### 1. RPC with named parameters |
| 16 | +##### math_subtract_1.csv |
| 17 | + |
| 18 | + |
| 19 | +|INPUT|TYPE|OUTPUT|TYPE| |
| 20 | +|-|-|-|-| |
| 21 | +|first|int|result|int| |
| 22 | +|second|int|||| |
| 23 | + |
| 24 | + |
| 25 | +|INPUT|VALUE|OUTPUT|VALUE| |
| 26 | +|-|-|-|-| |
| 27 | +|first|4|result|3| |
| 28 | +|second|1|||| |
| 29 | + |
| 30 | +>run::req[{"id": 1, "params": {"second": 13, "first": 18}, "jsonrpc": "2.0", "build": 10101, "method": 401}] size : 97 |
| 31 | +
|
| 32 | +>run::res[{"id":1,"jsonrpc":"2.0","result":5,"session":"wsxaljren"}] size : 58 |
| 33 | +
|
| 34 | +##### math_subtract_2.csv |
| 35 | + |
| 36 | +|INPUT|TYPE|OUTPUT|TYPE| |
| 37 | +|-|-|-|-| |
| 38 | +|first|int|first|int| |
| 39 | +|second|int|second|int| |
| 40 | +|||third|int| |
| 41 | + |
| 42 | +|INPUT|VALUE|OUTPUT|VALUE| |
| 43 | +|-|-|-|-| |
| 44 | +|first|7|first|6| |
| 45 | +|second|8|second|7| |
| 46 | +|||third|9| |
| 47 | + |
| 48 | +>run::req[{"id": 2, "params": {"second": 9, "first": 7}, "jsonrpc": "2.0", "build": 10101, "method": 402}] size : 95 |
| 49 | +
|
| 50 | +>run::res[{"id":2,"jsonrpc":"2.0","result":{"first":-2,"second":2,"third":4},"session":"wsxaljren"}] size : 90 |
| 51 | +
|
| 52 | + |
| 53 | +##### math_subtract_3.csv |
| 54 | + |
| 55 | +|INPUT|TYPE|OUTPUT|TYPE| |
| 56 | +|-|-|-|-| |
| 57 | +|first|int|first|int| |
| 58 | +|second|int|second|int| |
| 59 | +|third|int|||| |
| 60 | + |
| 61 | +|INPUT|VALUE|OUTPUT|VALUE| |
| 62 | +|-|-|-|-| |
| 63 | +|first|7|first|6| |
| 64 | +|second|8|second|7| |
| 65 | +|third|9|||| |
| 66 | + |
| 67 | +> run::req[{"id": 3, "params": {"second": 17, "third": 5, "first": 16}, "jsonrpc": "2.0", "build": 10101, "method": 403}] size : 109 |
| 68 | +
|
| 69 | +> run::res[{"id":3,"jsonrpc":"2.0","result":{"first":-1,"second":12},"session":"wsxaljren"}] size : 81 |
| 70 | +
|
| 71 | + |
| 72 | +#### 2. RPC with positioned parameters (Array) |
| 73 | + |
| 74 | +##### math_subtract_4.csv |
| 75 | + |
| 76 | +|INPUT|TYPE|OUTPUT|TYPE| |
| 77 | +|-|-|-|-| |
| 78 | +|first|[3]|first|[3]| |
| 79 | + |
| 80 | +|INPUT|VALUE|OUTPUT|VALUE| |
| 81 | +|-|-|-|-| |
| 82 | +|first|[7,9,10]|first|[6,8,9]| |
| 83 | + |
| 84 | + |
| 85 | +> run::req[{"id": 4, "params": [20, 41, 63], "jsonrpc": "2.0", "build": 10101, "method": 404}] size : 82 |
| 86 | +
|
| 87 | +> run::res[{"id":4,"jsonrpc":"2.0","result":[19,40,62],"session":"wsxaljren"}] size : 67 |
| 88 | +
|
| 89 | +##### math_subtract_5.csv |
| 90 | + |
| 91 | +|INPUT|TYPE|OUTPUT|TYPE| |
| 92 | +|-|-|-|-| |
| 93 | +|first|int[3]|first|int[3]| |
| 94 | +|second|int[5]|second|int[8]| |
| 95 | + |
| 96 | +|INPUT|VALUE|OUTPUT|VALUE| |
| 97 | +|-|-|-|-| |
| 98 | +|first|[7,9,10]|first|[6,8,9]| |
| 99 | +|second|[7,9,10,...]|second|[6,8,9,...]| |
| 100 | + |
| 101 | +>run::req[{"id": 5, "params": {"second": [11, 21, 31, 41, 51], "first": [20, 21, 23]}, "jsonrpc": "2.0", "build": 10101, "method": 405}] size : 125 |
| 102 | +
|
| 103 | +>run::res[{"id":5,"jsonrpc":"2.0","result":{"first":[19,20,22],"second":[9,19,29,1908443698,32506,0,0,0]},"session":"wsxaljren"}] size : 119 |
| 104 | +
|
| 105 | + |
| 106 | +#### 3. RPC with multi-level parameters |
| 107 | + |
| 108 | +##### math_subtract_6.csv |
| 109 | + |
| 110 | +**dict** type is a similar to **struct** in C/C++. |
| 111 | + |
| 112 | +|INPUT|TYPE|OUTPUT|TYPE| |
| 113 | +|-|-|-|-| |
| 114 | +|first|simple_struct{} |first|simple_struct{} | |
| 115 | + |
| 116 | + |
| 117 | +|INPUT|VALUE|OUTPUT|VALUE| |
| 118 | +|-|-|-|-| |
| 119 | +|first|{ "p1" : 2 , "p2" : 4 , "p3" : 10}|first|{ "p1" : 4 , "p2" : 5, "p3" : 6}| |
| 120 | + |
| 121 | + |
| 122 | +**simple_struct** for math_subtract_dict example. |
| 123 | + |
| 124 | +|PARAMETER|TYPE| |
| 125 | +|-|-| |
| 126 | +|p1|int| |
| 127 | +|p2|int| |
| 128 | +|p3|int| |
| 129 | + |
| 130 | +>run::req[{"id": 6, "params": {"first": {"p2": 5, "p3": 110, "p1": 44}}, "jsonrpc": "2.0", "build": 10101, "method": 406}] size : 111 |
| 131 | +
|
| 132 | +>run::res[{"id":6,"jsonrpc":"2.0","result":{"first":{"p1":40,"p2":1,"p3":106}},"session":"wsxaljren"}] size : 92 |
| 133 | +
|
| 134 | + |
| 135 | +##### math_subtract_7.csv |
| 136 | + |
| 137 | +**dict** type is a similar to **struct** in C/C++. |
| 138 | + |
| 139 | +|INPUT|TYPE|OUTPUT|TYPE| |
| 140 | +|-|-|-|-| |
| 141 | +|first|simple_struct{} |first|simple_struct{} | |
| 142 | +|second|simple_struct{} |second|simple_struct{} | |
| 143 | + |
| 144 | +|INPUT|VALUE|OUTPUT|VALUE| |
| 145 | +|-|-|-|-| |
| 146 | +|first|{ "p1" : 2 , "p2" : 4 , "p3" : 10}|first|{ "p1" : 4 , "p2" : 5, "p3" : 6}| |
| 147 | +|second|{ "p1" : 2 , "p2" : 4 , "p3" : 10}|second|{ "p1" : 4 , "p2" : 5, "p3" : 6}| |
| 148 | + |
| 149 | +> run::req[{"id": 7, "params": {"second": {"p2": 75, "p3": 20, "p1": 33}, "first": {"p2": 5, "p3": 110, "p1": 44}}, "jsonrpc": "2.0", "build": 10101, "method": 407}] size : 153 |
| 150 | +
|
| 151 | +> run::res[{"id":7,"jsonrpc":"2.0","result":{"first":{"p1":40,"p2":1,"p3":106},"second":{"p1":28,"p2":70,"p3":15}},"session":"wsxaljren"}] size : 127 |
| 152 | +
|
| 153 | + |
| 154 | +#### Additioanl Parameters (Automatically Added) |
| 155 | + |
| 156 | +|INPUT|TYPE|OUTPUT|TYPE| |
| 157 | +|-|-|-|-| |
| 158 | +|id|int|id|int| |
| 159 | +|session|int|session|string| |
| 160 | +|jsonrpc|string| | | |
| 161 | +|build|int| | | | |
| 162 | + |
| 163 | +**session** is an unique ID to be shared til the end of the whole chain of method calls. Allocated by the back-end. |
| 164 | +**build** is the release number to be compared for the backward compatibiity issue. |
| 165 | +**method** will be an enum value from code-generator |
| 166 | +#### 4. RPC Batch |
| 167 | + |
| 168 | +TBD. |
| 169 | +#### 5. RPC Error Detection |
| 170 | + |
| 171 | +##### 5.1 Parsing Error (JSON Format Error) -32700 |
| 172 | + |
| 173 | +run::req[{ 'jsonrpc': '2.0', 'build' : '10101', 'method': '407', 'params': '[ a,b,c,d,'' , 'id': '7'}] size : 93 |
| 174 | +run::res[{"error":{"code":-32700,"message":"Parse error"},"id":0,"jsonrpc":"2.0","session":""}] size : 86 |
| 175 | + |
| 176 | + |
| 177 | +##### 5.2 Unknown "method" -32601 |
| 178 | + |
| 179 | +> run::req[{"id": 7, "params": {"second": {"p2": 75, "p3": 20, "p1": 33}, "first": {"p2": 5, "p3": 110, "p1": 44}}, "jsonrpc": "2.0", "build": 10101, "method": 600}] size : 153 |
| 180 | +
|
| 181 | +>run::res[{"error":{"code":-32601,"message":"Method not found"},"id":7,"jsonrpc":"2.0","session":"wsxaljren"}] size : 100 |
| 182 | +
|
| 183 | + |
| 184 | +## Limitations |
| 185 | + |
| 186 | +Focus on different JSONRPC formats (as described in Example). Limit on the data type support (**int** and one-level struct). |
| 187 | + |
| 188 | +## Implementation |
| 189 | + |
| 190 | +For a simplicity reason, I use Microsoft Excel to put all examples in a single file. |
| 191 | + |
| 192 | +- math.xlsx becomes Math class. Each tab becomes method definition. |
| 193 | +- user-defined-types.xlsx |
| 194 | + |
| 195 | +Read .xls and generate codes as much as possible. **generator.py** |
| 196 | + |
| 197 | +The following package is used : |
| 198 | +- jsoncpp |
| 199 | +- AppWeb 2 EgiHandler |
| 200 | + |
| 201 | +Generated Code (**jsonrpc_handler.switch.include**) will be called from **EgiForm::run**. |
| 202 | + |
| 203 | + |
| 204 | +``` |
| 205 | + /* ...omitted for brevity... */ |
| 206 | + case MATH_SUBTRACT_1 : { |
| 207 | + Math math_instance; |
| 208 | + math_subtract_1_in_t math_subtract_1_input; |
| 209 | + math_subtract_1_out_t math_subtract_1_output; |
| 210 | + Json::Value JRes; |
| 211 | + int index = 0; |
| 212 | + math_subtract_1_input.first = JsonReq["params"]["first"].asInt(); |
| 213 | + math_subtract_1_input.second = JsonReq["params"]["second"].asInt(); |
| 214 | + jsonError = math_instance.subtract_1(math_subtract_1_input , math_subtract_1_output); |
| 215 | + JRes["result"] = math_subtract_1_output.result; |
| 216 | + JsonRes["result"] = JRes["result"]; |
| 217 | + } |
| 218 | +/* ...omitted for brevity... */ |
| 219 | +``` |
| 220 | + |
| 221 | + |
| 222 | +## Consideration |
| 223 | + |
| 224 | +- Use *.h (type definitions, function protoypes definitiosn, etc) instead. |
| 225 | + |
| 226 | + |
| 227 | + |
| 228 | + |
| 229 | + |
| 230 | + |
| 231 | + |
| 232 | + |
0 commit comments