84 lines
2.1 KiB
Go
84 lines
2.1 KiB
Go
// 429 详情探针:打印 429 响应的全部头部 + 响应体,看清 CDN 到底怎么限的。
|
|
//
|
|
// go run ./tools/probe429 -v <图片URL>
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 {
|
|
fmt.Fprintln(os.Stderr, "用法: go run ./tools/probe429 [-v] <图片URL>")
|
|
os.Exit(1)
|
|
}
|
|
url := os.Args[len(os.Args)-1]
|
|
verbose := false
|
|
for _, a := range os.Args {
|
|
if a == "-v" {
|
|
verbose = true
|
|
}
|
|
}
|
|
|
|
// 先探一张,看当前状态
|
|
for round := 1; round <= 3; round++ {
|
|
status, hdr, body, err := fullProbe(url, verbose)
|
|
if err != nil {
|
|
fmt.Printf("[第%d轮] 错误: %v\n", round, err)
|
|
continue
|
|
}
|
|
fmt.Printf("[第%d轮] HTTP %d\n", round, status)
|
|
if verbose || status == 429 {
|
|
for _, k := range []string{
|
|
"Retry-After", "X-RateLimit-Limit", "X-RateLimit-Remaining",
|
|
"X-RateLimit-Reset", "X-Cache", "CF-RateLimited",
|
|
"Server", "Content-Type", "X-Jetpack-Cache",
|
|
} {
|
|
if v := hdr.Get(k); v != "" {
|
|
fmt.Printf(" %s: %s\n", k, v)
|
|
}
|
|
}
|
|
if s := strings.TrimSpace(body); s != "" {
|
|
fmt.Printf(" body: %.300s\n", s)
|
|
}
|
|
}
|
|
if status == 200 {
|
|
fmt.Println(" ✓ 这次成功了")
|
|
break
|
|
}
|
|
if round < 3 {
|
|
time.Sleep(3 * time.Second)
|
|
}
|
|
}
|
|
}
|
|
|
|
func fullProbe(url string, verbose bool) (int, http.Header, 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, nil, "", err
|
|
}
|
|
// 用我们客户端的头
|
|
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")
|
|
req.Header.Set("Referer", "https://migmg.ssuu.uk/")
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return 0, nil, "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
b, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
|
|
|
|
fmt.Printf(" Proto=%s (2=HTTP/2, 1.1=HTTP/1.1)\n", resp.Proto)
|
|
return resp.StatusCode, resp.Header, string(b), nil
|
|
}
|