回退 HTTPS 与无 cookie 拉流改动:放弃 HTTPS 方案,iPhone 播放改用夸克系统解码;仅保留 *.tar.gz 与 _*.py 的 gitignore 卫生规则

This commit is contained in:
yvan
2026-09-18 11:30:23 +08:00
parent 67bb1d01c8
commit 53c87872fc
7 changed files with 2 additions and 59 deletions
-2
View File
@@ -21,5 +21,3 @@ __pycache__/
*.tar *.tar
*.tar.gz *.tar.gz
_*.py _*.py
deploy/caddy-djk/deploy_nas.py
deploy/caddy-djk/Caddyfile.nas
-14
View File
@@ -1,14 +0,0 @@
{
email yvan@xyvan.cn
}
djk2.xyvan.cn:31513 {
tls {
dns alidns {
access_key_id {$ALI_ID}
access_key_secret {$ALI_SECRET}
}
resolvers 223.5.5.5
}
reverse_proxy 192.168.31.32:8998
}
-6
View File
@@ -1,6 +0,0 @@
FROM caddy:2-builder AS builder
ENV GOPROXY=https://goproxy.cn,direct
RUN xcaddy build --with github.com/caddy-dns/alidns
FROM caddy:2
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
+1 -7
View File
@@ -259,16 +259,10 @@ func (app *UIApp) handlePlaybackMediaAsset(writer http.ResponseWriter, request *
return return
} }
run, err := strconv.ParseUint(parts[1], 10, 64) run, err := strconv.ParseUint(parts[1], 10, 64)
viewer := contextViewer(request.Context())
app.playbackMu.Lock() app.playbackMu.Lock()
session := app.playbacks[parts[0]] session := app.playbacks[parts[0]]
denied := err != nil || session == nil || session.run != run || session.media == nil if err != nil || !viewerOwnsPlayback(request.Context(), session) || session.run != run || session.media == nil {
if !denied && viewer != nil {
denied = !viewerOwnsPlayback(request.Context(), session)
}
if denied {
app.playbackMu.Unlock() app.playbackMu.Unlock()
app.recordPlaybackAssetDenial(request, "session-unavailable")
writer.WriteHeader(http.StatusGone) writer.WriteHeader(http.StatusGone)
return return
} }
-11
View File
@@ -94,17 +94,6 @@ func (app *UIApp) registerPlaybackRoutes(mux *http.ServeMux) {
mux.HandleFunc("/api/ui/playback/progress", app.handlePlaybackProgress) mux.HandleFunc("/api/ui/playback/progress", app.handlePlaybackProgress)
} }
// recordPlaybackAssetDenial 记录媒体资产请求被拒的情况,便于诊断
// iOS/WebKit 原生媒体管线的拉流失败(区分会话失效与观看者不匹配)。
func (app *UIApp) recordPlaybackAssetDenial(request *http.Request, reason string) {
agent := request.UserAgent()
if len(agent) > 120 {
agent = agent[:120]
}
app.downloader.recordDiagnostic(diagnosticEvent{Level: "warn", Event: "playback.asset.denied",
HTTPStatus: http.StatusGone, Message: reason + " ua=" + agent})
}
func playbackRequestAllowed(writer http.ResponseWriter, request *http.Request, method string) bool { func playbackRequestAllowed(writer http.ResponseWriter, request *http.Request, method string) bool {
writer.Header().Set("Cache-Control", "private, no-store, no-transform") writer.Header().Set("Cache-Control", "private, no-store, no-transform")
writer.Header().Set("X-Accel-Buffering", "no") writer.Header().Set("X-Accel-Buffering", "no")
+1 -7
View File
@@ -95,16 +95,10 @@ func (app *UIApp) handlePlaybackNativeAsset(writer http.ResponseWriter, request
writeJSON(writer, http.StatusBadRequest, map[string]string{"error": "播放请求编号无效"}) writeJSON(writer, http.StatusBadRequest, map[string]string{"error": "播放请求编号无效"})
return return
} }
viewer := contextViewer(request.Context())
app.playbackMu.Lock() app.playbackMu.Lock()
session := app.playbacks[query.Get("session")] session := app.playbacks[query.Get("session")]
denied := session == nil || session.run != run || session.native == nil if !viewerOwnsPlayback(request.Context(), session) || session.run != run || session.native == nil {
if !denied && viewer != nil {
denied = !viewerOwnsPlayback(request.Context(), session)
}
if denied {
app.playbackMu.Unlock() app.playbackMu.Unlock()
app.recordPlaybackAssetDenial(request, "stream-unavailable")
writeJSON(writer, http.StatusGone, map[string]string{"error": "此播放流已结束,请重新选择分集"}) writeJSON(writer, http.StatusGone, map[string]string{"error": "此播放流已结束,请重新选择分集"})
return return
} }
-12
View File
@@ -207,12 +207,6 @@ func viewerOwnsPlayback(ctx context.Context, session *playbackSession) bool {
return viewer != nil && session != nil && session.viewer == viewer && playbackSourceAllowed(ctx, session) return viewer != nil && session != nil && session.viewer == viewer && playbackSourceAllowed(ctx, session)
} }
// playbackCapabilityPath 判断是否为无需 viewer cookie 的媒体资产路径:
// 这些 URL 中已包含不可猜测的播放会话 ID,可作为独立能力凭证。
func playbackCapabilityPath(path string) bool {
return strings.HasPrefix(path, "/api/ui/playback/media/") || path == "/api/ui/playback/hls/index.m3u8" || path == "/api/ui/playback/hls/segment.ts"
}
func writeViewerError(writer http.ResponseWriter, status int, code, message string) { func writeViewerError(writer http.ResponseWriter, status int, code, message string) {
writer.Header().Set("Cache-Control", "private, no-store") writer.Header().Set("Cache-Control", "private, no-store")
writer.Header().Add("Vary", "Cookie") writer.Header().Add("Vary", "Cookie")
@@ -240,12 +234,6 @@ func (app *UIApp) withBrowserViewer(next http.Handler) http.Handler {
} }
identity := manager.identity(request) identity := manager.identity(request)
if account.ID == "" && (identity == "" || accountCookie) { if account.ID == "" && (identity == "" || accountCookie) {
if playbackCapabilityPath(path) {
// AVPlayer 等原生媒体管线可能不携带 cookie;播放会话 ID 本身即能力凭证,
// 由媒体资产接口自行校验会话与运行编号。
next.ServeHTTP(writer, request)
return
}
writeViewerError(writer, http.StatusUnauthorized, "viewer_required", "请刷新页面,恢复此浏览器的独立观看记录") writeViewerError(writer, http.StatusUnauthorized, "viewer_required", "请刷新页面,恢复此浏览器的独立观看记录")
return return
} }