mirror of
https://github.com/truewhile/MeBox.git
synced 2026-11-15 20:34:23 +08:00
优化
This commit is contained in:
@@ -73,13 +73,26 @@ func playbackInfoHandler(svc *service.Container) gin.HandlerFunc {
|
||||
subtitles = discovered
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
// 能在服务端换链就把最终直链一并返回:客户端直接连 CDN,省掉
|
||||
// /api/stream 的 302 往返。跨境/高延迟链路上,这一跳等于一次完整的
|
||||
// DNS + TCP + TLS,实测能到数秒,正好压在起播关键路径上。
|
||||
// 换链失败、本地文件或需要服务端加头的网盘保持原样,客户端仍走
|
||||
// stream_url 跳转,行为与改动前一致。
|
||||
directURL, hasDirectURL := "", false
|
||||
if svc.Stream != nil {
|
||||
directURL, hasDirectURL = svc.Stream.ResolveDirectPlayURL(c.Request, m)
|
||||
}
|
||||
payload := gin.H{
|
||||
"media": m,
|
||||
"stream_url": "/api/stream/" + m.ID + "?token=" + url.QueryEscape(token) + profileQuery,
|
||||
"hls_url": hlsURL,
|
||||
"resume": resumePayload,
|
||||
"subtitles": subtitles,
|
||||
})
|
||||
}
|
||||
if hasDirectURL {
|
||||
payload["direct_url"] = directURL
|
||||
}
|
||||
c.JSON(http.StatusOK, payload)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/truewhile/MeBox/internal/model"
|
||||
"github.com/truewhile/MeBox/internal/repository"
|
||||
"github.com/truewhile/MeBox/internal/service"
|
||||
"github.com/truewhile/MeBox/internal/service/cloud"
|
||||
)
|
||||
|
||||
func TestExternalURLUsesMediaScopedPlaybackToken(t *testing.T) {
|
||||
@@ -457,6 +458,60 @@ func TestPlaybackInfoForSTRMMediaIncludesHLS(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// 服务端能换到最终直链时,播放地址响应要把直链一并给客户端:移动端起播就能
|
||||
// 跳过 /api/stream 的 302 往返(跨境链路上等于一次完整 DNS+TCP+TLS)。
|
||||
func TestPlaybackInfoCarriesPrefetchedDirectURL(t *testing.T) {
|
||||
router, svc, secret := newPlaybackScopeTestRouter(t)
|
||||
loginToken := signedTestToken(t, secret)
|
||||
const direct = "https://cdnfhnfile.115cdn.net/637b/Movie.mkv?t=1&k=sig"
|
||||
var gotUA string
|
||||
svc.Stream.SetStrmPlayTargetResolver(func(_ context.Context, _, userAgent string) (*service.StrmPlayResult, error) {
|
||||
gotUA = userAgent
|
||||
return &service.StrmPlayResult{
|
||||
RedirectURL: direct,
|
||||
Link: &cloud.DirectLink{URL: direct, Headers: map[string]string{"User-Agent": userAgent}},
|
||||
}, nil
|
||||
})
|
||||
if err := svc.Repo.DB.Create(&model.Media{
|
||||
Base: model.Base{ID: "media-direct"},
|
||||
LibraryID: "lib-1",
|
||||
Title: "Direct",
|
||||
Path: "cloud://cloud115/Movie.mkv",
|
||||
Container: "strm",
|
||||
DurationSec: 3600,
|
||||
STRMURL: "/api/strm/play/cloud115/video.mkv?acct=a1&pickcode=pc1",
|
||||
}).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "http://nas.local/api/playback/media-direct/info", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+loginToken)
|
||||
req.Header.Set("User-Agent", "MeBox-Android/0.1.0")
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d body=%s", w.Code, w.Body.String())
|
||||
}
|
||||
var payload struct {
|
||||
DirectURL string `json:"direct_url"`
|
||||
StreamURL string `json:"stream_url"`
|
||||
}
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &payload); err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
if payload.DirectURL != direct {
|
||||
t.Fatalf("direct_url = %q, want %q (body=%s)", payload.DirectURL, direct, w.Body.String())
|
||||
}
|
||||
if !strings.Contains(payload.StreamURL, "/api/stream/media-direct") {
|
||||
t.Fatalf("stream_url must stay as the fallback, got %q", payload.StreamURL)
|
||||
}
|
||||
// 115 直链绑定换取时的 UA:预置直链必须按播放器的 UA 换,否则播放会 403。
|
||||
if gotUA != "MeBox-Android/0.1.0" {
|
||||
t.Fatalf("resolver UA = %q, want the client UA", gotUA)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubtitleListOnlyProbesEmbeddedTracksForHLS(t *testing.T) {
|
||||
router, svc, secret := newPlaybackScopeTestRouter(t)
|
||||
loginToken := signedTestToken(t, secret)
|
||||
|
||||
Reference in New Issue
Block a user