server.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gin-contrib/gzip"
  5. "github.com/gin-gonic/gin"
  6. "github.com/yhat/wsutil"
  7. "net/http"
  8. "net/http/httputil"
  9. "net/url"
  10. "os"
  11. "path"
  12. "strings"
  13. )
  14. var ServerEngine *gin.Engine
  15. var StaticFileSystem http.FileSystem
  16. var FileServer http.Handler
  17. var ReverseProxyRemote *url.URL
  18. func StartServer() {
  19. ErrorLog.Emit(LogLv_INFO, "Server", "HTTP Server Starting...")
  20. ServerEngine = gin.New()
  21. if ConfigData.CommonConfig.IsDebugModeOn {
  22. gin.SetMode(gin.DebugMode)
  23. } else {
  24. gin.SetMode(gin.ReleaseMode)
  25. }
  26. if ConfigData.CommonConfig.UseGZip {
  27. ServerEngine.Use(gzip.Gzip(gzip.DefaultCompression))
  28. }
  29. ServerEngine.Use(CustomRecoveryMidware(ErrorLog, ConfigData.CommonConfig.IsDebugModeOn))
  30. ServerEngine.Use(CustomAccessLogMidware(AccessLog, ErrorLog))
  31. ErrorLog.Emit(LogLv_INFO, "Server", "Loading URL Router...")
  32. StaticFileSystem = http.Dir(WWWRootPath)
  33. FileServer = http.FileServer(StaticFileSystem)
  34. var err error
  35. if ConfigData.CommonConfig.IsBackendProxyEnable {
  36. ReverseProxyRemote, err = url.Parse(BackendTarget)
  37. if err != nil {
  38. emsg := fmt.Sprintf("Fatal Error! Backend Proxy URL Error: %s", err.Error())
  39. ErrorLog.Emit(LogLv_FATAL, "Server", emsg)
  40. fmt.Println(emsg)
  41. }
  42. }
  43. ServerEngine.Any("/*reqpath", FrontendRouter)
  44. ErrorLog.Emit(LogLv_INFO, "Server", "Start Listening...")
  45. err = ServerEngine.Run(ListenAddress)
  46. if err != nil {
  47. emsg := fmt.Sprintf("Fatal Error! Server Couldn't Start: %s", err.Error())
  48. ErrorLog.Emit(LogLv_FATAL, "Server", emsg)
  49. fmt.Println(emsg)
  50. }
  51. ErrorLog.Emit(LogLv_INFO, "Server", "Server Ready.")
  52. }
  53. func FrontendRouter(ctx *gin.Context) {
  54. rpath := ctx.Param("reqpath")
  55. if strings.HasPrefix(rpath, "/"+BackendPrefix) {
  56. APIReverseProxy(ctx)
  57. } else {
  58. StaticFilesHandler(rpath, ctx)
  59. }
  60. }
  61. func NotFoundHandler(ctx *gin.Context) {
  62. if ConfigData.CommonConfig.RedirectWhen404 {
  63. ctx.Redirect(302, ConfigData.CommonConfig.RedirectURL)
  64. } else {
  65. ctx.Writer.WriteString("404 not found")
  66. ctx.Status(404)
  67. }
  68. }
  69. func ForbiddenHandler(ctx *gin.Context) {
  70. ctx.Writer.WriteString("403 forbidden")
  71. ctx.Status(403)
  72. }
  73. func StaticFilesHandler(url string, ctx *gin.Context) {
  74. finf, err := StaticFileSystem.Open(path.Clean(url))
  75. if os.IsNotExist(err) {
  76. if ConfigData.CommonConfig.VueHistoryMode {
  77. VueHistoryModeHandler(ctx)
  78. return
  79. } else {
  80. NotFoundHandler(ctx)
  81. return
  82. }
  83. }
  84. fst, err := finf.Stat()
  85. if err != nil {
  86. if ConfigData.CommonConfig.VueHistoryMode {
  87. VueHistoryModeHandler(ctx)
  88. return
  89. } else {
  90. NotFoundHandler(ctx)
  91. return
  92. }
  93. }
  94. if fst.IsDir() {
  95. _, err := StaticFileSystem.Open(path.Clean(path.Join(url, "index.html")))
  96. if os.IsNotExist(err) {
  97. if ConfigData.CommonConfig.VueHistoryMode {
  98. VueHistoryModeHandler(ctx)
  99. return
  100. } else {
  101. ForbiddenHandler(ctx)
  102. return
  103. }
  104. }
  105. }
  106. ctx.Request.URL.Path = url
  107. FileServer.ServeHTTP(ctx.Writer, ctx.Request)
  108. }
  109. func VueHistoryModeHandler(ctx *gin.Context) {
  110. http.ServeFile(ctx.Writer, ctx.Request, path.Join(WWWRootPath, "index.html"))
  111. }
  112. func APIReverseProxy(context *gin.Context) {
  113. if !ConfigData.CommonConfig.IsBackendProxyEnable {
  114. NotFoundHandler(context)
  115. }
  116. if context.IsWebsocket() {
  117. proxy := wsutil.NewSingleHostReverseProxy(ReverseProxyRemote)
  118. proxy.ServeHTTP(context.Writer, context.Request)
  119. } else {
  120. proxy := httputil.NewSingleHostReverseProxy(ReverseProxyRemote)
  121. proxy.ServeHTTP(context.Writer, context.Request)
  122. }
  123. }