2015-07-14 3 views
2

Я использовал Go's net/rpc и net/rpc/jsonrpc пакеты немного для выполнения соединений между процессами Go, однако мне интересно, есть ли способ подключиться к HTTP-серверу JSONRPC, используя только сервер инструментария из стандартной библиотеки (не то, что у меня есть проблема с написанием моего собственного, просто не хочу этого делать, если мне не нужно).golang 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, а затем напрямую напишет запрос JCON RPC в поток и получит ответ обратно таким же образом. Я не знаю, возможно ли это из браузера, но это, конечно, не так просто или совместимо, как простой POST.

Есть ли способ запустить JSON RPC-сервер, который я могу просто использовать POST для использования хорошего XML-файла XMLHttpRequest?

EDIT: Crap - выше даже не используется материал jsonrpc - это, вероятно, пытается использовать Gob, но что бы то ни было - проблема такая же - код в src/net/rpc/server.go не собирается для обработки POST, поэтому этот маршрут в целом не будет работать независимо от кодека сервера.

ответ

5

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)) 

} 
-1

RPC-инфраструктура shoud имеет список поддержки языков, я не использовал json-rpc, но он должен поддерживать javascript-язык на this link. вам нужно добавить один из указанных здесь javascript-клиентов sdk.

Смежные вопросы