初始提交:短剧库源码(含转码优化 ultrafast)
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPlaybackNginxFlushesMediaAndPreservesCookies(t *testing.T) {
|
||||
nginx, err := exec.LookPath("nginx")
|
||||
if err != nil || runtime.GOOS == "windows" {
|
||||
t.Skip("local Nginx is unavailable")
|
||||
}
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
if request.URL.Path == "/ready" {
|
||||
writer.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
cookie, err := request.Cookie("synthetic_viewer")
|
||||
if err != nil || cookie.Value != "local-fixture" {
|
||||
http.Error(writer, "missing fixture identity", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if request.URL.Path == "/stream" && !playbackRequestAllowed(writer, request, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
http.SetCookie(writer, &http.Cookie{Name: "synthetic_seen", Value: "yes", Path: "/", HttpOnly: true, SameSite: http.SameSiteLaxMode})
|
||||
writer.Header().Set("Content-Type", "video/mp4")
|
||||
_, _ = io.WriteString(writer, "synthetic-init")
|
||||
writer.(http.Flusher).Flush()
|
||||
select {
|
||||
case <-request.Context().Done():
|
||||
case <-time.After(5 * time.Second):
|
||||
}
|
||||
}))
|
||||
defer upstream.Close()
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
address := listener.Addr().String()
|
||||
_ = listener.Close()
|
||||
directory := t.TempDir()
|
||||
configuration := fmt.Sprintf(`worker_processes 1;
|
||||
error_log stderr;
|
||||
pid "%[1]s/nginx.pid";
|
||||
lock_file "%[1]s/nginx.lock";
|
||||
events { worker_connections 32; }
|
||||
http {
|
||||
access_log off;
|
||||
client_body_temp_path "%[1]s/client_temp";
|
||||
proxy_temp_path "%[1]s/proxy_temp";
|
||||
fastcgi_temp_path "%[1]s/fastcgi_temp";
|
||||
uwsgi_temp_path "%[1]s/uwsgi_temp";
|
||||
scgi_temp_path "%[1]s/scgi_temp";
|
||||
server {
|
||||
listen %[2]s;
|
||||
location / {
|
||||
proxy_pass %[3]s;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_http_version 1.1;
|
||||
proxy_buffering on;
|
||||
proxy_buffer_size 4k;
|
||||
proxy_buffers 8 4k;
|
||||
}
|
||||
}
|
||||
}
|
||||
`, directory, address, upstream.URL)
|
||||
path := filepath.Join(directory, "nginx.conf")
|
||||
if err := os.WriteFile(path, []byte(configuration), 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
command := exec.CommandContext(ctx, nginx, "-e", "stderr", "-p", directory+string(os.PathSeparator), "-c", path, "-g", "daemon off; master_process off;")
|
||||
output := &cappedStringWriter{limit: 8192}
|
||||
command.Stderr = output
|
||||
command.WaitDelay = time.Second
|
||||
if err := command.Start(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
done := make(chan struct{})
|
||||
var exitErr error
|
||||
go func() { exitErr = command.Wait(); close(done) }()
|
||||
defer func() { cancel(); <-done }()
|
||||
client := &http.Client{Transport: &http.Transport{Proxy: nil}, Timeout: time.Second}
|
||||
defer client.CloseIdleConnections()
|
||||
base := "http://" + address
|
||||
deadline := time.Now().Add(3 * time.Second)
|
||||
for {
|
||||
response, err := client.Get(base + "/ready")
|
||||
if err == nil {
|
||||
response.Body.Close()
|
||||
break
|
||||
}
|
||||
select {
|
||||
case <-done:
|
||||
if strings.Contains(output.String(), "sysctlbyname") && strings.Contains(output.String(), "Operation not permitted") {
|
||||
t.Skip("local Nginx cannot read TCP settings in the sandbox; run this integration test with system access")
|
||||
}
|
||||
t.Fatal("Nginx fixture exited", exitErr, output.String())
|
||||
default:
|
||||
}
|
||||
if time.Now().After(deadline) {
|
||||
t.Fatal("Nginx fixture did not start", err)
|
||||
}
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
}
|
||||
for _, route := range []string{"buffered", "stream"} {
|
||||
t.Run(route, func(t *testing.T) {
|
||||
request, _ := http.NewRequest(http.MethodGet, base+"/"+route, nil)
|
||||
request.Header.Set("Sec-Fetch-Site", "same-origin")
|
||||
request.Header.Set("Origin", "https://library.example.invalid")
|
||||
request.AddCookie(&http.Cookie{Name: "synthetic_viewer", Value: "local-fixture"})
|
||||
started := time.Now()
|
||||
response, err := client.Do(request)
|
||||
var body []byte
|
||||
if err == nil {
|
||||
defer response.Body.Close()
|
||||
body = make([]byte, len("synthetic-init"))
|
||||
_, err = io.ReadFull(response.Body, body)
|
||||
}
|
||||
if route == "buffered" {
|
||||
if err == nil {
|
||||
t.Logf("default buffering also forwarded this fixture in %s; buffering alone does not establish a deployment failure", time.Since(started))
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil || string(body) != "synthetic-init" || response.StatusCode != http.StatusOK {
|
||||
t.Fatal("Nginx buffered or rejected media initialization", err, string(body))
|
||||
}
|
||||
if !strings.Contains(response.Header.Get("Cache-Control"), "no-store") || !strings.Contains(response.Header.Get("Set-Cookie"), "synthetic_seen=yes") {
|
||||
t.Fatal("proxy lost privacy or browser identity headers", response.Header)
|
||||
}
|
||||
t.Logf("first media bytes arrived through Nginx in %s before upstream completion", time.Since(started))
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user