aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-03-31 11:28:15 +0200
committerDimitri Sokolyuk <demon@dim13.org>2016-03-31 11:28:15 +0200
commit94899ddaf95e79324de8bcdd70ca18ff834ec0be (patch)
tree6c3ade19899a77b4e28aee2d4f752164b6d3ae53
parent647ff6e872fe9e1de936521acdb23373a610e68d (diff)
Separated routes branch
-rw-r--r--entry.go13
-rw-r--r--route.go29
-rw-r--r--server.go40
-rw-r--r--server_test.go4
-rw-r--r--sni.go17
5 files changed, 60 insertions, 43 deletions
diff --git a/entry.go b/entry.go
new file mode 100644
index 0000000..de7c1e3
--- /dev/null
+++ b/entry.go
@@ -0,0 +1,13 @@
+package goxy
+
+// Entry holds routing settings
+type Entry struct {
+ Host string // HostName
+ Upstream string // URL
+ Cert []byte // PEM
+ Key []byte // PEM
+}
+
+func (e Entry) String() string {
+ return e.Host + " → " + e.Upstream
+}
diff --git a/route.go b/route.go
index 544fd2f..92d318d 100644
--- a/route.go
+++ b/route.go
@@ -1,9 +1,7 @@
package goxy
import (
- "crypto/tls"
"encoding/json"
- "errors"
"fmt"
"net/http"
"os"
@@ -12,14 +10,6 @@ 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)
-}
-
// Save routes to persistent file
func (r Route) Save(fname string) error {
fd, err := os.Create(fname)
@@ -42,23 +32,6 @@ func (r *Route) Load(fname string) error {
func (r Route) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
for k, v := range r {
- fmt.Fprintln(w, k, v)
- }
-}
-
-// Entry holds routing settings
-type Entry struct {
- Host string // HostName
- Upstream string // URL
- Cert []byte // PEM
- Key []byte // PEM
- cert *tls.Certificate // Parsed
-}
-
-func (e Entry) String() string {
- ret := e.Host + " → " + e.Upstream
- if e.cert != nil {
- ret += " with TLS"
+ fmt.Fprintln(w, k, "→", v)
}
- return ret
}
diff --git a/server.go b/server.go
index e4afc91..a000cad 100644
--- a/server.go
+++ b/server.go
@@ -10,33 +10,47 @@ import (
type Server struct {
DataFile string
+ SNI
Route
- http.Server
+ httpServer http.Server
+ tlsServer http.Server
}
func NewServer(dataFile string) (*Server, error) {
- r := make(Route)
- s := http.Server{TLSConfig: &tls.Config{GetCertificate: r.GetCertificate}}
- server := &Server{Route: r, Server: s, DataFile: dataFile}
+ sni := make(SNI)
+
+ server := &Server{
+ DataFile: dataFile,
+ SNI: sni,
+ Route: make(Route),
+ httpServer: http.Server{
+ Addr: ":http",
+ },
+ tlsServer: http.Server{
+ Addr: ":https",
+ TLSConfig: &tls.Config{
+ GetCertificate: sni.GetCertificate,
+ },
+ },
+ }
if dataFile != "" {
server.Load(dataFile)
}
RegisterRPC(server)
- http.Handle("/debug/route", r)
+ http.Handle("/debug/route", server.Route)
return server, server.Update()
}
// Update routes from in-memory state
func (s *Server) Update() error {
- mux := http.NewServeMux()
+ httpMux := http.NewServeMux()
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
- s.Route[k] = v
+ s.SNI[k] = &cert
}
up, err := url.Parse(v.Upstream)
if err != nil {
@@ -47,19 +61,19 @@ func (s *Server) Update() error {
}
switch up.Scheme {
case "ws":
- mux.Handle(v.Host, NewWebSocketProxy(up))
+ httpMux.Handle(v.Host, NewWebSocketProxy(up))
default:
- mux.Handle(v.Host, httputil.NewSingleHostReverseProxy(up))
+ httpMux.Handle(v.Host, httputil.NewSingleHostReverseProxy(up))
}
}
- s.Server.Handler = mux
+ s.httpServer.Handler = httpMux
return nil
}
func (s *Server) Start() error {
errc := make(chan error)
- go func() { errc <- s.ListenAndServe() }()
- go func() { errc <- s.ListenAndServeTLS("", "") }()
+ go func() { errc <- s.httpServer.ListenAndServe() }()
+ go func() { errc <- s.tlsServer.ListenAndServeTLS("", "") }()
go func() { errc <- http.ListenAndServe(":http-alt", nil) }()
return <-errc
}
diff --git a/server_test.go b/server_test.go
index ee72cb0..39a5826 100644
--- a/server_test.go
+++ b/server_test.go
@@ -73,7 +73,7 @@ func TestReverseProxy(t *testing.T) {
t.Error(err)
}
- frontServer.Config.Handler = server.Handler
+ frontServer.Config.Handler = server.httpServer.Handler
resp, err := http.Get(frontServer.URL)
if err != nil {
@@ -101,7 +101,7 @@ func TestReverseProxy(t *testing.T) {
t.Error(err)
}
- frontServer.Config.Handler = server.Handler
+ frontServer.Config.Handler = server.httpServer.Handler
ws, err := websocket.Dial("ws://"+frontURL.Host, "", "http://localhost")
if err != nil {
diff --git a/sni.go b/sni.go
new file mode 100644
index 0000000..cc73fb3
--- /dev/null
+++ b/sni.go
@@ -0,0 +1,17 @@
+package goxy
+
+import (
+ "crypto/tls"
+ "errors"
+)
+
+// SNI holds Certificates for Server Name Identication
+type SNI map[string]*tls.Certificate
+
+// GetCertificate returns certificate for SNI negotiation
+func (s SNI) GetCertificate(h *tls.ClientHelloInfo) (*tls.Certificate, error) {
+ if crt, ok := s[h.ServerName]; ok {
+ return crt, nil
+ }
+ return nil, errors.New("no cert for " + h.ServerName)
+}