server.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. package main
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "errors"
  6. "io/ioutil"
  7. "net/http"
  8. "net/url"
  9. )
  10. import (
  11. "github.com/fatih/color"
  12. log "github.com/sirupsen/logrus"
  13. "github.com/vulcand/oxy/forward"
  14. "github.com/vulcand/oxy/roundrobin"
  15. "golang.org/x/crypto/acme/autocert"
  16. )
  17. // Initialize the autocert manager and configure it,
  18. // also create an instance of the http.Server and link the autocert manager to it.
  19. func InitServer() error {
  20. m := autocert.Manager{
  21. Cache: autocert.DirCache(*STORAGE),
  22. Prompt: autocert.AcceptTOS,
  23. HostPolicy: func(ctx context.Context, host string) error {
  24. if _, ok := HOSTS[host]; ok {
  25. return nil
  26. }
  27. return errors.New("Unkown host(" + host + ")")
  28. },
  29. }
  30. s := &http.Server{
  31. Addr: *HTTPS_ADDR,
  32. TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
  33. Handler: ServeHTTP(),
  34. }
  35. log.SetOutput(ioutil.Discard)
  36. return s.ListenAndServeTLS("", "")
  37. }
  38. // The main server handler
  39. func ServeHTTP() http.Handler {
  40. return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
  41. if upstreams, ok := HOSTS[req.Host]; ok {
  42. forwarder, _ := forward.New()
  43. loadbalancer, _ := roundrobin.New(forwarder)
  44. for _, upstream := range upstreams {
  45. if url, err := url.Parse(upstream); err == nil {
  46. loadbalancer.UpsertServer(url)
  47. } else {
  48. colorize(color.FgRed, "⇛", err.Error())
  49. }
  50. }
  51. loadbalancer.ServeHTTP(res, req)
  52. return
  53. }
  54. http.Error(res, "The request domain couldn't be found here", http.StatusNotImplemented)
  55. })
  56. }