425nesp 425nesp - 13 days ago 6
JSON Question

Batch JSON-RPCs in Go with Gorilla RPC

Okay, so I'm working a server. It serves webpages and provides other services.

package main

import (
"fmt"
"log"
"net/http"

"github.com/gorilla/rpc"
"github.com/gorilla/rpc/json"
)

type Service struct {
Name string
}

type ServiceArgs struct {
Str string
Val float64
}

type ServiceReply struct {
Message string
}

func (e *Service) DoSomething(request *http.Request, args *ServiceArgs, reply *ServiceReply) error {
fmt.Println("DoSomething called remotely!")
reply.Message = "OMG. It works."

return nil
}

func main() {
rpcHandler := rpc.NewServer()
rpcHandler.RegisterCodec(json.NewCodec(), "application/json")
rpcHandler.RegisterService(new(Service), "")
http.Handle("/rpc", rpcHandler)

http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("."))))

fmt.Println("Listening on port 8080.")
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatalln(err)
}
}


I have an API on the server side that I want normal clients to be able to access. For this, I started learning more about JSON-RPC. This is how I call
Service.DoSomething
from a web browser.

var log = document.getElementById("log");
var request = new XMLHttpRequest();

var command = {
"jsonrpc":"2.0",
"method":"Service.DoSomething",
"params":[{
"Str":"pie",
"Val":3.14
}],
"id":1
};

request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
var response = JSON.parse(request.responseText).result;
log.textContent += response["Message"];
} else {
console.log(request.statusText);
}
};

request.open("POST", "/rpc", true);
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
request.send(JSON.stringify(command));


This works fine. I see "OMG. It works." in my browser when I run that JavaScript. Next, I wanted to run multiple method calls. I found that there is a way to send a "batch" of calls to the server. So I tried this from JavaScript.

var command = [
{"jsonrpc":"2.0","method":"Service.DoSomething","params":[{"Str":"pie","Val":3.14}],"id":1},
{"jsonrpc":"2.0","method":"Service.DoSomething","params":[{"Str":"pie","Val":3.14}],"id":2}
];

request.send(JSON.stringify(command));


However, this gives me a
400 (Bad Request)
. Did I screw up the syntax somewhere? Or is this a problem with
gorilla/rpc
?

Answer

According to The Gorilla Toolkit JSON-RPC overview:

This package follows the JSON-RPC 1.0 specification:

According to The JSON-RPC spec, and the JSON-RPC Google group discussion, 'batch' is a JSON-RPC 2.0 feature.

It looks like Gorilla JSON-RPC doesn't understand the batched queries.

Comments