du7979
du7979
2015-07-14 03:03
浏览 73

从网页访问golang http + jsonrpc

I've used Go's net/rpc and net/rpc/jsonrpc packages a bit to perform connections between Go processes, however I'm wondering if there is a way to connect to an HTTP JSONRPC server using only the server tooling from the standard library (not that I have a problem writing my own, just don't want to do it if I don't have to).

This is the basic server setup I have:

arith := new(server.Arith)

server := rpc.NewServer()
server.Register(arith)

server.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath)

listener, e := net.Listen("tcp", ":4321")
if e != nil {
    log.Fatal("listen error:", e)
}
defer listener.Close()

http.Serve(listener, http.DefaultServeMux)

And I'd like to be able to be hitting this from a web page or a simple command line CURL call - just a regular POST.

However, this line: http://golang.org/src/net/rpc/server.go?s=20445:20475#L670 appears to indicate that it expects an HTTP client to issue a CONNECT and then directly write the JSON RPC request to the stream and receive the reply back the same way. I don't know if this is even possible from a browser, but it certainly is not as common or compatible as a simple POST.

Is there a way to start a JSON RPC server that I can just POST to using good ol' XMLHttpRequest ?

EDIT: Crap - the above is not even using the jsonrpc stuff - this is probably trying to use Gob, but whatever - the problem is the same - the code in src/net/rpc/server.go is not going to handle POSTs, so this route overall isn't going to work regardless of server codec.

图片转代码服务由CSDN问答提供 功能建议

我用过Go的 net / rpc net / rpc / jsonrpc 打包了一些代码来执行Go进程之间的连接,但是我想知道是否有一种方法可以仅使用标准库中的服务器工具来连接到HTTP JSONRPC服务器(不是我编写自己的问题时遇到了问题 ,只是不想做就可以了。)

这是我拥有的基本服务器设置:

 < 代码> arith:= new(server.Arith)
 
server:= rpc.NewServer()
server.Register(arith)
 
server.HandleHTTP(rpc.DefaultRPCPath,rpc.DefaultDebugPath)
 
listener,e  := net.Listen(“ tcp”,“:4321”)
if e!= nil {
 log.Fatal(“ listen error:”,e)
} 
defer listener.Close()
 
http  .serve(listener,http.DefaultServeMux)
   
 
 

而且我希望能够从网页或简单的命令行CURL调用中找到它- 只是常规的POST。

但是,这一行: http://golang.org/src/net/rpc/server.go?s=20445:20475#L670 似乎表明它期望使用HTTP客户端 发出CONNECT,然后将JSON RPC请求直接写入流中,并以相同的方式接收回复。 我不知道这是否可以通过浏览器实现,但是它肯定不像简单的POST那样普遍或兼容。

是否有一种启动JSON RPC服务器的方法? 我可以开机自检以使用良好的XMLHttpRequest吗?

编辑:废话-上面甚至没有使用jsonrpc东西-这可能是试图使用Gob,但是无论如何-问题是 相同-src / net / rpc / server.go中的代码将无法处理POST,因此无论服务器编解码器如何,此路由总体上都将无法工作。

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • duanqinjiao5244
    duanqinjiao5244 2015-07-16 02:13
    已采纳

    FWIW, I got this working by making a simple HTTP handler that adapts the HTTP request/response to a ServerCodec. Seems to work like a charm.

    Here's the working code as a test:

    import (
        "bytes"
        "fmt"
        "io"
        "io/ioutil"
        "log"
        "net"
        "net/http"
        "net/rpc"
        "net/rpc/jsonrpc"
        "testing"
    )
    
    // adapt HTTP connection to ReadWriteCloser
    type HttpConn struct {
        in  io.Reader
        out io.Writer
    }
    
    func (c *HttpConn) Read(p []byte) (n int, err error)  { return c.in.Read(p) }
    func (c *HttpConn) Write(d []byte) (n int, err error) { return c.out.Write(d) }
    func (c *HttpConn) Close() error                      { return nil }
    
    // our service
    type CakeBaker struct{}
    
    func (cb *CakeBaker) BakeIt(n int, msg *string) error {
        *msg = fmt.Sprintf("your cake has been bacon (%d)", n)
        return nil
    }
    
    func TestHTTPServer(t *testing.T) {
    
        fmt.Printf("TestHTTPServer
    ")
    
        cb := &CakeBaker{}
    
        server := rpc.NewServer()
        server.Register(cb)
    
        listener, e := net.Listen("tcp", ":4321")
        if e != nil {
            log.Fatal("listen error:", e)
        }
        defer listener.Close()
    
        go http.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    
            if r.URL.Path == "/bake-me-a-cake" {
                serverCodec := jsonrpc.NewServerCodec(&HttpConn{in: r.Body, out: w})
                w.Header().Set("Content-type", "application/json")
                w.WriteHeader(200)
                err := server.ServeRequest(serverCodec)
                if err != nil {
                    log.Printf("Error while serving JSON request: %v", err)
                    http.Error(w, "Error while serving JSON request, details have been logged.", 500)
                    return
                }
            }
    
        }))
    
        resp, err := http.Post("http://localhost:4321/bake-me-a-cake", "application/json", bytes.NewBufferString(
            `{"jsonrpc":"2.0","id":1,"method":"CakeBaker.BakeIt","params":[10]}`,
        ))
        if err != nil {
            panic(err)
        }
        defer resp.Body.Close()
        b, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            panic(err)
        }
    
        fmt.Printf("returned JSON: %s
    ", string(b))
    
    }
    
    点赞 评论
  • duanbushi1867
    duanbushi1867 2015-07-14 06:06

    a RPC framework shoud have language supports list, I not used json-rpc, but it should support javascript language by this link. you need add one of the javascript client sdk listed there.

    点赞 评论

相关推荐