aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-03-27 20:44:30 +0200
committerDimitri Sokolyuk <demon@dim13.org>2016-03-27 20:44:30 +0200
commit0824f4bcd9a31add8e7cfa1662d2cb40900de073 (patch)
tree63a152cd81992a9815fc8e3f23d873f2c562c505
parent24ba33d974cf651df195d2912b00238e6eeb2ed8 (diff)
Encapsulate in package
-rw-r--r--Dockerfile2
-rw-r--r--cmd/goxy/main.go28
-rw-r--r--cmd/goxyctl/main.go (renamed from goxyctl/main.go)28
-rw-r--r--data.go26
-rw-r--r--main.go34
-rw-r--r--route.go42
-rw-r--r--rpc.go33
-rw-r--r--server.go52
-rw-r--r--ws.go2
9 files changed, 126 insertions, 121 deletions
diff --git a/Dockerfile b/Dockerfile
index ae1638b..343a2e3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
FROM golang
ADD . /go/src/dim13.org/goxy
-RUN go install dim13.org/goxy
+RUN go install dim13.org/goxy/cmd/goxy
VOLUME /go/src/dim13.org/goxy/data
WORKDIR /go/src/dim13.org/goxy
ENTRYPOINT /go/bin/goxy
diff --git a/cmd/goxy/main.go b/cmd/goxy/main.go
new file mode 100644
index 0000000..fc122e0
--- /dev/null
+++ b/cmd/goxy/main.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "flag"
+ "log"
+ "net/http"
+
+ "dim13.org/goxy"
+
+ _ "net/http/pprof"
+)
+
+var data = flag.String("data", "data/goxy.gob", "persistent storage file")
+
+func main() {
+ flag.Parse()
+
+ server, err := goxy.NewServer(*data)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ errc := make(chan error, 3)
+ go func() { errc <- server.ListenAndServe() }()
+ go func() { errc <- server.ListenAndServeTLS("", "") }()
+ go func() { errc <- http.ListenAndServe(":http-alt", nil) }()
+ log.Fatal(<-errc)
+}
diff --git a/goxyctl/main.go b/cmd/goxyctl/main.go
index 5fbc1e8..1057fd4 100644
--- a/goxyctl/main.go
+++ b/cmd/goxyctl/main.go
@@ -5,6 +5,8 @@ import (
"io/ioutil"
"log"
"net/rpc"
+
+ "dim13.org/goxy"
)
var (
@@ -16,22 +18,6 @@ var (
remove = flag.Bool("remove", false, "Remove route")
)
-// Entry contains routing settings
-type Entry struct {
- ServerName string
- Upstream string
- Cert []byte
- Key []byte
-}
-
-func (e Entry) String() string {
- ret := e.ServerName + " → " + e.Upstream
- if e.Cert != nil && e.Key != nil {
- ret += " with TLS"
- }
- return ret
-}
-
func loadCert(certFile, keyFile string) ([]byte, []byte) {
if certFile == "" || keyFile == "" {
return nil, nil
@@ -47,7 +33,7 @@ func loadCert(certFile, keyFile string) ([]byte, []byte) {
return cert, key
}
-func send(server string, e Entry, del bool) error {
+func send(server string, e goxy.Entry, del bool) error {
client, err := rpc.DialHTTP("tcp", server)
if err != nil {
return err
@@ -62,20 +48,20 @@ func send(server string, e Entry, del bool) error {
log.Println("Del", e)
return client.Call("GoXY.Del", e, nil)
default:
- var r []Entry
+ var r goxy.Route
err = client.Call("GoXY.List", struct{}{}, &r)
if err != nil {
return err
}
- for _, e := range r {
- log.Println(e)
+ for k, v := range r {
+ log.Println(k, v)
}
}
return nil
}
func main() {
- var e Entry
+ var e goxy.Entry
flag.Parse()
e.ServerName, e.Upstream = *servername, *upstream
diff --git a/data.go b/data.go
deleted file mode 100644
index 474afae..0000000
--- a/data.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package main
-
-import (
- "encoding/gob"
- "os"
-)
-
-// Save routes to persistent file
-func (r Route) Save(fname string) error {
- fd, err := os.Create(fname)
- if err != nil {
- return err
- }
- defer fd.Close()
- return gob.NewEncoder(fd).Encode(r)
-}
-
-// Load routes from persistent file
-func (r *Route) Load(fname string) error {
- fd, err := os.Open(fname)
- if err != nil {
- return err
- }
- defer fd.Close()
- return gob.NewDecoder(fd).Decode(r)
-}
diff --git a/main.go b/main.go
deleted file mode 100644
index 21e68da..0000000
--- a/main.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package main
-
-import (
- "crypto/tls"
- "flag"
- "log"
- "net/http"
-
- _ "net/http/pprof"
-)
-
-var (
- data = flag.String("data", "data/goxy.gob", "persistent storage file")
- route = make(Route)
- server = http.Server{
- Handler: http.NewServeMux(),
- TLSConfig: &tls.Config{GetCertificate: route.GetCertificate},
- }
-)
-
-func main() {
- flag.Parse()
- if err := route.Load(*data); err != nil {
- log.Println(err)
- }
- if err := route.Restore(); err != nil {
- log.Fatal(err)
- }
- errc := make(chan error)
- go func() { errc <- server.ListenAndServe() }()
- go func() { errc <- server.ListenAndServeTLS("", "") }()
- go func() { errc <- http.ListenAndServe(":http-alt", nil) }()
- log.Fatal(<-errc)
-}
diff --git a/route.go b/route.go
index a695355..2fc38b3 100644
--- a/route.go
+++ b/route.go
@@ -1,4 +1,4 @@
-package main
+package goxy
import (
"crypto/tls"
@@ -12,21 +12,29 @@ import (
// Route defines a set of routes including correspondent TLS certificates
type Route map[string]Entry
+// GetCertificate returns certificate for SNI negotiation
+func (r Route) GetCertificate(h *tls.ClientHelloInfo) (*tls.Certificate, error) {
+ if e, ok := r[h.ServerName]; ok && e.cert != nil {
+ return e.cert, nil
+ }
+ return nil, errors.New("no cert for " + h.ServerName)
+}
+
// Entry holds routing settings
type Entry struct {
ServerName string
Upstream string
- Cert []byte
- Key []byte
- cert *tls.Certificate
+ Cert []byte // PEM
+ Key []byte // PEM
+ cert *tls.Certificate // Parsed
}
-// GetCertificate returns certificate for SNI negotiation
-func (r Route) GetCertificate(h *tls.ClientHelloInfo) (*tls.Certificate, error) {
- if e, ok := r[h.ServerName]; ok && e.cert != nil {
- return e.cert, nil
+func (e Entry) String() string {
+ ret := e.ServerName + " → " + e.Upstream
+ if e.cert != nil {
+ ret += " with TLS"
}
- return nil, errors.New("no cert for " + h.ServerName)
+ return ret
}
func NewReverseProxy(target *url.URL) *httputil.ReverseProxy {
@@ -39,16 +47,16 @@ func NewReverseProxy(target *url.URL) *httputil.ReverseProxy {
}
// Restore and update routes from in-memory state
-func (r Route) Restore() error {
+func (s *Server) Restore() error {
mux := http.NewServeMux()
- for k, v := range route {
+ for k, v := range s.Route {
if v.Cert != nil && v.Key != nil {
cert, err := tls.X509KeyPair(v.Cert, v.Key)
if err != nil {
return err
}
v.cert = &cert
- r[k] = v
+ s.Route[k] = v
}
up, err := url.Parse(v.Upstream)
if err != nil {
@@ -65,14 +73,6 @@ func (r Route) Restore() error {
mux.Handle(v.ServerName, NewReverseProxy(up))
}
}
- server.Handler = mux
+ s.Server.Handler = mux
return nil
}
-
-func (e Entry) String() string {
- ret := e.ServerName + " → " + e.Upstream
- if e.cert != nil {
- ret += " with TLS"
- }
- return ret
-}
diff --git a/rpc.go b/rpc.go
index 62a6a3f..bf7b36d 100644
--- a/rpc.go
+++ b/rpc.go
@@ -1,38 +1,37 @@
-package main
+package goxy
import (
"log"
"net/rpc"
)
-// GoXY defines RPC interface
-type GoXY struct{}
+type GoXY struct {
+ Server *Server
+}
-func init() {
- rpc.Register(GoXY{})
+func Register(s *Server) {
+ rpc.Register(&GoXY{s})
rpc.HandleHTTP()
}
// Add adds a new route
-func (GoXY) Add(e Entry, _ *struct{}) error {
+func (s *GoXY) Add(e Entry, _ *struct{}) error {
log.Println("Add route", e)
- defer route.Save(*data)
- route[e.ServerName] = e
- return route.Restore()
+ defer s.Server.Save()
+ s.Server.Route[e.ServerName] = e
+ return s.Server.Restore()
}
// Del removes a route
-func (GoXY) Del(e Entry, _ *struct{}) error {
+func (s *GoXY) Del(e Entry, _ *struct{}) error {
log.Println("Del route", e)
- defer route.Save(*data)
- delete(route, e.ServerName)
- return route.Restore()
+ defer s.Server.Save()
+ delete(s.Server.Route, e.ServerName)
+ return s.Server.Restore()
}
// List routes
-func (GoXY) List(_ struct{}, r *[]Entry) error {
- for _, v := range route {
- *r = append(*r, v)
- }
+func (s GoXY) List(_ struct{}, r *Route) error {
+ *r = s.Server.Route
return nil
}
diff --git a/server.go b/server.go
new file mode 100644
index 0000000..3d6651f
--- /dev/null
+++ b/server.go
@@ -0,0 +1,52 @@
+package goxy
+
+import (
+ "crypto/tls"
+ "encoding/gob"
+ "log"
+ "net/http"
+ "os"
+)
+
+type Server struct {
+ Route
+ http.Server
+ Data string
+}
+
+func NewServer(fname string) (*Server, error) {
+ r := make(Route)
+ s := http.Server{
+ Handler: http.NewServeMux(),
+ TLSConfig: &tls.Config{GetCertificate: r.GetCertificate},
+ }
+ server := &Server{Route: r, Server: s, Data: fname}
+ if err := server.Load(); err != nil {
+ log.Println(err)
+ }
+ if err := server.Restore(); err != nil {
+ return nil, err
+ }
+ Register(server)
+ return server, nil
+}
+
+// Save routes to persistent file
+func (s Server) Save() error {
+ fd, err := os.Create(s.Data)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ return gob.NewEncoder(fd).Encode(s.Route)
+}
+
+// Load routes from persistent file
+func (s *Server) Load() error {
+ fd, err := os.Open(s.Data)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ return gob.NewDecoder(fd).Decode(&s.Route)
+}
diff --git a/ws.go b/ws.go
index a5c5d2f..b0199e8 100644
--- a/ws.go
+++ b/ws.go
@@ -1,4 +1,4 @@
-package main
+package goxy
import (
"io"