开发者

Go重写http请求重定向的方法

开发者 https://www.devze.com 2024-08-31 10:25 出处:网络 作者: 二郎腿
目录一、背景二、默认值三、禁止重定向四、更改重定向次数五、自定义重定向策略六、完整示例七、总结一、背景
目录
  • 一、背景
  • 二、默认值
  • 三、禁止重定向
  • 四、更改重定向次数
  • 五、自定义重定向策略
  • 六、完整示例
  • 七、总结

一、背景

当使用 Go 语言进行 HTTP 请求时,默认情况下,http.Client 会自动处理服务器返回的重定向响应(3xx 状态码)。但有时候,我们可能需要在请求中禁止自动的重定向。本文将详细介绍如何在 Go 中实现禁止 HTTP 请求的重定向、限制重定向次数以及添加自定义重定向策略

二、默认值

http.ClientCheckRedirect 字段是用于处理重定向策略的函数,如果 CheckRedirect 不是 nil,则客户端会在遵循 HTTP 重定向之前调用它。参数 req 和 via 是即将到来的请求和已经发出的请求,最早发出的请求在前面。如果 CheckRedirect 返回错误,则 ClientGet 方法将返回前一个 Response(其 Body 关闭)和 CheckRedirect 的错误(包装在 url.Error),而不是继续发出重定向请求。作为一种特殊情况,如果 CheckRedirect 返回 ErrUseLastResponse,则返回的最新响应体的 body, 且 body 未关闭,并返回 nil 错误。如果 CheckRedirectnil,则客户端使用其默认重定向策略,即在连续 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.ClientCheckRedirect 字段为一个为一个自定义的函数,可以控制重定向的行为。这个函数接收一个 *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)!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号