first commit

This commit is contained in:
2026-10-11 12:56:38 +08:00
commit 7d21f317a4
41 changed files with 10758 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
// 源站压力探针:连续快速请求源站,看它是否也限流。
// 同时校验源站图和 Photon 图的字节数是否一致(确认画质没变)。
//
// go run ./tools/probeorigin -load <Photon图片URL> [次数]
package main
import (
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
)
func main() {
load := false
ref := false
var url string
n := 20
for i := 1; i < len(os.Args); i++ {
if os.Args[i] == "-load" {
load = true
continue
}
if os.Args[i] == "-ref" {
ref = true
continue
}
if url == "" {
url = os.Args[i]
} else if v, err := strconv.Atoi(os.Args[i]); err == nil {
n = v
}
}
if url == "" {
fmt.Fprintln(os.Stderr, "用法: go run ./tools/probeorigin [-load|-ref] <Photon或源站URL> [次数]")
os.Exit(1)
}
origin, ok := stripPhoton(url)
if !ok {
origin = url // 已经是源站直链
}
// 防盗链探测:源站到底认不认 Referer?
//
// 风险点:浏览器走 Photon 而非源站,说明源站可能有防盗链、只是被
// Photon 绕开了。若是这样,直连就必须带对 Referer。
if ref {
fmt.Printf("源站: %s\n\n", origin)
for _, c := range []struct{ name, referer string }{
{"裸请求(不带头)", ""},
{"本域 Referer", "https://migmg.ssuu.uk/content/09/x.html"},
{"跨站 Referer", "https://example.com/some-page"},
{"Photon 自己", "https://i0.wp.com/"},
} {
status, b, ct, err := fetchRef(origin, c.referer, c.referer == "")
if err != nil {
fmt.Printf("%-16s → 错误: %v\n", c.name, err)
continue
}
mark := "✓"
if status != 200 || b < 1000 {
mark = "✗"
}
fmt.Printf("%-16s → HTTP %d %d 字节 type=%s %s\n", c.name, status, b, ct, mark)
time.Sleep(700 * time.Millisecond)
}
return
}
if !load {
fmt.Printf("源站: %s\n", origin)
status, b, ct, err := fetch(origin)
fmt.Printf("HTTP %d %d 字节 type=%s err=%v\n", status, b, ct, err)
return
}
// 并发压测源站
fmt.Printf("压测源站 ×%d 并发...\n", n)
var ok200, fail int64
var mu sync.Mutex
lat := []time.Duration{}
start := time.Now()
var wg sync.WaitGroup
for i := 0; i < n; i++ {
wg.Add(1)
go func() {
defer wg.Done()
t := time.Now()
status, b, _, err := fetch(origin)
d := time.Since(t)
mu.Lock()
lat = append(lat, d)
mu.Unlock()
if err == nil && status == 200 && b > 1000 {
atomic.AddInt64(&ok200, 1)
} else {
atomic.AddInt64(&fail, 1)
}
}()
}
wg.Wait()
total := time.Since(start)
fmt.Printf("成功 %d / 失败 %d 总耗时 %v\n", ok200, fail, total.Round(time.Millisecond))
if len(lat) > 0 {
var sum time.Duration
for _, d := range lat {
sum += d
}
fmt.Printf("平均延迟 %v 最快 %v 最慢 %v\n",
(sum / time.Duration(len(lat))).Round(time.Millisecond),
minDur(lat).Round(time.Millisecond),
maxDur(lat).Round(time.Millisecond))
}
}
func minDur(d []time.Duration) time.Duration {
m := d[0]
for _, x := range d[1:] {
if x < m {
m = x
}
}
return m
}
func maxDur(d []time.Duration) time.Duration {
m := d[0]
for _, x := range d[1:] {
if x > m {
m = x
}
}
return m
}
func stripPhoton(raw string) (string, bool) {
low := strings.ToLower(raw)
idx := strings.Index(low, "://i")
if idx < 0 {
return "", false
}
rest := low[idx+3:]
dot := strings.Index(rest, ".wp.com/")
if dot < 0 {
return "", false
}
scheme := raw[:idx]
origin := scheme + "://" + raw[idx+3+dot+len(".wp.com/"):]
if i := strings.IndexAny(origin, "?#"); i >= 0 {
origin = origin[:i]
}
return origin, true
}
func fetch(url string) (int, int64, string, error) {
return fetchRef(url, "https://migmg.ssuu.uk/", false)
}
// fetchRef 带可控 Referer 的请求。bare=true 时连 UA 都不发,
// 用来验证「源站是否真的无防盗链」。
func fetchRef(url, referer string, bare bool) (int, int64, string, error) {
tr := &http.Transport{ForceAttemptHTTP2: true}
defer tr.CloseIdleConnections()
client := &http.Client{Transport: tr, Timeout: 25 * time.Second}
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return 0, 0, "", err
}
if !bare {
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
req.Header.Set("Accept", "image/webp,image/*,*/*;q=0.8")
}
if referer != "" {
req.Header.Set("Referer", referer)
}
resp, err := client.Do(req)
if err != nil {
return 0, 0, "", err
}
defer resp.Body.Close()
b, _ := io.Copy(io.Discard, resp.Body)
return resp.StatusCode, b, resp.Header.Get("Content-Type"), nil
}