server.go 1.8 KB

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