2017-01-18 09:57:18 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2017-10-01 13:28:13 +00:00
|
|
|
"context"
|
2017-01-22 18:16:18 +00:00
|
|
|
"crypto/tls"
|
2017-01-18 09:57:18 +00:00
|
|
|
"flag"
|
|
|
|
"math/rand"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
2017-10-01 13:54:56 +00:00
|
|
|
_ "git.xeserv.us/xena/route/internal"
|
|
|
|
"git.xeserv.us/xena/route/internal/middleware"
|
2017-09-30 13:50:24 +00:00
|
|
|
"git.xeserv.us/xena/route/internal/routecrypto"
|
|
|
|
"git.xeserv.us/xena/route/internal/server"
|
2017-04-28 23:28:03 +00:00
|
|
|
"github.com/Xe/ln"
|
|
|
|
"github.com/caarlos0/env"
|
2017-01-18 09:57:18 +00:00
|
|
|
"github.com/facebookgo/flagenv"
|
|
|
|
_ "github.com/joho/godotenv/autoload"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2017-01-26 04:22:27 +00:00
|
|
|
sslCertKey = flag.String("ssl-cert-key", "", "if set encrypt SSL certs with this key")
|
2017-01-18 09:57:18 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
|
|
|
flagenv.Parse()
|
|
|
|
rand.Seed(time.Now().Unix())
|
2017-10-01 13:28:13 +00:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
2017-01-18 09:57:18 +00:00
|
|
|
|
2017-01-26 04:22:27 +00:00
|
|
|
certKey, _ := routecrypto.ParseKey(*sslCertKey)
|
|
|
|
|
2017-04-28 23:28:03 +00:00
|
|
|
scfg := server.Config{}
|
|
|
|
err := env.Parse(&scfg)
|
2017-01-18 09:57:18 +00:00
|
|
|
if err != nil {
|
2017-10-01 13:28:13 +00:00
|
|
|
ln.FatalErr(ctx, err, ln.Action("parsing environment for config"))
|
2017-01-18 09:57:18 +00:00
|
|
|
}
|
2017-04-28 23:28:03 +00:00
|
|
|
scfg.CertKey = certKey
|
2017-01-18 09:57:18 +00:00
|
|
|
|
2017-04-28 23:28:03 +00:00
|
|
|
s, err := server.New(scfg)
|
|
|
|
if err != nil {
|
2017-10-01 13:28:13 +00:00
|
|
|
ln.FatalErr(ctx, err, ln.Action("create server instance"))
|
2017-01-22 18:16:18 +00:00
|
|
|
}
|
|
|
|
|
2017-04-28 23:28:03 +00:00
|
|
|
go setupTLS(s, scfg)
|
|
|
|
|
2017-10-01 13:28:13 +00:00
|
|
|
// listen on HTTP listener
|
2017-04-28 23:28:03 +00:00
|
|
|
l, err := net.Listen("tcp", scfg.WebAddr)
|
2017-01-18 09:57:18 +00:00
|
|
|
if err != nil {
|
2017-10-01 13:28:13 +00:00
|
|
|
ln.FatalErr(ctx, err, ln.Action("listening on HTTP port"), ln.F{"addr": scfg.WebAddr})
|
2017-01-18 09:57:18 +00:00
|
|
|
}
|
|
|
|
defer l.Close()
|
|
|
|
|
|
|
|
hs := &http.Server{
|
2017-10-01 18:29:31 +00:00
|
|
|
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
switch r.Method {
|
|
|
|
case http.MethodPatch, http.MethodPut, http.MethodPost:
|
|
|
|
http.Error(w, "use https", http.StatusNotAcceptable)
|
|
|
|
ln.Log(r.Context(), ln.Action("cannot redirect (wrong method)"), ln.F{"remote": r.RemoteAddr, "host": r.Host, "path": r.URL.Path})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-10-01 18:01:18 +00:00
|
|
|
r.URL.Host = r.Host
|
2017-10-01 17:57:52 +00:00
|
|
|
r.URL.Scheme = "https"
|
2017-10-01 18:04:19 +00:00
|
|
|
|
2017-10-01 18:29:31 +00:00
|
|
|
ln.Log(r.Context(), ln.Action("redirecting insecure HTTP to HTTPS"), ln.F{"remote": r.RemoteAddr, "host": r.Host, "path": r.URL.Path})
|
2017-10-01 18:04:19 +00:00
|
|
|
|
2017-10-01 17:57:52 +00:00
|
|
|
http.Redirect(w, r, r.URL.String(), http.StatusPermanentRedirect)
|
2017-10-01 18:29:31 +00:00
|
|
|
}),
|
2017-10-01 17:57:52 +00:00
|
|
|
Addr: scfg.WebAddr,
|
2017-01-18 09:57:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hs.Serve(l)
|
|
|
|
}
|
2017-01-22 18:16:18 +00:00
|
|
|
|
2017-04-28 23:28:03 +00:00
|
|
|
func setupTLS(s *server.Server, scfg server.Config) {
|
2017-01-22 18:16:18 +00:00
|
|
|
hs := &http.Server{
|
2017-10-01 13:54:56 +00:00
|
|
|
Handler: middleware.Trace(s),
|
2017-04-28 23:28:03 +00:00
|
|
|
Addr: scfg.SSLAddr,
|
2017-01-22 18:16:18 +00:00
|
|
|
TLSConfig: &tls.Config{
|
2017-04-28 23:28:03 +00:00
|
|
|
GetCertificate: s.GetCertificate,
|
2017-01-22 18:16:18 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2017-10-01 13:28:13 +00:00
|
|
|
for {
|
|
|
|
hs.ListenAndServeTLS("", "")
|
|
|
|
}
|
2017-01-22 18:16:18 +00:00
|
|
|
}
|