aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go126
1 files changed, 59 insertions, 67 deletions
diff --git a/main.go b/main.go
index 946603f..e54cd96 100644
--- a/main.go
+++ b/main.go
@@ -4,107 +4,99 @@ import (
"crypto/tls"
"errors"
"flag"
- "io/ioutil"
"log"
"net/http"
"net/http/httputil"
+ "net/rpc"
"net/url"
- "sync"
-
- "gopkg.in/yaml.v2"
)
var (
config = flag.String("conf", "certs/goxy.yml", "configuration file")
- listen = flag.String("listen", ":http", "HTTP")
- listenTLS = flag.String("listentls", ":https", "TLS")
+ listen = flag.String("listen", ":http", "HTTP port")
+ listenTLS = flag.String("listentls", ":https", "TLS port")
+ listenRPC = flag.String("listenrpc", ":http-alt", "RPC port")
+ data = flag.String("data", "data/goxy.gob", "persistent storage file")
+ route = make(Route)
+ mux = http.NewServeMux()
)
-type Config map[string]Route
+type Route map[string]Entry
-type Route struct {
- CertFile string
- KeyFile string
- Upstream string
- cert *tls.Certificate
+type Entry struct {
+ ServerName string
+ Upstream string
+ Cert *tls.Certificate
}
-func (c Config) SNI(h *tls.ClientHelloInfo) (*tls.Certificate, error) {
- if r, ok := c[h.ServerName]; ok && r.cert != nil {
- return r.cert, nil
+func (r Route) SNI(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)
}
-func (r *Route) LoadCert() error {
- if r.CertFile == "" && r.KeyFile == "" {
- return nil
+func (r Route) Restore() {
+ *mux = *http.NewServeMux()
+ for _, e := range route {
+ e.NewHandle()
}
- cert, err := tls.LoadX509KeyPair(r.CertFile, r.KeyFile)
+}
+
+func (e Entry) NewHandle() error {
+ log.Println("New handle", e)
+ up, err := url.Parse(e.Upstream)
if err != nil {
return err
}
- r.cert = &cert
+ mux.Handle(e.ServerName+"/", httputil.NewSingleHostReverseProxy(up))
return nil
}
-func (r Route) String() string {
- if r.cert != nil {
- return r.Upstream + " with TLS"
+func (e Entry) String() string {
+ if e.Cert != nil {
+ return e.ServerName + " -> " + e.Upstream + " with TLS"
} else {
- return r.Upstream
+ return e.ServerName + " -> " + e.Upstream
}
}
-func LoadConfig(fname string) (Config, error) {
- conf, err := ioutil.ReadFile(fname)
- if err != nil {
- return Config{}, err
+func StartHTTP(listen string) {
+ log.Println("listen", listen, "(HTTP)")
+ s := http.Server{
+ Addr: listen,
+ Handler: mux,
+ }
+ log.Fatal(s.ListenAndServe())
+}
+
+func StartTLS(listen string) {
+ log.Println("listen", listen, "(TLS)")
+ s := http.Server{
+ Addr: listen,
+ Handler: mux,
+ TLSConfig: &tls.Config{GetCertificate: route.SNI},
}
- var c Config
- return c, yaml.Unmarshal(conf, &c)
+ log.Fatal(s.ListenAndServeTLS("", ""))
+}
+
+func StartRPC(listen string) {
+ log.Println("listen", listen, "(RPC)")
+ rpc.HandleHTTP()
+ log.Fatal(http.ListenAndServe(listen, nil))
}
func main() {
flag.Parse()
- c, err := LoadConfig(*config)
- if err != nil {
- log.Fatal(err)
- }
- for k, v := range c {
- if err := v.LoadCert(); err != nil {
- log.Println("load", err)
- continue
- }
- c[k] = v
- up, err := url.Parse(v.Upstream)
- if err != nil {
- log.Println("upstream", err)
- continue
- }
- log.Println("map", k, "to", v)
- http.Handle(k+"/", httputil.NewSingleHostReverseProxy(up))
+ if err := route.Load(*data); err != nil {
+ log.Println(err)
}
+ route.Restore()
+
+ go StartHTTP(*listen)
+ go StartTLS(*listenTLS)
+ go StartRPC(*listenRPC)
- var wg sync.WaitGroup
- wg.Add(2)
- go func() {
- defer wg.Done()
- log.Println("listen", *listenTLS)
- s := http.Server{
- Addr: *listenTLS,
- TLSConfig: &tls.Config{GetCertificate: c.SNI},
- }
- log.Fatal(s.ListenAndServeTLS("", ""))
- }()
- go func() {
- defer wg.Done()
- log.Println("listen", *listen)
- s := http.Server{
- Addr: *listen,
- }
- log.Fatal(s.ListenAndServe())
- }()
- wg.Wait()
+ select {}
}