mirror of
https://github.com/truewhile/MeBox.git
synced 2026-11-12 19:34:24 +08:00
119 lines
3.7 KiB
Go
119 lines
3.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"bytes"
|
|
"image/color"
|
|
"image/jpeg"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/golang-jwt/jwt/v5"
|
|
"github.com/glebarez/sqlite"
|
|
"go.uber.org/zap"
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/truewhile/MeBox/internal/config"
|
|
"github.com/truewhile/MeBox/internal/middleware"
|
|
"github.com/truewhile/MeBox/internal/model"
|
|
"github.com/truewhile/MeBox/internal/repository"
|
|
"github.com/truewhile/MeBox/internal/service"
|
|
)
|
|
|
|
func coverTestToken(t *testing.T, secret, userID string) string {
|
|
t.Helper()
|
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, middleware.Claims{
|
|
UserID: userID,
|
|
Role: "admin",
|
|
RegisteredClaims: jwt.RegisteredClaims{
|
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),
|
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
|
Subject: userID,
|
|
},
|
|
})
|
|
signed, err := token.SignedString([]byte(secret))
|
|
if err != nil {
|
|
t.Fatalf("sign token: %v", err)
|
|
}
|
|
return signed
|
|
}
|
|
|
|
// TestLibraryCoverRouteServesImageThroughFullRouter 走完整的 handler.Register
|
|
// 路由表请求封面:既验证路由挂载正确,也验证鉴权链(AuthRequired +
|
|
// activeUserRequired)不会把它挡成 404。
|
|
func TestLibraryCoverRouteServesImageThroughFullRouter(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
const secret = "test-secret"
|
|
|
|
poster := coverTestJPEG(t, color.RGBA{R: 200, G: 120, B: 60, A: 255})
|
|
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "image/jpeg")
|
|
_, _ = w.Write(poster)
|
|
}))
|
|
defer upstream.Close()
|
|
parsed, _ := url.Parse(upstream.URL)
|
|
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open db: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&model.Library{}, &model.Media{}, &model.User{}); err != nil {
|
|
t.Fatalf("migrate: %v", err)
|
|
}
|
|
repos := repository.New(db)
|
|
user := model.User{Base: model.Base{ID: "user-1"}, Username: "viewer", IsActive: true}
|
|
if err := db.Create(&user).Error; err != nil {
|
|
t.Fatalf("create user: %v", err)
|
|
}
|
|
lib := model.Library{Name: "电影", Path: "/media/movies", Type: "movie", Enabled: true}
|
|
if err := repos.Library.Create(t.Context(), &lib); err != nil {
|
|
t.Fatalf("create library: %v", err)
|
|
}
|
|
for i := 0; i < 4; i++ {
|
|
row := model.Media{
|
|
Base: model.Base{ID: "m" + string(rune('a'+i))},
|
|
LibraryID: lib.ID,
|
|
Title: "Movie " + string(rune('A'+i)),
|
|
Path: "/media/movies/m" + string(rune('a'+i)) + ".mkv",
|
|
PosterURL: upstream.URL + "/p" + string(rune('1'+i)) + ".jpg",
|
|
}
|
|
if err := db.Create(&row).Error; err != nil {
|
|
t.Fatalf("create media: %v", err)
|
|
}
|
|
}
|
|
|
|
cfg := &config.Config{
|
|
Cache: config.CacheConfig{CacheDir: filepath.Join(t.TempDir(), "cache")},
|
|
Secrets: config.SecretsConfig{JWTSecret: secret},
|
|
}
|
|
proxy := service.NewImageProxy(cfg, zap.NewNop())
|
|
proxy.SetAllowedRemoteHostsProvider(func() []string { return []string{parsed.Host} })
|
|
svc := &service.Container{Repo: repos, ImageProxy: proxy}
|
|
|
|
engine := gin.New()
|
|
Register(engine, cfg, zap.NewNop(), svc)
|
|
|
|
token := coverTestToken(t, secret, user.ID)
|
|
req := httptest.NewRequest(http.MethodGet, "/api/libraries/"+lib.ID+"/cover?w=480&h=270&api_key="+token, nil)
|
|
w := httptest.NewRecorder()
|
|
engine.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("status = %d body=%s", w.Code, w.Body.String())
|
|
}
|
|
if ct := w.Header().Get("Content-Type"); ct != "image/jpeg" {
|
|
t.Fatalf("content type = %q, want image/jpeg", ct)
|
|
}
|
|
img, err := jpeg.Decode(bytes.NewReader(w.Body.Bytes()))
|
|
if err != nil {
|
|
t.Fatalf("decode cover: %v", err)
|
|
}
|
|
if img.Bounds().Dx() != 480 || img.Bounds().Dy() != 270 {
|
|
t.Fatalf("cover size = %v, want 480x270", img.Bounds())
|
|
}
|
|
}
|