log_page.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package nginx_log
  2. import (
  3. "io"
  4. "net/http"
  5. "os"
  6. "github.com/0xJacky/Nginx-UI/internal/translation"
  7. "github.com/gin-gonic/gin"
  8. "github.com/pkg/errors"
  9. "github.com/spf13/cast"
  10. "github.com/uozi-tech/cosy"
  11. "github.com/uozi-tech/cosy/logger"
  12. )
  13. // GetNginxLogPage handles retrieving a page of log content from a log file
  14. func GetNginxLogPage(c *gin.Context) {
  15. page := cast.ToInt64(c.Query("page"))
  16. if page < 0 {
  17. page = 0
  18. }
  19. var control controlStruct
  20. if !cosy.BindAndValid(c, &control) {
  21. return
  22. }
  23. logPath, err := getLogPath(&control)
  24. if err != nil {
  25. c.JSON(http.StatusInternalServerError, nginxLogPageResp{
  26. Error: translation.C(err.Error()),
  27. })
  28. logger.Error(err)
  29. return
  30. }
  31. logFileStat, err := os.Stat(logPath)
  32. if err != nil {
  33. c.JSON(http.StatusInternalServerError, nginxLogPageResp{
  34. Error: translation.C(err.Error()),
  35. })
  36. logger.Error(err)
  37. return
  38. }
  39. if !logFileStat.Mode().IsRegular() {
  40. c.JSON(http.StatusInternalServerError, nginxLogPageResp{
  41. Error: translation.C("Log file %{log_path} is not a regular file. "+
  42. "If you are using nginx-ui in docker container, please refer to "+
  43. "https://nginxui.com/zh_CN/guide/config-nginx-log.html for more information.",
  44. map[string]any{
  45. "log_path": logPath,
  46. }),
  47. })
  48. logger.Errorf("log file is not a regular file: %s", logPath)
  49. return
  50. }
  51. // to fix: seek invalid argument #674
  52. if logFileStat.Size() == 0 {
  53. c.JSON(http.StatusOK, nginxLogPageResp{
  54. Page: 1,
  55. Content: "",
  56. })
  57. return
  58. }
  59. f, err := os.Open(logPath)
  60. if err != nil {
  61. c.JSON(http.StatusInternalServerError, nginxLogPageResp{
  62. Error: translation.C(err.Error()),
  63. })
  64. logger.Error(err)
  65. return
  66. }
  67. defer f.Close()
  68. totalPage := logFileStat.Size() / PageSize
  69. if logFileStat.Size()%PageSize > 0 {
  70. totalPage++
  71. }
  72. var buf []byte
  73. var offset int64
  74. if page == 0 {
  75. page = totalPage
  76. }
  77. buf = make([]byte, PageSize)
  78. offset = (page - 1) * PageSize
  79. // seek to the correct position in the file
  80. _, err = f.Seek(offset, io.SeekStart)
  81. if err != nil && err != io.EOF {
  82. c.JSON(http.StatusInternalServerError, nginxLogPageResp{
  83. Error: translation.C(err.Error()),
  84. })
  85. logger.Error(err)
  86. return
  87. }
  88. n, err := f.Read(buf)
  89. if err != nil && !errors.Is(err, io.EOF) {
  90. c.JSON(http.StatusInternalServerError, nginxLogPageResp{
  91. Error: translation.C(err.Error()),
  92. })
  93. logger.Error(err)
  94. return
  95. }
  96. c.JSON(http.StatusOK, nginxLogPageResp{
  97. Page: page,
  98. Content: string(buf[:n]),
  99. })
  100. }