gpt4 book ai didi

http - Go lang 捕获带超时的重定向 url 和状态代码

转载 作者:IT王子 更新时间:2023-10-29 01:27:36 25 4
gpt4 key购买 nike

我正在尝试向给定的 url 发出请求,并捕获重定向 url 及其所遵循的状态代码。

我尝试寻找我的具体问题的答案 - this接近了。

但是,我还需要在整个连接上添加代理、用户代理和超时,即无论有多少重定向/代理延迟等,时间量都不应超过 X 秒。

我通过设置请求 header 来处理用户代理,并通过将其添加到传输结构来处理代理。我尝试探索 CheckRedirect 的重定向 - 但它只给了我 Url,我还需要状态代码,所以我必须实现 RoundTrip 函数。

目前一切正常——除了超时。这是我到目前为止所拥有的 - playground link我也在这里粘贴了相关代码 - playground 有一个完整版本,带有一个模拟重定向服务器 - 不幸的是它 panic 说连接被拒绝可能是因为 playground 限制 - 虽然它完全在本地工作。

type Redirect struct {
StatusCode int
URL string
}

type TransportWrapper struct {
Transport http.RoundTripper
Url string
Proxy string
UserAgent string
TimeoutInSeconds int
FinalUrl string
RedirectUrls []Redirect
}
// Implementing Round Tripper to capture intermediate urls
func (t *TransportWrapper) RoundTrip(req *http.Request) (*http.Response, error) {
transport := t.Transport
if transport == nil {
transport = http.DefaultTransport
}

resp, err := transport.RoundTrip(req)
if err != nil {
return resp, err
}

// Remember redirects
if resp.StatusCode >= 300 && resp.StatusCode <= 399 {
t.RedirectUrls = append(
t.RedirectUrls, Redirect{resp.StatusCode, req.URL.String()},
)
}
return resp, err
}

func (t *TransportWrapper) Do() (*http.Response, error) {
t.Transport = &http.Transport{}
if t.Proxy != "" {
proxyUrl, err := url.Parse(t.Proxy)
if err != nil {
return nil, err
}

t.Transport = &http.Transport{Proxy:http.ProxyURL(proxyUrl)}
// HELP
// Why does this fail
// t.Transport.Proxy = http.ProxyUrl(proxyUrl)
}

client := &http.Client{
Transport: t, // Since I've implemented RoundTrip I can pass this
// Timeout: t.TimeoutInSeconds * time.Second, // This Fails
}

req, err := http.NewRequest("GET", t.Url, nil)
if err != nil {
return nil, err
}

if t.UserAgent != "" {
req.Header.Set("User-Agent", t.UserAgent)
}

resp, err := client.Do(req)
if err != nil {
return nil, err
}

t.FinalUrl = resp.Request.URL.String()
return resp, nil
}

func startClient() {
t := &TransportWrapper {
Url: "http://127.0.0.1:8080/temporary/redirect?num=5",
// Proxy
// UserAgent
// Timeout
}

_, err := t.Do()
if err != nil {
panic(err)
}

fmt.Printf("Intermediate Urls: \n")
for i, v := range t.RedirectUrls {
fmt.Printf("[%d] %s\n", i, v)
}

}

问题一:如何添加超时时间?

尝试#1:

client := &http.Client{ Transport: t, Timeout: myTimeout }

但是 Go 提示说“*main.TransportWrapper 不支持取消请求;不支持超时”

尝试#2:

// Adding a CancelRequest
func (t *TransportWrapper) CancelRequest(req *http.Request) {
dt := http.DefaultTransport
dt.CancelRequest(req)
}

但是 Go 提示说“dt.CancelRequest 未定义(类型 http.RoundTripper 没有字段或方法 CancelRequest)”

我如何在不做太多事情的情况下实现这个 CancelRequest 并让默认的 CancelRequest 接管?

问题 2:我是否走错了路,是否有解决问题的替代方法,

给定一个 Url、Proxy、UserAgent 和 Timeout - 返回响应连同重定向 URL 及其状态代码以到达那里。

我希望我的措辞是恰当的。

谢谢

最佳答案

已经有一个检查重定向的钩子(Hook),Client.CheckRedirect .

您可以提供回调来执行您想要的操作。

如果你真的想创建你自己的传输来扩展其他功能,你需要提供一个 CancelRequest 方法,就像错误所说的那样处理 Client.Timeout .

func (t *TransportWrapper) CancelRequest(req *Request) {
t.Transport.CancelRequest(req)
}

更常见的是,您可以嵌入Transport,以便自动提升所有方法和字段。但是,您应该避免传输中的可写字段,因为它预计可以安全地同时使用,否则您应该使用互斥锁保护所有访问权限,或者您必须确保它仅在一个 goroutine 中使用。

一个最小的例子是这样的:

type TransportWrapper struct {
*http.Transport
RedirectUrls []Redirect
}

func (t *TransportWrapper) RoundTrip(req *http.Request) (*http.Response, error) {
transport := t.Transport
if transport == nil {
transport = http.DefaultTransport.(*http.Transport)
}

resp, err := transport.RoundTrip(req)
if err != nil {
return resp, err
}

// Remember redirects
if resp.StatusCode >= 300 && resp.StatusCode <= 399 {
fmt.Println("redirected")
t.RedirectUrls = append(
t.RedirectUrls, Redirect{resp.StatusCode, req.URL.String()},
)
}
return resp, err
}

然后您可以在客户端中使用超时:

client := &http.Client{
Transport: &TransportWrapper{
Transport: http.DefaultTransport.(*http.Transport),
},
Timeout: 5 * time.Second,
}

关于http - Go lang 捕获带超时的重定向 url 和状态代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32154712/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com