server.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. errchan := make(chan error)
  31. s := &http.Server{
  32. Addr: *HTTPS_ADDR,
  33. TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
  34. Handler: ServeHTTP(),
  35. }
  36. log.SetOutput(ioutil.Discard)
  37. go (func() {
  38. handler := m.HTTPHandler(ServeHTTP())
  39. if *AUTOREDIRECT {
  40. handler = m.HTTPHandler(nil)
  41. }
  42. errchan <- http.ListenAndServe(*HTTP_ADDR, handler)
  43. })()
  44. go (func() {
  45. errchan <- s.ListenAndServeTLS("", "")
  46. })()
  47. return <-errchan
  48. }
  49. // The main server handler
  50. func ServeHTTP() http.Handler {
  51. return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
  52. if upstreams, ok := HOSTS[req.Host]; ok {
  53. forwarder, _ := forward.New(forward.PassHostHeader(true))
  54. loadbalancer, _ := roundrobin.New(forwarder)
  55. for _, upstream := range upstreams {
  56. if url, err := url.Parse(upstream); err == nil {
  57. loadbalancer.UpsertServer(url)
  58. } else {
  59. colorize(color.FgRed, "⇛", err.Error())
  60. }
  61. }
  62. if *EXPOSE_INFO {
  63. res.Header().Set("X-HTTPSIFY-Version", VERSION)
  64. }
  65. if *HSTS != "" {
  66. res.Header().Set("Strict-Transport-Security", *HSTS)
  67. }
  68. loadbalancer.ServeHTTP(res, req)
  69. return
  70. }
  71. http.Error(res, "The request service couldn't be found here", http.StatusNotImplemented)
  72. })
  73. }