proxy.go 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package proxy
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "net/http/httputil"
  7. "net/url"
  8. )
  9. func NewHandler(endpoints []string) (*httputil.ReverseProxy, error) {
  10. d, err := newDirector(endpoints)
  11. if err != nil {
  12. return nil, err
  13. }
  14. proxy := httputil.ReverseProxy{
  15. Director: d.direct,
  16. Transport: &http.Transport{},
  17. FlushInterval: 0,
  18. }
  19. return &proxy, nil
  20. }
  21. func newDirector(endpoints []string) (*director, error) {
  22. if len(endpoints) == 0 {
  23. return nil, errors.New("one or more endpoints required")
  24. }
  25. urls := make([]url.URL, len(endpoints))
  26. for i, e := range endpoints {
  27. u, err := url.Parse(e)
  28. if err != nil {
  29. return nil, fmt.Errorf("invalid endpoint %q: %v", e, err)
  30. }
  31. if u.Scheme == "" {
  32. return nil, fmt.Errorf("invalid endpoint %q: scheme required", e)
  33. }
  34. if u.Host == "" {
  35. return nil, fmt.Errorf("invalid endpoint %q: host empty", e)
  36. }
  37. urls[i] = *u
  38. }
  39. d := director{
  40. endpoints: urls,
  41. }
  42. return &d, nil
  43. }
  44. type director struct {
  45. endpoints []url.URL
  46. }
  47. func (d *director) direct(req *http.Request) {
  48. choice := d.endpoints[0]
  49. req.URL.Scheme = choice.Scheme
  50. req.URL.Host = choice.Host
  51. }