Bladeren bron

Cache javascripts in browser

0xJacky 3 jaren geleden
bovenliggende
commit
77dfd64445
5 gewijzigde bestanden met toevoegingen van 117 en 81 verwijderingen
  1. 2 2
      .air.toml
  2. 1 1
      .github/workflows/build.yml
  3. 30 0
      server/router/middleware.go
  4. 80 78
      server/router/routers.go
  5. 4 0
      server/settings/settings.go

+ 2 - 2
.air.toml

@@ -7,7 +7,7 @@ tmp_dir = "tmp"
 
 [build]
 # Just plain old shell command. You could use `make` as well.
-cmd = "go build -o ./tmp/main ."
+cmd = "go build -ldflags=\"-X 'github.com/0xJacky/Nginx-UI/server/settings.BuildTime=$(date +%Y.%m.%d.%H%M%S)'\" -o ./tmp/main ."
 # Binary file yields from `cmd`.
 bin = "tmp/main"
 # Customize binary.
@@ -50,4 +50,4 @@ runner = "green"
 
 [misc]
 # Delete tmp directory on exit
-clean_on_exit = true
+clean_on_exit = true

+ 1 - 1
.github/workflows/build.yml

@@ -151,7 +151,7 @@ jobs:
             - name: Build
               run: |
                   mkdir -p dist
-                  go build -ldflags "$LD_FLAGS" -o dist/nginx-ui -v main.go
+                  go build -ldflags "$LD_FLAGS -X 'github.com/0xJacky/Nginx-UI/server/settings.BuildTime=$(date +%Y.%m.%d.%H%M%S)'" -o dist/nginx-ui -v main.go
 
             - name: Archive backend artifacts
               uses: actions/upload-artifact@v2

+ 30 - 0
server/router/middleware.go

@@ -4,14 +4,29 @@ import (
 	"encoding/base64"
 	"github.com/0xJacky/Nginx-UI/frontend"
 	"github.com/0xJacky/Nginx-UI/server/model"
+	"github.com/0xJacky/Nginx-UI/server/settings"
 	"github.com/gin-contrib/static"
 	"github.com/gin-gonic/gin"
 	"io/fs"
 	"log"
 	"net/http"
 	"path"
+	"strings"
+	"time"
 )
 
+func recovery() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		defer func() {
+			if err := recover(); err != nil {
+				log.Println(err)
+			}
+		}()
+
+		c.Next()
+	}
+}
+
 func authRequired() gin.HandlerFunc {
 	return func(c *gin.Context) {
 		token := c.GetHeader("Authorization")
@@ -64,3 +79,18 @@ func mustFS(dir string) (serverFileSystem static.ServeFileSystem) {
 
 	return
 }
+
+func cacheJs() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		if strings.Contains(c.Request.URL.String(), "js") {
+			c.Header("Cache-Control", "max-age: 1296000")
+			t, _ := time.Parse("2006.01.02.150405", settings.BuildTime)
+			t = t.Add(-8 * time.Hour)
+			lastModified := strings.ReplaceAll(t.Format(time.RFC1123), "UTC", "GMT")
+			if c.Request.Header.Get("If-Modified-Since") == lastModified {
+				c.AbortWithStatus(http.StatusNotModified)
+			}
+			c.Header("Last-Modified", lastModified)
+		}
+	}
+}

+ 80 - 78
server/router/routers.go

@@ -1,85 +1,87 @@
 package router
 
 import (
-    "bufio"
-    "github.com/0xJacky/Nginx-UI/server/api"
-    "github.com/0xJacky/Nginx-UI/server/settings"
-    "github.com/gin-contrib/static"
-    "github.com/gin-gonic/gin"
-    "net/http"
-    "strings"
+	"bufio"
+	"github.com/0xJacky/Nginx-UI/server/api"
+	"github.com/0xJacky/Nginx-UI/server/settings"
+	"github.com/gin-contrib/static"
+	"github.com/gin-gonic/gin"
+	"net/http"
+	"strings"
 )
 
 func InitRouter() *gin.Engine {
-    r := gin.New()
-    r.Use(gin.Logger())
-
-    r.Use(gin.Recovery())
-
-    r.Use(static.Serve("/", mustFS("")))
-
-    r.NoRoute(func(c *gin.Context) {
-        accept := c.Request.Header.Get("Accept")
-        if strings.Contains(accept, "text/html") {
-            file, _ := mustFS("").Open("index.html")
-            stat, _ := file.Stat()
-            c.DataFromReader(http.StatusOK, stat.Size(), "text/html",
-                bufio.NewReader(file), nil)
-        }
-    })
-
-    g := r.Group("/api")
-    {
-
-        g.GET("settings", func(c *gin.Context) {
-            c.JSON(http.StatusOK, gin.H{
-                "demo": settings.ServerSettings.Demo,
-            })
-        })
-
-        g.GET("install", api.InstallLockCheck)
-        g.POST("install", api.InstallNginxUI)
-
-        g.POST("/login", api.Login)
-        g.DELETE("/logout", api.Logout)
-
-        g := g.Group("/", authRequired())
-        {
-            g.GET("/analytic", api.Analytic)
-            g.GET("/analytic/init", api.GetAnalyticInit)
-
-            g.GET("/users", api.GetUsers)
-            g.GET("/user/:id", api.GetUser)
-            g.POST("/user", api.AddUser)
-            g.POST("/user/:id", api.EditUser)
-            g.DELETE("/user/:id", api.DeleteUser)
-
-            g.GET("domains", api.GetDomains)
-            g.GET("domain/:name", api.GetDomain)
-            g.POST("domain/:name", api.EditDomain)
-            g.POST("domain/:name/enable", api.EnableDomain)
-            g.POST("domain/:name/disable", api.DisableDomain)
-            g.DELETE("domain/:name", api.DeleteDomain)
-
-            g.GET("configs", api.GetConfigs)
-            g.GET("config/:name", api.GetConfig)
-            g.POST("config", api.AddConfig)
-            g.POST("config/:name", api.EditConfig)
-
-            g.GET("backups", api.GetFileBackupList)
-            g.GET("backup/:id", api.GetFileBackup)
-
-            g.GET("template/:name", api.GetTemplate)
-
-            g.GET("cert/issue/:domain", api.IssueCert)
-            g.GET("cert/:domain/info", api.CertInfo)
-
-            // 添加域名到自动续期列表
-            g.POST("cert/:domain", api.AddDomainToAutoCert)
-            // 从自动续期列表中删除域名
-            g.DELETE("cert/:domain", api.RemoveDomainFromAutoCert)
-        }
-    }
-
-    return r
+	r := gin.New()
+	r.Use(gin.Logger())
+
+	r.Use(recovery())
+
+	r.Use(cacheJs())
+
+	r.Use(static.Serve("/", mustFS("")))
+
+	r.NoRoute(func(c *gin.Context) {
+		accept := c.Request.Header.Get("Accept")
+		if strings.Contains(accept, "text/html") {
+			file, _ := mustFS("").Open("index.html")
+			stat, _ := file.Stat()
+			c.DataFromReader(http.StatusOK, stat.Size(), "text/html",
+				bufio.NewReader(file), nil)
+		}
+	})
+
+	g := r.Group("/api")
+	{
+
+		g.GET("settings", func(c *gin.Context) {
+			c.JSON(http.StatusOK, gin.H{
+				"demo": settings.ServerSettings.Demo,
+			})
+		})
+
+		g.GET("install", api.InstallLockCheck)
+		g.POST("install", api.InstallNginxUI)
+
+		g.POST("/login", api.Login)
+		g.DELETE("/logout", api.Logout)
+
+		g := g.Group("/", authRequired())
+		{
+			g.GET("/analytic", api.Analytic)
+			g.GET("/analytic/init", api.GetAnalyticInit)
+
+			g.GET("/users", api.GetUsers)
+			g.GET("/user/:id", api.GetUser)
+			g.POST("/user", api.AddUser)
+			g.POST("/user/:id", api.EditUser)
+			g.DELETE("/user/:id", api.DeleteUser)
+
+			g.GET("domains", api.GetDomains)
+			g.GET("domain/:name", api.GetDomain)
+			g.POST("domain/:name", api.EditDomain)
+			g.POST("domain/:name/enable", api.EnableDomain)
+			g.POST("domain/:name/disable", api.DisableDomain)
+			g.DELETE("domain/:name", api.DeleteDomain)
+
+			g.GET("configs", api.GetConfigs)
+			g.GET("config/:name", api.GetConfig)
+			g.POST("config", api.AddConfig)
+			g.POST("config/:name", api.EditConfig)
+
+			g.GET("backups", api.GetFileBackupList)
+			g.GET("backup/:id", api.GetFileBackup)
+
+			g.GET("template/:name", api.GetTemplate)
+
+			g.GET("cert/issue/:domain", api.IssueCert)
+			g.GET("cert/:domain/info", api.CertInfo)
+
+			// 添加域名到自动续期列表
+			g.POST("cert/:domain", api.AddDomainToAutoCert)
+			// 从自动续期列表中删除域名
+			g.DELETE("cert/:domain", api.RemoveDomainFromAutoCert)
+		}
+	}
+
+	return r
 }

+ 4 - 0
server/settings/settings.go

@@ -7,6 +7,10 @@ import (
 
 var Conf *ini.File
 
+var (
+	BuildTime string
+)
+
 type Server struct {
 	HttpPort          string
 	RunMode           string