server.go 2.8 KB

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