support remote server group handler
This commit is contained in:
@@ -59,7 +59,7 @@ func (r *Client) Call(method string, args ...interface{}) (*Response, error) {
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, errors.Errorf("bad status %d for %s", resp.StatusCode, method)
|
||||
return nil, errors.Errorf("bad status %s for %s", resp.Status, method)
|
||||
}
|
||||
|
||||
cr := Response{}
|
||||
|
||||
@@ -40,6 +40,9 @@ type Server struct {
|
||||
}
|
||||
}
|
||||
|
||||
// Encoder is a function to encode call's result to Response
|
||||
type Encoder func(id uint64, resp interface{}, e error) (Response, error)
|
||||
|
||||
// ServerFn handler registered for each method with Add
|
||||
// Implementations provided by consumer and define response logic.
|
||||
type ServerFn func(id uint64, params json.RawMessage) Response
|
||||
@@ -107,10 +110,29 @@ func (s *Server) Shutdown() error {
|
||||
|
||||
// Add method handler
|
||||
func (s *Server) Add(method string, fn ServerFn) {
|
||||
s.httpServer.Lock()
|
||||
defer s.httpServer.Unlock()
|
||||
if s.httpServer.Server != nil {
|
||||
log.Printf("[WARN] ignored method %s, can't be added to activated server", method)
|
||||
return
|
||||
}
|
||||
|
||||
s.funcs.once.Do(func() {
|
||||
s.funcs.m = map[string]ServerFn{}
|
||||
})
|
||||
|
||||
s.funcs.m[method] = fn
|
||||
log.Printf("[INFO] add handler for %s", method)
|
||||
}
|
||||
|
||||
// HandlersGroup alias for map of handlers
|
||||
type HandlersGroup map[string]ServerFn
|
||||
|
||||
// Group of handlers with common prefix
|
||||
func (s *Server) Group(prefix string, m HandlersGroup) {
|
||||
for k, v := range m {
|
||||
s.Add(prefix+"."+k, v)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -40,6 +40,7 @@ func TestServerPrimitiveTypes(t *testing.T) {
|
||||
})
|
||||
|
||||
go func() { s.Run(9091) }()
|
||||
defer func() { assert.NoError(t, s.Shutdown()) }()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// check with direct http call
|
||||
@@ -64,7 +65,6 @@ func TestServerPrimitiveTypes(t *testing.T) {
|
||||
err = json.Unmarshal(*r.Result, &res)
|
||||
assert.Equal(t, respData{Res1: "res blah", Res2: true}, res)
|
||||
assert.Equal(t, uint64(1), r.ID)
|
||||
assert.NoError(t, s.Shutdown())
|
||||
}
|
||||
|
||||
func TestServerWithObject(t *testing.T) {
|
||||
@@ -94,6 +94,7 @@ func TestServerWithObject(t *testing.T) {
|
||||
})
|
||||
|
||||
go func() { s.Run(9091) }()
|
||||
defer func() { assert.NoError(t, s.Shutdown()) }()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
c := Client{API: "http://127.0.0.1:9091/v1/cmd", Client: http.Client{}}
|
||||
@@ -104,8 +105,6 @@ func TestServerWithObject(t *testing.T) {
|
||||
res := respData{}
|
||||
err = json.Unmarshal(*r.Result, &res)
|
||||
assert.Equal(t, respData{Res1: "res blah", Res2: true}, res)
|
||||
|
||||
assert.NoError(t, s.Shutdown())
|
||||
}
|
||||
|
||||
func TestServerMethodNotImplemented(t *testing.T) {
|
||||
@@ -148,6 +147,7 @@ func TestServerWithAuth(t *testing.T) {
|
||||
|
||||
go func() { s.Run(9091) }()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
defer func() { assert.NoError(t, s.Shutdown()) }()
|
||||
|
||||
c := Client{API: "http://127.0.0.1:9091/v1/cmd", Client: http.Client{}, AuthUser: "user", AuthPasswd: "passwd"}
|
||||
r, err := c.Call("test", "blah", 42, true)
|
||||
@@ -160,9 +160,7 @@ func TestServerWithAuth(t *testing.T) {
|
||||
|
||||
c = Client{API: "http://127.0.0.1:9091/v1/cmd", Client: http.Client{}}
|
||||
_, err = c.Call("test", "blah", 42, true)
|
||||
assert.EqualError(t, err, "bad status 401 for test")
|
||||
|
||||
assert.NoError(t, s.Shutdown())
|
||||
assert.EqualError(t, err, "bad status 401 Unauthorized for test")
|
||||
}
|
||||
|
||||
func TestServerErrReturn(t *testing.T) {
|
||||
@@ -186,13 +184,57 @@ func TestServerErrReturn(t *testing.T) {
|
||||
})
|
||||
|
||||
go func() { s.Run(9091) }()
|
||||
defer func() { assert.NoError(t, s.Shutdown()) }()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
c := Client{API: "http://127.0.0.1:9091/v1/cmd", Client: http.Client{}, AuthUser: "user", AuthPasswd: "passwd"}
|
||||
_, err := c.Call("test", "blah", 42, true)
|
||||
assert.EqualError(t, err, "some error")
|
||||
}
|
||||
|
||||
assert.NoError(t, s.Shutdown())
|
||||
func TestServerGroup(t *testing.T) {
|
||||
s := Server{API: "/v1/cmd"}
|
||||
s.Group("pre", HandlersGroup{
|
||||
"fn1": func(id uint64, params json.RawMessage) Response {
|
||||
return Response{}
|
||||
},
|
||||
"fn2": func(id uint64, params json.RawMessage) Response {
|
||||
return Response{}
|
||||
},
|
||||
})
|
||||
go func() { s.Run(9091) }()
|
||||
defer func() { assert.NoError(t, s.Shutdown()) }()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
c := Client{API: "http://127.0.0.1:9091/v1/cmd", Client: http.Client{}}
|
||||
_, err := c.Call("fn1")
|
||||
assert.EqualError(t, err, "bad status 501 Not Implemented for fn1")
|
||||
|
||||
_, err = c.Call("pre.fn1")
|
||||
assert.NoError(t, err)
|
||||
_, err = c.Call("pre.fn2")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestServerAddLate(t *testing.T) {
|
||||
s := Server{API: "/v1/cmd"}
|
||||
s.Add("fn1", func(id uint64, params json.RawMessage) Response {
|
||||
return Response{}
|
||||
})
|
||||
go func() { s.Run(9091) }()
|
||||
defer func() { assert.NoError(t, s.Shutdown()) }()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// too late, ignored after run
|
||||
s.Add("fn2", func(id uint64, params json.RawMessage) Response {
|
||||
return Response{}
|
||||
})
|
||||
|
||||
c := Client{API: "http://127.0.0.1:9091/v1/cmd", Client: http.Client{}}
|
||||
_, err := c.Call("fn1")
|
||||
assert.NoError(t, err)
|
||||
_, err = c.Call("fn2")
|
||||
assert.EqualError(t, err, "bad status 501 Not Implemented for fn2")
|
||||
}
|
||||
|
||||
func TestServerNoHandlers(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user