为了账号安全,请及时绑定邮箱和手机立即绑定

GoLang - 使用正文数据跟踪 POST 请求的重定向

GoLang - 使用正文数据跟踪 POST 请求的重定向

Go
ITMISS 2022-10-24 09:11:41
我想在 POST 请求中使用相同的正文进行重定向。来自 GO 来源 (client.go)func redirectBehavior(reqMethod string, resp *Response, ireq *Request) (redirectMethod string, shouldRedirect, includeBody bool) {    switch resp.StatusCode {    case 301, 302, 303:        redirectMethod = reqMethod        shouldRedirect = true        includeBody = false        // RFC 2616 allowed automatic redirection only with GET and        // HEAD requests. RFC 7231 lifts this restriction, but we still        // restrict other methods to GET to maintain compatibility.        // See Issue 18570.但有时服务器会为 POST 请求返回 302 Redirect,这意味着我需要将相同的正文发送到另一个位置。在这种情况下我该怎么办?func FollowRedirectForPost() {    client := &http.Client{}        req, _ := http.NewRequest(http.MethodPost, "example.com/test", strings.NewReader(url.Values{        "key": {"value"},        "key1":{"value1"},    }.Encode()))    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")    client.Do(req) // If server returns 302 Redirect so it means I need make the same request with the same body to    // a different location. Just imagine i replaced "example.com/test" to "example.com/redirect_url"}
查看完整描述

2 回答

?
慕的地6264312

TA贡献1817条经验 获得超6个赞

来自RFC7231

服务器应该在包含不同 URI 的 URI 引用的响应中生成 Location 头字段。用户代理可以使用 Location 字段值进行自动重定向。服务器的响应负载通常包含一个简短的超文本注释,其中包含指向不同 URI 的超链接。

注意:由于历史原因,用户代理可以将后续请求的请求方法从 POST 更改为 GET。如果不希望出现这种行为,则可以改用 307(临时重定向)状态代码。

所以你可以跟随重定向,新的 URI 在Location标头中。你不必。您可以将方法更改为 GET,但不必这样做。所以本质上,你所做的任何事情都是符合 RFC 的。

CheckRedirect您可以通过提供函数来提供自己的重定向策略。基本上与客户在is和was时redirectPostOn302所做的相同:includeBodytrueredirectMethodPOST

func FollowRedirectForPost() {

    client := &http.Client{

        CheckRedirect: redirectPostOn302,

    }

    

    req, _ := http.NewRequest(http.MethodPost, "example.com/test", strings.NewReader(url.Values{

        "key": {"value"},

        "key1":{"value1"},

    }.Encode()))


    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

    client.Do(req) // If server returns 302 Redirect so it means I need make the same request with the same body to

    // a different location. Just imagine i replaced "example.com/test" to "example.com/redirect_url"

}


func redirectPostOn302(req *http.Request, via []*http.Request) error {

    if len(via) >= 10 {

        return errors.New("stopped after 10 redirects")

    }


    lastReq := via[len(via)-1]

    if req.Response.StatusCode == 302 && lastReq.Method == http.MethodPost {

        req.Method = http.MethodPost


        // Get the body of the original request, set here, since req.Body will be nil if a 302 was returned

        if via[0].GetBody != nil {

            var err error

            req.Body, err = via[0].GetBody()

            if err != nil {

                return err

            }

            req.ContentLength = via[0].ContentLength

        }

    }


    return nil

}


查看完整回答
反对 回复 2022-10-24
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

最佳做法是更改服务器状态代码 - 307(临时重定向)或 308(永久重定向)。

如果服务器回复重定向,则客户端首先使用 CheckRedirect 函数来确定是否应遵循重定向。如果允许,301、302 或 303 重定向会导致后续请求使用 HTTP 方法 GET(如果原始请求是 HEAD,则使用 HEAD),没有正文。如果定义了 Request.GetBody 函数,307 或 308 重定向会保留原始 HTTP 方法和正文。NewRequest 函数自动为通用标准库主体类型设置 GetBody。

另一种超级 hacky 方式可能是 - 更改 CheckRedirect 函数中的请求 https://github.com/golang/go/blob/master/src/net/http/client.go#L78 https://github.com/golang/去/blob/master/src/net/http/client.go#L691

// example hack

 func FollowRedirectForPost(data io.Reader) {

    client := &http.Client{

        CheckRedirect: func(req *Request, via []*Request) error {

            // check status code etc.

            req.Method = http.MethodPost

            req.Body = data

        }

    }

    

    req, _ := http.NewRequest(http.MethodPost, "example.com/test", data)


    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

    client.Do(req) // If server returns 302 Redirect so it means I need make the same request with the same body to

    // a different location. Just imagine i replaced "example.com/test" to "example.com/redirect_url"

}


查看完整回答
反对 回复 2022-10-24
  • 2 回答
  • 0 关注
  • 163 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信