Test: frontend middleware
This commit is contained in:
parent
5d406f1c6a
commit
5ab93a6e0d
4 changed files with 146 additions and 159 deletions
|
@ -39,13 +39,13 @@ func FrontendFileHandler() gin.HandlerFunc {
|
||||||
path := c.Request.URL.Path
|
path := c.Request.URL.Path
|
||||||
|
|
||||||
// API 跳过
|
// API 跳过
|
||||||
if strings.HasPrefix(path, "/api") || strings.HasPrefix(path, "/custom") || strings.HasPrefix(path, "/custom") || path == "manifest.json" {
|
if strings.HasPrefix(path, "/api") || strings.HasPrefix(path, "/custom") || strings.HasPrefix(path, "/dav") || path == "/manifest.json" {
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 不存在的路径和index.html均返回index.html
|
// 不存在的路径和index.html均返回index.html
|
||||||
if !bootstrap.StaticFS.Exists("/", path) || (path == "/index.html") || (path == "/") {
|
if (path == "/index.html") || (path == "/") || !bootstrap.StaticFS.Exists("/", path) {
|
||||||
// 读取、替换站点设置
|
// 读取、替换站点设置
|
||||||
options := model.GetSettingByNames("siteName", "siteKeywords", "siteScript",
|
options := model.GetSettingByNames("siteName", "siteKeywords", "siteScript",
|
||||||
"pwa_small_icon")
|
"pwa_small_icon")
|
||||||
|
|
144
middleware/frontend_test.go
Normal file
144
middleware/frontend_test.go
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/cloudreve/Cloudreve/v3/bootstrap"
|
||||||
|
"github.com/cloudreve/Cloudreve/v3/pkg/cache"
|
||||||
|
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
testMock "github.com/stretchr/testify/mock"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StaticMock struct {
|
||||||
|
testMock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m StaticMock) Open(name string) (http.File, error) {
|
||||||
|
args := m.Called(name)
|
||||||
|
return args.Get(0).(http.File), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m StaticMock) Exists(prefix string, filepath string) bool {
|
||||||
|
args := m.Called(prefix, filepath)
|
||||||
|
return args.Bool(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFrontendFileHandler(t *testing.T) {
|
||||||
|
asserts := assert.New(t)
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
// 静态资源未加载
|
||||||
|
{
|
||||||
|
TestFunc := FrontendFileHandler()
|
||||||
|
|
||||||
|
c, _ := gin.CreateTestContext(rec)
|
||||||
|
c.Params = []gin.Param{}
|
||||||
|
c.Request, _ = http.NewRequest("GET", "/", nil)
|
||||||
|
TestFunc(c)
|
||||||
|
asserts.False(c.IsAborted())
|
||||||
|
}
|
||||||
|
|
||||||
|
// index.html 不存在
|
||||||
|
{
|
||||||
|
testStatic := &StaticMock{}
|
||||||
|
bootstrap.StaticFS = testStatic
|
||||||
|
testStatic.On("Open", "/index.html").
|
||||||
|
Return(&os.File{}, errors.New("error"))
|
||||||
|
TestFunc := FrontendFileHandler()
|
||||||
|
|
||||||
|
c, _ := gin.CreateTestContext(rec)
|
||||||
|
c.Params = []gin.Param{}
|
||||||
|
c.Request, _ = http.NewRequest("GET", "/", nil)
|
||||||
|
TestFunc(c)
|
||||||
|
asserts.False(c.IsAborted())
|
||||||
|
}
|
||||||
|
|
||||||
|
// index.html 读取失败
|
||||||
|
{
|
||||||
|
file, _ := util.CreatNestedFile("tests/index.html")
|
||||||
|
file.Close()
|
||||||
|
testStatic := &StaticMock{}
|
||||||
|
bootstrap.StaticFS = testStatic
|
||||||
|
testStatic.On("Open", "/index.html").
|
||||||
|
Return(file, nil)
|
||||||
|
TestFunc := FrontendFileHandler()
|
||||||
|
|
||||||
|
c, _ := gin.CreateTestContext(rec)
|
||||||
|
c.Params = []gin.Param{}
|
||||||
|
c.Request, _ = http.NewRequest("GET", "/", nil)
|
||||||
|
TestFunc(c)
|
||||||
|
asserts.False(c.IsAborted())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 成功且命中
|
||||||
|
{
|
||||||
|
file, _ := util.CreatNestedFile("tests/index.html")
|
||||||
|
defer file.Close()
|
||||||
|
testStatic := &StaticMock{}
|
||||||
|
bootstrap.StaticFS = testStatic
|
||||||
|
testStatic.On("Open", "/index.html").
|
||||||
|
Return(file, nil)
|
||||||
|
TestFunc := FrontendFileHandler()
|
||||||
|
|
||||||
|
c, _ := gin.CreateTestContext(rec)
|
||||||
|
c.Params = []gin.Param{}
|
||||||
|
c.Request, _ = http.NewRequest("GET", "/", nil)
|
||||||
|
|
||||||
|
cache.Set("setting_siteName", "cloudreve", 0)
|
||||||
|
cache.Set("setting_siteKeywords", "cloudreve", 0)
|
||||||
|
cache.Set("setting_siteScript", "cloudreve", 0)
|
||||||
|
cache.Set("setting_pwa_small_icon", "cloudreve", 0)
|
||||||
|
|
||||||
|
TestFunc(c)
|
||||||
|
asserts.True(c.IsAborted())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 成功且命中静态文件
|
||||||
|
{
|
||||||
|
file, _ := util.CreatNestedFile("tests/index.html")
|
||||||
|
defer file.Close()
|
||||||
|
testStatic := &StaticMock{}
|
||||||
|
bootstrap.StaticFS = testStatic
|
||||||
|
testStatic.On("Open", "/index.html").
|
||||||
|
Return(file, nil)
|
||||||
|
testStatic.On("Exists", "/", "/2").
|
||||||
|
Return(true)
|
||||||
|
testStatic.On("Open", "/2").
|
||||||
|
Return(file, nil)
|
||||||
|
TestFunc := FrontendFileHandler()
|
||||||
|
|
||||||
|
c, _ := gin.CreateTestContext(rec)
|
||||||
|
c.Params = []gin.Param{}
|
||||||
|
c.Request, _ = http.NewRequest("GET", "/2", nil)
|
||||||
|
|
||||||
|
TestFunc(c)
|
||||||
|
asserts.True(c.IsAborted())
|
||||||
|
testStatic.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// API 相关跳过
|
||||||
|
{
|
||||||
|
for _, reqPath := range []string{"/api/user", "/manifest.json", "/dav/path"} {
|
||||||
|
file, _ := util.CreatNestedFile("tests/index.html")
|
||||||
|
defer file.Close()
|
||||||
|
testStatic := &StaticMock{}
|
||||||
|
bootstrap.StaticFS = testStatic
|
||||||
|
testStatic.On("Open", "/index.html").
|
||||||
|
Return(file, nil)
|
||||||
|
TestFunc := FrontendFileHandler()
|
||||||
|
|
||||||
|
c, _ := gin.CreateTestContext(rec)
|
||||||
|
c.Params = []gin.Param{}
|
||||||
|
c.Request, _ = http.NewRequest("GET", reqPath, nil)
|
||||||
|
|
||||||
|
TestFunc(c)
|
||||||
|
asserts.False(c.IsAborted())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,13 +1,9 @@
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"github.com/cloudreve/Cloudreve/v3/bootstrap"
|
|
||||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/hashid"
|
"github.com/cloudreve/Cloudreve/v3/pkg/hashid"
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,47 +38,3 @@ func IsFunctionEnabled(key string) gin.HandlerFunc {
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InjectSiteInfo 向首页html中插入站点信息
|
|
||||||
func InjectSiteInfo() gin.HandlerFunc {
|
|
||||||
ignoreFunc := func(c *gin.Context) {
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
if bootstrap.StaticFS == nil {
|
|
||||||
return ignoreFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取index.html
|
|
||||||
file, err := bootstrap.StaticFS.Open("/index.html")
|
|
||||||
if err != nil {
|
|
||||||
util.Log().Warning("静态文件[index.html]不存在,可能会影响首页展示")
|
|
||||||
return ignoreFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
fileContentBytes, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
util.Log().Warning("静态文件[index.html]读取失败,可能会影响首页展示")
|
|
||||||
return ignoreFunc
|
|
||||||
}
|
|
||||||
fileContent := string(fileContentBytes)
|
|
||||||
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
if c.Request.URL.Path == "/" || c.Request.URL.Path == "/index.html" {
|
|
||||||
// 读取、替换站点设置
|
|
||||||
options := model.GetSettingByNames("siteName", "siteKeywords", "siteScript",
|
|
||||||
"pwa_small_icon")
|
|
||||||
finalHTML := util.Replace(map[string]string{
|
|
||||||
"{siteName}": options["siteName"],
|
|
||||||
"{siteDes}": options["siteDes"],
|
|
||||||
"{siteScript}": options["siteScript"],
|
|
||||||
"{pwa_small_icon}": options["pwa_small_icon"],
|
|
||||||
}, fileContent)
|
|
||||||
|
|
||||||
c.Header("Content-Type", "text/html")
|
|
||||||
c.String(200, finalHTML)
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/cloudreve/Cloudreve/v3/bootstrap"
|
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/cache"
|
"github.com/cloudreve/Cloudreve/v3/pkg/cache"
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/hashid"
|
"github.com/cloudreve/Cloudreve/v3/pkg/hashid"
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
testMock "github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHashID(t *testing.T) {
|
func TestHashID(t *testing.T) {
|
||||||
|
@ -81,107 +76,3 @@ func TestIsFunctionEnabled(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type StaticMock struct {
|
|
||||||
testMock.Mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m StaticMock) Open(name string) (http.File, error) {
|
|
||||||
args := m.Called(name)
|
|
||||||
return args.Get(0).(http.File), args.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m StaticMock) Exists(prefix string, filepath string) bool {
|
|
||||||
args := m.Called(prefix, filepath)
|
|
||||||
return args.Bool(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInjectSiteInfo(t *testing.T) {
|
|
||||||
asserts := assert.New(t)
|
|
||||||
rec := httptest.NewRecorder()
|
|
||||||
|
|
||||||
// 静态资源未加载
|
|
||||||
{
|
|
||||||
TestFunc := InjectSiteInfo()
|
|
||||||
|
|
||||||
c, _ := gin.CreateTestContext(rec)
|
|
||||||
c.Params = []gin.Param{}
|
|
||||||
c.Request, _ = http.NewRequest("GET", "/", nil)
|
|
||||||
TestFunc(c)
|
|
||||||
asserts.False(c.IsAborted())
|
|
||||||
}
|
|
||||||
|
|
||||||
// index.html 不存在
|
|
||||||
{
|
|
||||||
testStatic := &StaticMock{}
|
|
||||||
bootstrap.StaticFS = testStatic
|
|
||||||
testStatic.On("Open", "/index.html").
|
|
||||||
Return(&os.File{}, errors.New("error"))
|
|
||||||
TestFunc := InjectSiteInfo()
|
|
||||||
|
|
||||||
c, _ := gin.CreateTestContext(rec)
|
|
||||||
c.Params = []gin.Param{}
|
|
||||||
c.Request, _ = http.NewRequest("GET", "/", nil)
|
|
||||||
TestFunc(c)
|
|
||||||
asserts.False(c.IsAborted())
|
|
||||||
}
|
|
||||||
|
|
||||||
// index.html 读取失败
|
|
||||||
{
|
|
||||||
file, _ := util.CreatNestedFile("tests/index.html")
|
|
||||||
file.Close()
|
|
||||||
testStatic := &StaticMock{}
|
|
||||||
bootstrap.StaticFS = testStatic
|
|
||||||
testStatic.On("Open", "/index.html").
|
|
||||||
Return(file, nil)
|
|
||||||
TestFunc := InjectSiteInfo()
|
|
||||||
|
|
||||||
c, _ := gin.CreateTestContext(rec)
|
|
||||||
c.Params = []gin.Param{}
|
|
||||||
c.Request, _ = http.NewRequest("GET", "/", nil)
|
|
||||||
TestFunc(c)
|
|
||||||
asserts.False(c.IsAborted())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 成功且命中
|
|
||||||
{
|
|
||||||
file, _ := util.CreatNestedFile("tests/index.html")
|
|
||||||
defer file.Close()
|
|
||||||
testStatic := &StaticMock{}
|
|
||||||
bootstrap.StaticFS = testStatic
|
|
||||||
testStatic.On("Open", "/index.html").
|
|
||||||
Return(file, nil)
|
|
||||||
TestFunc := InjectSiteInfo()
|
|
||||||
|
|
||||||
c, _ := gin.CreateTestContext(rec)
|
|
||||||
c.Params = []gin.Param{}
|
|
||||||
c.Request, _ = http.NewRequest("GET", "/", nil)
|
|
||||||
|
|
||||||
cache.Set("setting_siteName", "cloudreve", 0)
|
|
||||||
cache.Set("setting_siteKeywords", "cloudreve", 0)
|
|
||||||
cache.Set("setting_siteScript", "cloudreve", 0)
|
|
||||||
cache.Set("setting_pwa_small_icon", "cloudreve", 0)
|
|
||||||
|
|
||||||
TestFunc(c)
|
|
||||||
asserts.True(c.IsAborted())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 成功且未命中
|
|
||||||
{
|
|
||||||
file, _ := util.CreatNestedFile("tests/index.html")
|
|
||||||
defer file.Close()
|
|
||||||
testStatic := &StaticMock{}
|
|
||||||
bootstrap.StaticFS = testStatic
|
|
||||||
testStatic.On("Open", "/index.html").
|
|
||||||
Return(file, nil)
|
|
||||||
TestFunc := InjectSiteInfo()
|
|
||||||
|
|
||||||
c, _ := gin.CreateTestContext(rec)
|
|
||||||
c.Params = []gin.Param{}
|
|
||||||
c.Request, _ = http.NewRequest("GET", "/2", nil)
|
|
||||||
|
|
||||||
TestFunc(c)
|
|
||||||
asserts.False(c.IsAborted())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue