使用Basic Auth转到HTTP请求返回401而不是301重定向

Ces*_*sar 3 redirect curl go

使用Go 1.5.1.

当我尝试向使用Basic Auth自动重定向到HTTPS的站点发出请求时,我希望获得301重定向响应,而不是我得到401.

package main

import "net/http"
import "log"

func main() {
    url := "http://aerolith.org/files"
    username := "cesar"
    password := "password"
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        log.Println("error", err)
    }
    if username != "" || password != "" {
        req.SetBasicAuth(username, password)
        log.Println("[DEBUG] Set basic auth to", username, password)
    }
    cli := &http.Client{

    }
    resp, err := cli.Do(req)
    if err != nil {
        log.Println("Do error", err)
    }
    log.Println("[DEBUG] resp.Header", resp.Header)
    log.Println("[DEBUG] req.Header", req.Header)
    log.Println("[DEBUG] code", resp.StatusCode)

}
Run Code Online (Sandbox Code Playgroud)

请注意,curl返回301:

curl -vvv http://aerolith.org/files --user cesar:password
Run Code Online (Sandbox Code Playgroud)

什么可能出错?

Cer*_*món 6

http://aerolith.org/files重定向到的请求https://aerolith.org/files(注意从http更改为https).https://aerolith.org/files重定向到的请求https://aerolith.org/files/(注意添加尾随/).

Curl不遵循重定向.卷曲打印从重定向301点的状态http://aerolith.org/fileshttps://aerolith.org/files/.

Go客户端遵循两个重定向https://aerolith.org/files/.https://aerolith.org/files/返回状态为401 的请求,因为Go客户端不通过重定向传播授权标头.

https://aerolith.org/files/来自Go客户端和Curl的请求返回状态200.

如果要成功遵循重定向和身份验证,请在CheckRedirect函数中设置auth标头:

cli := &http.Client{
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
        if len(via) >= 10 {
            return errors.New("stopped after 10 redirects")
        }
        req.SetBasicAuth(username, password)
        return nil
    }}
resp, err := cli.Do(req)
Run Code Online (Sandbox Code Playgroud)

如果您想匹配Curl的作用,请直接使用传输.传输不遵循重定向.

resp, err := http.DefaultTransport.RoundTrip(req)
Run Code Online (Sandbox Code Playgroud)

应用程序还可以使用客户端CheckRedirect函数和一个区分错误来防止重定向,如回答如何使HTTP客户端不自动跟踪重定向?.这种技术似乎有点流行,但比直接使用传输更复杂.

redirectAttemptedError := errors.New("redirect")
cli := &http.Client{
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
        return redirectAttemptedError
    }}
resp, err := cli.Do(req)
if urlError, ok := err.(*url.Error); ok && urlError.Err == redirectAttemptedError {
    // ignore error from check redirect
    err = nil   
}
if err != nil {
    log.Println("Do error", err)
}
Run Code Online (Sandbox Code Playgroud)