mirror of
https://git.fightbot.fun/hxuanyu/BingPaper.git
synced 2026-02-15 05:59:32 +08:00
新增单元测试验证图片重定向逻辑,优化前端预览链接样式,调整依赖配置
This commit is contained in:
4
go.mod
4
go.mod
@@ -10,6 +10,7 @@ require (
|
||||
github.com/glebarez/sqlite v1.11.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/studio-b12/gowebdav v0.12.0
|
||||
github.com/swaggo/files v1.0.1
|
||||
github.com/swaggo/gin-swagger v1.6.1
|
||||
@@ -29,6 +30,7 @@ require (
|
||||
github.com/bytedance/sonic v1.14.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
@@ -61,6 +63,7 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/quic-go v0.54.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
@@ -85,6 +88,7 @@ require (
|
||||
golang.org/x/tools v0.40.0 // indirect
|
||||
google.golang.org/protobuf v1.36.9 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.22.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.5.0 // indirect
|
||||
|
||||
@@ -172,9 +172,11 @@ func handleImageResponse(c *gin.Context, img *model.Image) {
|
||||
if mode == "redirect" {
|
||||
if selected.PublicURL != "" {
|
||||
c.Redirect(http.StatusFound, selected.PublicURL)
|
||||
} else if img.URLBase != "" {
|
||||
// 兜底重定向到原始 Bing
|
||||
bingURL := fmt.Sprintf("https://www.bing.com%s_%s.jpg", img.URLBase, selected.Variant)
|
||||
c.Redirect(http.StatusFound, bingURL)
|
||||
} else {
|
||||
// 兜底重定向到原始 Bing (如果可能,但由于 URLBase 只有一部分,这里可能不工作)
|
||||
// 这里我们更倾向于 local 转发,如果 PublicURL 为空
|
||||
serveLocal(c, selected.StorageKey)
|
||||
}
|
||||
} else {
|
||||
@@ -201,7 +203,9 @@ func formatMeta(img *model.Image) gin.H {
|
||||
variants := []gin.H{}
|
||||
for _, v := range img.Variants {
|
||||
url := v.PublicURL
|
||||
if cfg.API.Mode == "local" || url == "" {
|
||||
if url == "" && cfg.API.Mode == "redirect" && img.URLBase != "" {
|
||||
url = fmt.Sprintf("https://www.bing.com%s_%s.jpg", img.URLBase, v.Variant)
|
||||
} else if cfg.API.Mode == "local" || url == "" {
|
||||
url = fmt.Sprintf("%s/api/v1/image/date/%s?variant=%s&format=%s", cfg.Server.BaseURL, img.Date, v.Variant, v.Format)
|
||||
}
|
||||
variants = append(variants, gin.H{
|
||||
|
||||
68
internal/http/handlers/image_test.go
Normal file
68
internal/http/handlers/image_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"BingPaper/internal/config"
|
||||
"BingPaper/internal/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestHandleImageResponseRedirect(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
// Setup config
|
||||
err := config.Init("")
|
||||
assert.NoError(t, err)
|
||||
config.GetConfig().API.Mode = "redirect"
|
||||
|
||||
// Mock Image and Variant
|
||||
img := &model.Image{
|
||||
Date: "2026-01-26",
|
||||
URLBase: "/th?id=OHR.TestImage",
|
||||
Variants: []model.ImageVariant{
|
||||
{
|
||||
Variant: "UHD",
|
||||
Format: "jpg",
|
||||
PublicURL: "", // Empty for local storage simulation
|
||||
StorageKey: "2026-01-26/2026-01-26_UHD.jpg",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("Redirect mode with empty PublicURL should redirect to Bing", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request, _ = http.NewRequest("GET", "/api/v1/image/today?variant=UHD", nil)
|
||||
|
||||
handleImageResponse(c, img)
|
||||
|
||||
assert.Equal(t, http.StatusFound, w.Code)
|
||||
assert.Contains(t, w.Header().Get("Location"), "bing.com")
|
||||
assert.Contains(t, w.Header().Get("Location"), "UHD")
|
||||
})
|
||||
|
||||
t.Run("FormatMeta in redirect mode should return Bing URL if PublicURL is empty", func(t *testing.T) {
|
||||
config.GetConfig().API.Mode = "redirect"
|
||||
meta := formatMeta(img)
|
||||
|
||||
variants := meta["variants"].([]gin.H)
|
||||
assert.Equal(t, 1, len(variants))
|
||||
assert.Contains(t, variants[0]["url"].(string), "bing.com")
|
||||
assert.Contains(t, variants[0]["url"].(string), "UHD")
|
||||
})
|
||||
|
||||
t.Run("FormatMeta in local mode should return API URL", func(t *testing.T) {
|
||||
config.GetConfig().API.Mode = "local"
|
||||
config.GetConfig().Server.BaseURL = "http://myserver.com"
|
||||
meta := formatMeta(img)
|
||||
|
||||
variants := meta["variants"].([]gin.H)
|
||||
assert.Equal(t, 1, len(variants))
|
||||
assert.Contains(t, variants[0]["url"].(string), "myserver.com")
|
||||
assert.Contains(t, variants[0]["url"].(string), "/api/v1/image/date/")
|
||||
})
|
||||
}
|
||||
@@ -38,6 +38,21 @@
|
||||
|
||||
/* Info Section */
|
||||
.info-card { background: var(--card-bg); padding: 2rem; border-radius: 12px; margin-bottom: 2rem; box-shadow: 0 2px 10px rgba(0,0,0,0.05); }
|
||||
.info-card ul { list-style: none; padding: 0; }
|
||||
.info-card li { margin-bottom: 12px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
||||
.preview-link {
|
||||
text-decoration: none;
|
||||
color: var(--primary-color);
|
||||
font-size: 0.85rem;
|
||||
padding: 2px 8px;
|
||||
border: 1px solid var(--primary-color);
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.preview-link:hover {
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
code { background: #f1f1f1; padding: 2px 5px; border-radius: 4px; color: #e83e8c; }
|
||||
pre { background: #f1f1f1; padding: 1rem; border-radius: 8px; overflow-x: auto; }
|
||||
|
||||
@@ -82,10 +97,10 @@
|
||||
<h2>使用说明</h2>
|
||||
<p>这是一个自动抓取必应每日一图并提供多分辨率管理的工具。您可以直接通过以下接口获取图片:</p>
|
||||
<ul>
|
||||
<li>今日图片:<code>/api/v1/image/today</code></li>
|
||||
<li>今日元数据:<code>/api/v1/image/today/meta</code></li>
|
||||
<li>随机图片:<code>/api/v1/image/random</code></li>
|
||||
<li>指定日期:<code>/api/v1/image/date/2026-01-26</code></li>
|
||||
<li><span>今日图片:</span><code>/api/v1/image/today</code> <a href="/api/v1/image/today" target="_blank" class="preview-link">立即预览</a></li>
|
||||
<li><span>今日元数据:</span><code>/api/v1/image/today/meta</code> <a href="/api/v1/image/today/meta" target="_blank" class="preview-link">立即预览</a></li>
|
||||
<li><span>随机图片:</span><code>/api/v1/image/random</code> <a href="/api/v1/image/random" target="_blank" class="preview-link">立即预览</a></li>
|
||||
<li><span>指定日期:</span><code>/api/v1/image/date/2026-01-26</code> <a href="/api/v1/image/date/2026-01-26" target="_blank" class="preview-link">立即预览</a></li>
|
||||
</ul>
|
||||
<p>参数支持:<code>variant=UHD|1920x1080|1366x768</code>,<code>format=jpg</code>。</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user