proxy.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package middleware
  2. import (
  3. "crypto/tls"
  4. "github.com/0xJacky/Nginx-UI/internal/logger"
  5. "github.com/0xJacky/Nginx-UI/query"
  6. "github.com/0xJacky/Nginx-UI/settings"
  7. "github.com/gin-gonic/gin"
  8. "github.com/spf13/cast"
  9. "io"
  10. "net/http"
  11. "net/url"
  12. )
  13. func Proxy() gin.HandlerFunc {
  14. return func(c *gin.Context) {
  15. nodeID, ok := c.Get("ProxyNodeID")
  16. if !ok {
  17. c.Next()
  18. return
  19. }
  20. id := cast.ToInt(nodeID)
  21. if id == 0 {
  22. c.Next()
  23. return
  24. }
  25. defer c.Abort()
  26. env := query.Environment
  27. environment, err := env.Where(env.ID.Eq(id)).First()
  28. if err != nil {
  29. logger.Error(err)
  30. c.AbortWithStatusJSON(http.StatusServiceUnavailable, gin.H{
  31. "message": err.Error(),
  32. })
  33. return
  34. }
  35. baseUrl, err := url.Parse(environment.URL)
  36. if err != nil {
  37. logger.Error(err)
  38. c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
  39. "message": err.Error(),
  40. })
  41. return
  42. }
  43. proxyUrl, err := baseUrl.Parse(c.Request.RequestURI)
  44. if err != nil {
  45. logger.Error(err)
  46. c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
  47. "message": err.Error(),
  48. })
  49. return
  50. }
  51. logger.Debug("Proxy request", proxyUrl.String())
  52. client := http.Client{
  53. Transport: &http.Transport{
  54. TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
  55. },
  56. }
  57. req, err := http.NewRequest(c.Request.Method, proxyUrl.String(), c.Request.Body)
  58. if err != nil {
  59. logger.Error(err)
  60. c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
  61. "message": err.Error(),
  62. })
  63. return
  64. }
  65. req.Header.Set("X-Node-Secret", environment.Token)
  66. resp, err := client.Do(req)
  67. if err != nil {
  68. logger.Error(err)
  69. c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
  70. "message": err.Error(),
  71. })
  72. return
  73. }
  74. defer resp.Body.Close()
  75. // rewrite status code to fix https://github.com/0xJacky/nginx-ui/issues/342
  76. if resp.StatusCode == http.StatusForbidden {
  77. resp.StatusCode = http.StatusServiceUnavailable
  78. }
  79. c.Writer.WriteHeader(resp.StatusCode)
  80. c.Writer.Header().Add("Content-Type", resp.Header.Get("Content-Type"))
  81. _, err = io.Copy(c.Writer, resp.Body)
  82. if err != nil {
  83. logger.Error(err)
  84. return
  85. }
  86. }
  87. }