Created
November 7, 2018 16:10
-
-
Save asim/a035820aec2d8cba5d73b5be12c6e707 to your computer and use it in GitHub Desktop.
First commit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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