在 Go 中有选择地遵循重定向
Selectively Follow Redirects in Go
我正在尝试编写一个 Twitter 阅读器来解决 link 缩短器等的最终 URLs,但在途中给了我一个 URL 手动列表定义的主机模式。这样做的原因是我不想以付费专区结束URL,而是之前的那个。
据我所知,这样做的方法是基于默认值 RoundTripper
编写我自己的客户端,因为从自定义 CheckRedirect
函数返回错误会中止客户端而不产生响应。
有没有办法使用默认 client
并通过自定义 checkRedirect
函数记录 URLs/specific URL 的列表?
如果您的自定义 CheckResponse
产生错误(如前所述在评论中)。
http://golang.org/pkg/net/http/#Client
If CheckRedirect returns an error, the Client's Get method returns both the previous Response and CheckRedirect's error (wrapped in a url.Error) instead of issuing the Request req.
如果您维护 "known" 付费专区 url 列表,您可以使用自定义 error
类型(Paywalled
在 CheckResponse
中中止付费专区重定向下面的例子)。
您的错误处理代码稍后必须将该错误类型视为特殊(非错误)情况。
示例:
package main
import (
"errors"
"fmt"
"net/http"
"net/url"
)
var Paywalled = errors.New("next redirect would hit a paywall")
var badHosts = map[string]error{
"registration.ft.com": Paywalled,
}
var client = &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
// N.B.: when used in production, also check for redirect loops
return badHosts[req.URL.Host]
},
}
func main() {
resp, err := client.Get("http://on.ft.com/14pQBYE")
// ignore non-nil err if it's a `Paywalled` wrapped in url.Error
if e, ok := err.(*url.Error); (ok && e.Err != Paywalled) || (!ok && err != nil) {
fmt.Println("error: ", err)
return
}
resp.Body.Close()
fmt.Println(resp.Request.URL)
}
我正在尝试编写一个 Twitter 阅读器来解决 link 缩短器等的最终 URLs,但在途中给了我一个 URL 手动列表定义的主机模式。这样做的原因是我不想以付费专区结束URL,而是之前的那个。
据我所知,这样做的方法是基于默认值 RoundTripper
编写我自己的客户端,因为从自定义 CheckRedirect
函数返回错误会中止客户端而不产生响应。
有没有办法使用默认 client
并通过自定义 checkRedirect
函数记录 URLs/specific URL 的列表?
如果您的自定义 CheckResponse
产生错误(如前所述在评论中)。
http://golang.org/pkg/net/http/#Client
If CheckRedirect returns an error, the Client's Get method returns both the previous Response and CheckRedirect's error (wrapped in a url.Error) instead of issuing the Request req.
如果您维护 "known" 付费专区 url 列表,您可以使用自定义 error
类型(Paywalled
在 CheckResponse
中中止付费专区重定向下面的例子)。
您的错误处理代码稍后必须将该错误类型视为特殊(非错误)情况。
示例:
package main
import (
"errors"
"fmt"
"net/http"
"net/url"
)
var Paywalled = errors.New("next redirect would hit a paywall")
var badHosts = map[string]error{
"registration.ft.com": Paywalled,
}
var client = &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
// N.B.: when used in production, also check for redirect loops
return badHosts[req.URL.Host]
},
}
func main() {
resp, err := client.Get("http://on.ft.com/14pQBYE")
// ignore non-nil err if it's a `Paywalled` wrapped in url.Error
if e, ok := err.(*url.Error); (ok && e.Err != Paywalled) || (!ok && err != nil) {
fmt.Println("error: ", err)
return
}
resp.Body.Close()
fmt.Println(resp.Request.URL)
}