util.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package controller
  2. import (
  3. "net"
  4. "net/http"
  5. "strings"
  6. "github.com/mhsanaei/3x-ui/v2/config"
  7. "github.com/mhsanaei/3x-ui/v2/logger"
  8. "github.com/mhsanaei/3x-ui/v2/web/entity"
  9. "github.com/gin-gonic/gin"
  10. )
  11. // getRemoteIp extracts the real IP address from the request headers or remote address.
  12. func getRemoteIp(c *gin.Context) string {
  13. value := c.GetHeader("X-Real-IP")
  14. if value != "" {
  15. return value
  16. }
  17. value = c.GetHeader("X-Forwarded-For")
  18. if value != "" {
  19. ips := strings.Split(value, ",")
  20. return ips[0]
  21. }
  22. addr := c.Request.RemoteAddr
  23. ip, _, _ := net.SplitHostPort(addr)
  24. return ip
  25. }
  26. // jsonMsg sends a JSON response with a message and error status.
  27. func jsonMsg(c *gin.Context, msg string, err error) {
  28. jsonMsgObj(c, msg, nil, err)
  29. }
  30. // jsonObj sends a JSON response with an object and error status.
  31. func jsonObj(c *gin.Context, obj any, err error) {
  32. jsonMsgObj(c, "", obj, err)
  33. }
  34. // jsonMsgObj sends a JSON response with a message, object, and error status.
  35. func jsonMsgObj(c *gin.Context, msg string, obj any, err error) {
  36. m := entity.Msg{
  37. Obj: obj,
  38. }
  39. if err == nil {
  40. m.Success = true
  41. if msg != "" {
  42. m.Msg = msg
  43. }
  44. } else {
  45. m.Success = false
  46. m.Msg = msg + " (" + err.Error() + ")"
  47. logger.Warning(msg+" "+I18nWeb(c, "fail")+": ", err)
  48. }
  49. c.JSON(http.StatusOK, m)
  50. }
  51. // pureJsonMsg sends a pure JSON message response with custom status code.
  52. func pureJsonMsg(c *gin.Context, statusCode int, success bool, msg string) {
  53. c.JSON(statusCode, entity.Msg{
  54. Success: success,
  55. Msg: msg,
  56. })
  57. }
  58. // html renders an HTML template with the provided data and title.
  59. func html(c *gin.Context, name string, title string, data gin.H) {
  60. if data == nil {
  61. data = gin.H{}
  62. }
  63. data["title"] = title
  64. host := c.GetHeader("X-Forwarded-Host")
  65. if host == "" {
  66. host = c.GetHeader("X-Real-IP")
  67. }
  68. if host == "" {
  69. var err error
  70. host, _, err = net.SplitHostPort(c.Request.Host)
  71. if err != nil {
  72. host = c.Request.Host
  73. }
  74. }
  75. data["host"] = host
  76. data["request_uri"] = c.Request.RequestURI
  77. data["base_path"] = c.GetString("base_path")
  78. c.HTML(http.StatusOK, name, getContext(data))
  79. }
  80. // getContext adds version and other context data to the provided gin.H.
  81. func getContext(h gin.H) gin.H {
  82. a := gin.H{
  83. "cur_ver": config.GetVersion(),
  84. }
  85. for key, value := range h {
  86. a[key] = value
  87. }
  88. return a
  89. }
  90. // isAjax checks if the request is an AJAX request.
  91. func isAjax(c *gin.Context) bool {
  92. return c.GetHeader("X-Requested-With") == "XMLHttpRequest"
  93. }