Go lang Capture Redirect urls and status code with

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


我试过寻找我的具体问题的答案 -这很接近。


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


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


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


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

}



PIPIONE
浏览 150回答 1
1回答

德玛西亚99

已经有一个用于检查重定向的钩子,Client.CheckRedirect.您可以提供回调来执行您想要的操作。如果你真的想创建你自己的传输来扩展其他功能,你需要提供一个CancelRequest像错误所说的方法来处理Client.Timeout。func (t *TransportWrapper) CancelRequest(req *Request) {&nbsp; &nbsp; t.Transport.CancelRequest(req)}更常见的是,您会嵌入Transport, 以便自动提升所有方法和字段。但是,您应该避免在传输中使用可写字段,因为预计并发使用是安全的,否则您应该使用互斥锁保护所有访问,或者您必须确保它只在一个 goroutine 中使用。一个最小的例子看起来像:type TransportWrapper struct {&nbsp; &nbsp; *http.Transport&nbsp; &nbsp; RedirectUrls []Redirect}func (t *TransportWrapper) RoundTrip(req *http.Request) (*http.Response, error) {&nbsp; &nbsp; transport := t.Transport&nbsp; &nbsp; if transport == nil {&nbsp; &nbsp; &nbsp; &nbsp; transport = http.DefaultTransport.(*http.Transport)&nbsp; &nbsp; }&nbsp; &nbsp; resp, err := transport.RoundTrip(req)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return resp, err&nbsp; &nbsp; }&nbsp; &nbsp; // Remember redirects&nbsp; &nbsp; if resp.StatusCode >= 300 && resp.StatusCode <= 399 {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("redirected")&nbsp; &nbsp; &nbsp; &nbsp; t.RedirectUrls = append(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t.RedirectUrls, Redirect{resp.StatusCode, req.URL.String()},&nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; }&nbsp; &nbsp; return resp, err}然后您可以在客户端使用超时:client := &http.Client{&nbsp; &nbsp; Transport: &TransportWrapper{&nbsp; &nbsp; &nbsp; &nbsp; Transport: http.DefaultTransport.(*http.Transport),&nbsp; &nbsp; },&nbsp; &nbsp; Timeout: 5 * time.Second,}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go