First commit
From 64696c3fd04ba616a8d8e5a52eaad17aad229b72 Mon Sep 17 00:00:00 2001 | |
From: Asim <asim@chuhnk.me> | |
Date: Fri, 31 Oct 2014 17:14:25 +0000 | |
Subject: [PATCH] First | |
--- | |
client/client.go | 18 ++++++++ | |
client/request.go | 8 ++++ | |
client/rpc_client.go | 60 +++++++++++++++++++++++++++ | |
client/rpc_request.go | 35 ++++++++++++++++ | |
examples/client.go | 23 ++++++++++ | |
server/receiver.go | 6 +++ | |
server/rpc_server.go | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ | |
server/server.go | 33 +++++++++++++++ | |
8 files changed, 296 insertions(+) | |
create mode 100644 client/client.go | |
create mode 100644 client/request.go | |
create mode 100644 client/rpc_client.go | |
create mode 100644 client/rpc_request.go | |
create mode 100644 examples/client.go | |
create mode 100644 server/receiver.go | |
create mode 100644 server/rpc_server.go | |
create mode 100644 server/server.go | |
diff --git a/client/client.go b/client/client.go | |
new file mode 100644 | |
index 0000000..3a71b60 | |
--- /dev/null | |
+++ b/client/client.go | |
@@ -0,0 +1,18 @@ | |
+package client | |
+ | |
+type Client interface { | |
+ NewRequest(string, string, string, interface{}) Request | |
+ Call(string, interface{}, interface{}) error | |
+} | |
+ | |
+var ( | |
+ client = NewRpcClient() | |
+) | |
+ | |
+func Call(request Request, response interface{}) error { | |
+ return client.Call(request, response) | |
+} | |
+ | |
+func NewRequest(address, path, method string, request interface{}) Request { | |
+ return client.NewRequest(address, path, method, request) | |
+} | |
diff --git a/client/request.go b/client/request.go | |
new file mode 100644 | |
index 0000000..adce84b | |
--- /dev/null | |
+++ b/client/request.go | |
@@ -0,0 +1,8 @@ | |
+package client | |
+ | |
+type Request interface { | |
+ Address() string | |
+ Path() string | |
+ Method() string | |
+ Request() interface{} | |
+} | |
diff --git a/client/rpc_client.go b/client/rpc_client.go | |
new file mode 100644 | |
index 0000000..9374322 | |
--- /dev/null | |
+++ b/client/rpc_client.go | |
@@ -0,0 +1,60 @@ | |
+package client | |
+ | |
+import ( | |
+ "bufio" | |
+ "errors" | |
+ "io" | |
+ "net" | |
+ "net/http" | |
+ "net/rpc" | |
+ | |
+ //log "github.com/cihub/seelog" | |
+ // "code.google.com/p/goprotobuf/proto" | |
+ "code.google.com/p/protorpc" | |
+) | |
+ | |
+type RpcClient struct{} | |
+ | |
+func (r *RpcClient) Call(request Request, response interface{}) error { | |
+ c, err := r.Dial(request) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ return c.Call(request.Method(), request.Request(), response) | |
+} | |
+ | |
+func (r *RpcClient) Dial(req Request) (*rpc.Client, error) { | |
+ var err error | |
+ conn, err := net.Dial("tcp", req.Address()) | |
+ if err != nil { | |
+ return nil, err | |
+ } | |
+ io.WriteString(conn, "CONNECT "+req.Path()+" HTTP/1.0\n\n") | |
+ | |
+ // Require successful HTTP response | |
+ // before switching to RPC protocol. | |
+ resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"}) | |
+ if err == nil && resp.Status == "200 Connected to Go RPC" { | |
+ cc := protorpc.NewClientCodec(conn) | |
+ return rpc.NewClientWithCodec(cc), nil | |
+ } | |
+ if err == nil { | |
+ err = errors.New("unexpected HTTP response: " + resp.Status) | |
+ } | |
+ conn.Close() | |
+ return nil, &net.OpError{ | |
+ Op: "dial-http", | |
+ Net: "tcp " + req.Address(), | |
+ Addr: nil, | |
+ Err: err, | |
+ } | |
+} | |
+ | |
+func (r *RpcClient) NewRequest(address, path, method string, request interface{}) *RpcRequest { | |
+ return newRpcRequest(address, path, method, request) | |
+} | |
+ | |
+func NewRpcClient() *RpcClient { | |
+ return &RpcClient{} | |
+} | |
diff --git a/client/rpc_request.go b/client/rpc_request.go | |
new file mode 100644 | |
index 0000000..e71111b | |
--- /dev/null | |
+++ b/client/rpc_request.go | |
@@ -0,0 +1,35 @@ | |
+package client | |
+ | |
+type RpcRequest struct { | |
+ address, path, method string | |
+ request interface{} | |
+} | |
+ | |
+func newRpcRequest(address, path, method string, request interface{}) *RpcRequest { | |
+ return &RpcRequest{ | |
+ address: address, | |
+ path: path, | |
+ method: method, | |
+ request: request, | |
+ } | |
+} | |
+ | |
+func (r *RpcRequest) Address() string { | |
+ return r.address | |
+} | |
+ | |
+func (r *RpcRequest) Path() string { | |
+ return r.path | |
+} | |
+ | |
+func (r *RpcRequest) Method() string { | |
+ return r.method | |
+} | |
+ | |
+func (r *RpcRequest) Request() interface{} { | |
+ return r.request | |
+} | |
+ | |
+func NewRpcRequest(address, path, method string, request interface{}) *RpcRequest { | |
+ return newRpcRequest(address, path, method, request) | |
+} | |
diff --git a/examples/client.go b/examples/client.go | |
new file mode 100644 | |
index 0000000..f45e78d | |
--- /dev/null | |
+++ b/examples/client.go | |
@@ -0,0 +1,23 @@ | |
+package main | |
+ | |
+import ( | |
+ "fmt" | |
+ | |
+ "code.google.com/p/goprotobuf/proto" | |
+ "github.com/myodc/go-platform/client" | |
+ example "github.com/myodc/go-template/proto/example" | |
+) | |
+ | |
+func main() { | |
+ req := client.NewRequest(":8080", "/rpc", "Example.Call", &example.Request{ | |
+ Name: proto.String("John"), | |
+ }) | |
+ | |
+ rsp := &example.Response{} | |
+ if err := client.Call(req, rsp); err != nil { | |
+ fmt.Println(err) | |
+ return | |
+ } | |
+ | |
+ fmt.Println(rsp.GetMsg()) | |
+} | |
diff --git a/server/receiver.go b/server/receiver.go | |
new file mode 100644 | |
index 0000000..f7498e3 | |
--- /dev/null | |
+++ b/server/receiver.go | |
@@ -0,0 +1,6 @@ | |
+package server | |
+ | |
+type Receiver interface { | |
+ Name() string | |
+ Handler() interface{} | |
+} | |
diff --git a/server/rpc_server.go b/server/rpc_server.go | |
new file mode 100644 | |
index 0000000..fd3f380 | |
--- /dev/null | |
+++ b/server/rpc_server.go | |
@@ -0,0 +1,113 @@ | |
+package server | |
+ | |
+import ( | |
+ "io" | |
+ "net" | |
+ "net/http" | |
+ "net/rpc" | |
+ | |
+ "code.google.com/p/protorpc" | |
+ log "github.com/cihub/seelog" | |
+) | |
+ | |
+type RpcReceiver struct { | |
+ name string | |
+ handler interface{} | |
+} | |
+ | |
+type RpcServer struct { | |
+ *rpc.Server | |
+ address string | |
+ exit chan chan error | |
+} | |
+ | |
+var ( | |
+ RpcPath = "/rpc" | |
+ DebugRpcPath = "/debug/rpc" | |
+) | |
+ | |
+func newRpcReceiver(name string, handler interface{}) *RpcReceiver { | |
+ return &RpcReceiver{ | |
+ name: name, | |
+ handler: handler, | |
+ } | |
+} | |
+ | |
+func (r *RpcReceiver) Name() string { | |
+ return r.name | |
+} | |
+ | |
+func (r *RpcReceiver) Handler() interface{} { | |
+ return r.handler | |
+} | |
+ | |
+func (s *RpcServer) Init() error { | |
+ return nil | |
+} | |
+ | |
+func (s *RpcServer) NewReceiver(name string, handler interface{}) *RpcReceiver { | |
+ return newRpcReceiver(name, handler) | |
+} | |
+ | |
+func (s *RpcServer) Register(r Receiver) error { | |
+ if len(r.Name()) > 0 { | |
+ s.RegisterName(r.Name(), r.Handler()) | |
+ return nil | |
+ } | |
+ | |
+ s.Server.Register(r.Handler()) | |
+ return nil | |
+} | |
+ | |
+func (s *RpcServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | |
+ if req.Method != "CONNECT" { | |
+ w.Header().Set("Content-Type", "text/plain; charset=utf-8") | |
+ w.WriteHeader(http.StatusMethodNotAllowed) | |
+ io.WriteString(w, "405 must CONNECT\n") | |
+ return | |
+ } | |
+ conn, _, err := w.(http.Hijacker).Hijack() | |
+ if err != nil { | |
+ log.Trace("rpc hijacking ", req.RemoteAddr, ": ", err.Error()) | |
+ return | |
+ } | |
+ io.WriteString(conn, "HTTP/1.0 200 Connected to Go RPC\n\n") | |
+ cc := protorpc.NewServerCodec(conn) | |
+ s.ServeCodec(cc) | |
+} | |
+ | |
+func (s *RpcServer) Start() error { | |
+ http.Handle(RpcPath, s) | |
+ | |
+ log.Debugf("Rpc HTTP handler %s", RpcPath) | |
+ | |
+ l, err := net.Listen("tcp", s.address) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Debugf("Listening on %s", s.address) | |
+ go http.Serve(l, nil) | |
+ | |
+ ch := <-s.exit | |
+ ch <- l.Close() | |
+ return nil | |
+} | |
+ | |
+func (s *RpcServer) Stop() error { | |
+ ch := make(chan error) | |
+ s.exit <- ch | |
+ return <-ch | |
+} | |
+ | |
+func NewRpcReceiver(name string, handler interface{}) *RpcReceiver { | |
+ return newRpcReceiver(name, handler) | |
+} | |
+ | |
+func NewRpcServer(address string) *RpcServer { | |
+ return &RpcServer{ | |
+ rpc.NewServer(), | |
+ address, | |
+ make(chan chan error), | |
+ } | |
+} | |
diff --git a/server/server.go b/server/server.go | |
new file mode 100644 | |
index 0000000..997b18f | |
--- /dev/null | |
+++ b/server/server.go | |
@@ -0,0 +1,33 @@ | |
+package server | |
+ | |
+type Server interface { | |
+ Init() error | |
+ NewReceiver(string, interface{}) Receiver | |
+ Register(Receiver) error | |
+ Start() error | |
+ Stop() error | |
+} | |
+ | |
+var ( | |
+ server = NewRpcServer(":8080") | |
+) | |
+ | |
+func Init() error { | |
+ return server.Init() | |
+} | |
+ | |
+func NewReceiver(path string, handler interface{}) Receiver { | |
+ return server.NewReceiver(path, handler) | |
+} | |
+ | |
+func Register(r Receiver) error { | |
+ return server.Register(r) | |
+} | |
+ | |
+func Start() error { | |
+ return server.Start() | |
+} | |
+ | |
+func Stop() error { | |
+ return server.Stop() | |
+} | |
-- | |
2.10.5 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment