回退 HTTPS 与无 cookie 拉流改动:放弃 HTTPS 方案,iPhone 播放改用夸克系统解码;仅保留 *.tar.gz 与 _*.py 的 gitignore 卫生规则
This commit is contained in:
@@ -21,5 +21,3 @@ __pycache__/
|
|||||||
*.tar
|
*.tar
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
_*.py
|
_*.py
|
||||||
deploy/caddy-djk/deploy_nas.py
|
|
||||||
deploy/caddy-djk/Caddyfile.nas
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user