Go重写http请求重定向的方法
目录
- 一、背景
- 二、默认值
- 三、禁止重定向
- 四、更改重定向次数
- 五、自定义重定向策略
- 六、完整示例
- 七、总结
一、背景
当使用 Go 语言进行 HTTP 请求时,默认情况下,http.Client
会自动处理服务器返回的重定向响应(3xx 状态码)。但有时候,我们可能需要在请求中禁止自动的重定向。本文将详细介绍如何在 Go 中实现禁止 HTTP 请求的重定向、限制重定向次数以及添加自定义重定向策略。
二、默认值
http.Client
的 CheckRedirect
字段是用于处理重定向策略的函数,如果 CheckRedirect
不是 nil
,则客户端会在遵循 HTTP 重定向之前调用它。参数 req 和 via 是即将到来的请求和已经发出的请求,最早发出的请求在前面。如果 CheckRedirect
返回错误,则 Client
的 Get
方法将返回前一个 Response(其 Body 关闭)和 CheckRedirect
的错误(包装在 url.Error
),而不是继续发出重定向请求。作为一种特殊情况,如果 CheckRedirect
返回 ErrUseLastResponse
,则返回的最新响应体的 body, 且 body 未关闭,并返回 nil
错误。如果 CheckRedirect
为 nil
,则客户端使用其默认重定向策略,即在连续 10 个请求后停止。gpbbvJgZV相关源码如下,来自src/net/http/client.go
。
func defaultCheckRedirect(req *Request, via []*Request) error { if len(via) >= 10 { return errors.New("stopped after 10 redirects") } return nil }
三、禁止重定向
通过设置 http.Client
的 CheckRedirect
字段为一个为一个自定义的函数,可以控制重定向的行为。这个函数接收一个 *http.Request
和一个 []*http.Request
参数,前者代表当前正在处理的请求,后者代表已经请求的重定向请求链,返回 http.ErrUseLastResponse
错误,收到这个错误后,http.Client
不会再继续重定向请求,并且返回一个 nil
错误给上游,如下:
func forbidRedirect(req *http.Request, via []*http.Request) (err error) { // 返回一个错误,表示不允许重定向 return http.ErrUseLastResponse }
如果 CheckRedirect
字段不设置值,或是设置 nil
值,都会采用上述的默认函数defaultCheckRedirect
,进行最多 10 重定向;如果返回的不是 http.ErrUseLastResponse
错误,那么该请求将会收到一个非 nil
的错误。
四、更改重定向次数
即更改对 []*http.Request
参数长度的限制即可,一定不能返回 http.ErrUseLastResponse
错误。
func limitRedirect(req *http.Request, via []*http.Request) error { // via 记录了已经请求的 url 个数 if len(via) >= 3 { return errors.New("stopped after max redirects") } return nil }
五、自定义重定向策略
通过对重定向函数的重写,添加一些自定义的逻辑,并将该函数其赋值给 http client 的CheckRedirect
,可以实现自定义重定向策略,其中 req.Response
参数表示导致该次重定向的返回。
func myRedirect(req *http.Request, via []*http.Request) error { // 限制重定向次数 if len(via) >= 10 { return errors.New("stopped after 10 redirects") } if req == nil || req.URL == nil || req.Response == nil || !strings.HASPrefix(req.Response.Status, "3") { return http.ErrUseLastResponse } // 禁止重定向下载 apk 文件 if strings.HasSuffix(req.URL.Path, "apk") { return fmt.Errorf("invalid redirect url, path: %s", req.URL.Path) } // 限制重定向请求类型 contentType := req.Response.Header.Get("Content-Type") if strings.Contains(contentType, "octet-stream") { return fmt.Errorf("invalid redirect url, type: %s", contentType) } // 限制重定向请求体长度 contentLength := req.Response.Header.Get("Content-Length") if contentLength != "" { length, _ := strconv.Atoi(contentLength) if length > 1000 { return fmt.Errorf("invalid redirect url, len: %s", contentLength) } } // 限制重定向请求传输编码 transferEncoding := req.Response.Header.Get("Transfer-Encoding") if strings.Contains(transferEncoding, "chunked") { return fmt.Errorf("invalid redirect url, encoding: %s", transferEncoding) } return http.ErrUseLastResponse }
六、完整示例
package main import ( "errors" "fmt" "io" "net/http" ) func forbidRedirect(req *http.Request, via []*http.Request) (err error) { // 返回一个错误,表示不允许重定向 return http.ErrUseLastResponse } func limitRedirect(req *http.Request, via []*http.Request) error { // via 记录了已经请求的 url 个数 if len(via) >= 3 { return errors.New("stopped after max redirects") } return nil } func main() { // 创建一个自定义的 HTTP Client client := &http.Client{ CheckRedirect: forbidRedirect, } // 创建一个 GET 请求,该 url 一定要重定向 req, err := http.NewRequest("GET", "ht编程tps://weibo.com", nil) if err != nil { fmt.Println("Error creating request:", err) return } // 使用自定义的 Client 发送请求 resp, err := clientjs.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } 编程defer resp.Body.Close() fmt.Println("Response Status:", resp.Status) body, _ := io.ReadAll(resp.Body) fmt.Println("Response Body:", string(body)) }
七、总结
http.Client
的 CheckRedirect
字段是用于处理重定向策略的函数,如果不赋值时就会采用默认函数,默认最多重定向 10 次。我们可以通过重写默认函数来禁止重定向、改变重定向次数以及添加自定义的重定向过滤逻辑。
到此这篇关于Go重写http请求重定向的方法的文章就介绍到这了,更多相关Go http请求重定向内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以http://www.devze.com后多多支持编程客栈(www.devze.com)!
精彩评论