handler.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package desktop
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. _ "io/ioutil"
  7. "net/http"
  8. "net/http/httputil"
  9. "nginx-ui/server/config"
  10. "strings"
  11. )
  12. type ApiHandler struct {
  13. http.Handler
  14. ctx context.Context
  15. api *Api
  16. proxy *httputil.ReverseProxy
  17. handler http.Handler
  18. }
  19. func rewriteRequestURL(req *http.Request) {
  20. logger.Printf("req.URL: %s, method: %s", req.URL, req.Method)
  21. req.URL.Scheme = "http"
  22. req.URL.Host = fmt.Sprintf("localhost:%d", config.Config.Port)
  23. path := req.URL.Path
  24. path = strings.TrimPrefix(path, "/api")
  25. req.URL.Path = path
  26. logger.Printf("Loading '%s'", req.URL)
  27. }
  28. func NewApiHandler(baseHandler http.Handler) *ApiHandler {
  29. var proxy *httputil.ReverseProxy
  30. errSkipProxy := fmt.Errorf("skip proxying")
  31. proxy = httputil.NewSingleHostReverseProxy(nil)
  32. proxy.ModifyResponse = func(res *http.Response) error {
  33. if baseHandler == nil {
  34. return nil
  35. }
  36. if res.StatusCode == http.StatusSwitchingProtocols {
  37. return nil
  38. }
  39. if res.StatusCode == http.StatusNotFound || res.StatusCode == http.StatusMethodNotAllowed {
  40. return errSkipProxy
  41. }
  42. return nil
  43. }
  44. proxy.ErrorHandler = func(rw http.ResponseWriter, r *http.Request, err error) {
  45. if baseHandler != nil && errors.Is(err, errSkipProxy) {
  46. logger.Printf("'%s' returned not found, using AssetHandler", r.URL)
  47. baseHandler.ServeHTTP(rw, r)
  48. } else {
  49. logger.Printf("Proxy error: %v", err)
  50. rw.WriteHeader(http.StatusBadGateway)
  51. }
  52. }
  53. return &ApiHandler{
  54. api: NewApi(),
  55. proxy: proxy,
  56. handler: baseHandler,
  57. }
  58. }
  59. func (h *ApiHandler) Startup(ctx context.Context) {
  60. ApiSession.ctx = ctx
  61. h.ctx = ctx
  62. h.api.ctx = ctx
  63. }
  64. // 这也是一种方法,不过感觉比较复杂,需要自己处理请求参数之类的
  65. func (h *ApiHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
  66. h.proxy.Director = func(request *http.Request) {
  67. rewriteRequestURL(request)
  68. request.Body = req.Body
  69. }
  70. h.proxy.ServeHTTP(rw, req)
  71. }