我正在嘗試向給定的URL發出請求,並捕獲後續的重定向URL及其狀態代碼。Go lang Capture重定向URL和超時狀態代碼
我試過尋找我的具體問題的答案 - this接近。
但是,我還需要在整個連接上添加代理,用戶代理和超時,無論有多少重定向/代理延遲等,時間量不應超過X秒。
我已經通過設置請求頭和代理通過將它添加到傳輸結構來處理用戶代理。 我試着探索CheckRedirect重定向 - 但是這隻給了我Url,我還需要狀態碼,所以我必須實現RoundTrip功能。
現在一切正常 - 除了超時。 繼承人我到目前爲止 - playground link 我已經粘貼了相關的代碼 - 操場上有一個完整版本的模擬重定向服務器 - 不幸的是,它恐慌說連接被拒絕可能是因爲操場限制 - 它的工作完全儘管在本地。
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:如何添加超時?
嘗試#1:
client := &http.Client{ Transport: t, Timeout: myTimeout }
而去笙歌說: 「* main.TransportWrapper不支持CancelRequest;不支持超時」
嘗試#2:
// Adding a CancelRequest
func (t *TransportWrapper) CancelRequest(req *http.Request) {
dt := http.DefaultTransport
dt.CancelRequest(req)
}
但去抱怨說:「dt.CancelRequest未定義(類型http.RoundTripper沒有字段或方法CancelRequest)」
如何在不做太多的情況下實現這個CancelRequest,並讓默認的CancelRequest接管?
問題2:有我走了下來壞路,是有解決問題的替代方案,
獲得一個網址,代理,用戶代理和超時 - 返回與重定向URL及其狀態碼響應隨後到達那裏。
我希望我適當地說過這句話。
感謝
的'Client.CheckRedirect'讓我捕捉到重定向的URL,但我也想知道他們的狀態代碼,即301,302等,我相信[這個SO回答](http://stackoverflow.com/questions/24577494/how-to-get-the-http-redirect-status代碼在golang)說我需要創建我自己的RoundTripper。我在這裏嘗試了CancelRequest,但沒有任何區別 - 我讓服務器睡了5秒,並在一秒鐘超時,仍然沒有運氣。更新的代碼與睡眠和取消請求是[這裏](http://play.golang.org/p/zOxvQdCjOz) –
@AbhishekShivanna:我不知道爲什麼CancelRequest不適合你沒有代碼和錯誤,但我舉了一個最小的例子。我也會避免將'Do'方法放在'Transport'中,因爲它屬於'Client',並且使代碼混淆,並在兩者之間引用循環引用。 – JimB
非常感謝!我決定採用嵌入的方法。當你談論併發保護時,是否因爲同一個傳輸包裝可能在另一個客戶中使用?我計劃爲每個我想要的所有重定向的URL創建一個新的傳輸包裝器和客戶端。在這種情況下,我不應該需要鎖嗎?或者是一些內部魔法的鎖定,以及默認傳輸執行的例程? –