Skip to content

Instantly share code, notes, and snippets.

@asim
Created November 7, 2018 16:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asim/a035820aec2d8cba5d73b5be12c6e707 to your computer and use it in GitHub Desktop.
Save asim/a035820aec2d8cba5d73b5be12c6e707 to your computer and use it in GitHub Desktop.
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