【问题标题】:golang http+jsonrpc access from web pagegolang http+jsonrpc 从网页访问
【发布时间】:2015-07-14 03:03:57
【问题描述】:

我已经使用了 Go 的 net/rpcnet/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 服务器,我可以通过 POST 来使用好的 ol' XMLHttpRequest ?

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

【问题讨论】:

    标签: json go json-rpc


    【解决方案1】:

    FWIW,我通过制作一个简单的 HTTP 处理程序来完成这项工作,该处理程序使 HTTP 请求/响应适应 ServerCodec。似乎像魅力一样工作。

    这是作为测试的工作代码:

    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\n")
    
        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\n", string(b))
    
    }
    

    【讨论】:

      【解决方案2】:

      一个 RPC 框架应该有语言支持列表,我没有使用 json-rpc,但它应该支持 javascript 语言 this link。您需要添加其中列出的 javascript 客户端 sdk 之一。

      【讨论】:

        猜你喜欢
        • 2016-08-05
        • 1970-01-01
        • 1970-01-01
        • 2020-03-08
        • 2014-06-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-18
        相关资源
        最近更新 更多