Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP308 跳转是否丢失数据 #217

Open
DeemoASCII opened this issue Apr 29, 2020 · 10 comments
Open

HTTP308 跳转是否丢失数据 #217

DeemoASCII opened this issue Apr 29, 2020 · 10 comments

Comments

@DeemoASCII
Copy link

我向 http://test.mesoor.com/api/open-candidates/ 发送一个 http 请求如下所示,

GET /api/open-candidates/mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1 HTTP/1.1
Authorization: Bearer **
Host: test1.mesoor.com

但是我却得到
< HTTP/2.0 401 Unauthorized
{
"message": "未携带 Token",
"reason": null,
"type": "TOKEN_VALIDATE:NO_TOKEN"
}
这里的 token 我已经确定是包含在 headers 的 Authorization 并且正确。
待我向后端询问的时候让我尝试用 https,即请求 https://test.mesoor.com/api/open-candidates/,这样我能得到正常的结果,因为使用 http 的时候会返回 308 Permanent Redirect,重定向到 https 的请求上,但是 gout 没有给我返回 308,并且自动重定向了,在这个过程中,没有附带上 Authorization,请问这是个 bug 吗

@guonaihong
Copy link
Owner

了解,方便的话可以把gout的使用代码发下嘛。

@guonaihong
Copy link
Owner

有环境的话,我来看下原因。

@DeemoASCII
Copy link
Author

代码如下:
err := gout.GET(ResumeDetailUrl + ctx.Params().Get("openid")).
Debug(true).
SetHeader(gout.H{
"host": ctx.Host(),
"authorization": auth,
}).
BindBody(&resp).
Code(&code).
Do()
可以使用如下环境:
url: "http://zhaohutest1.mesoor.com/api/open-candidates/rd5.zhaopin.com-(mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1"
authorization: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJmNmFhYTcyNy1iNDRmLTRiNDYtYWExNS1jYWZhYTA4NDg1NmIiLCJ1c2VyUm9sZSI6MTYsImlhdCI6MTU4ODA2ODMyMywiZXhwIjoxNTg4NjczMTIzfQ.ZcrFxAZwdDf6s2eGbDuhxyh3VaFxFtCZ35G8O6bwQqk"
host: "zhaohutest1.mesoor.com"

@guonaihong
Copy link
Owner

@DeemoASCII 我刚刚写了一个mock代码。证实gout不会丢authorization,建议再看看服务端那块逻辑。
mock代码逻辑,先访问/308接口,然后传一个308状态让转到/api接口,把authorization字段数据打到终端,和客户设置的值是一样的。

package main

import (
    "fmt"
    "time"

    "github.com/gin-gonic/gin"
    "github.com/guonaihong/gout"
)

func mockServer() {
    r := gin.Default()
    r.GET("/api/*action", func(c *gin.Context) {
        fmt.Println("")
        fmt.Printf("--------->authorization:(%s)\n", c.Request.Header.Get("authorization"))
        fmt.Println("")
    })

    r.GET("/308/*action", func(c *gin.Context) {
        c.Redirect(308, "http://127.0.0.1:8080/api/hello")
    })

    r.Run()
}

func main() {

    go mockServer()

    time.Sleep(time.Second)

    resp := ""
    code := 0
    err := gout.GET("http://127.0.0.1:8080/308/open-candidates/rd5.zhaopin.com-(mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1").
        //err := gout.GET("https://zhaohutest1.mesoor.com/api/open-candidates/rd5.zhaopin.com-(mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1").
        //err := gout.GET("http://zhaohutest1.mesoor.com/api/open-candidates/rd5.zhaopin.com-(mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1").
        Debug(true).
        SetHeader(gout.H{
            "host":          "test1.mesoor.com",
            "authorization": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJmNmFhYTcyNy1iNDRmLTRiNDYtYWExNS1jYWZhYTA4NDg1NmIiLCJ1c2VyUm9sZSI6MTYsImlhdCI6MTU4ODA2ODMyMywiZXhwIjoxNTg4NjczMTIzfQ.ZcrFxAZwdDf6s2eGbDuhxyh3VaFxFtCZ35G8O6bwQqk",
        }).
        BindBody(&resp).
        Code(&code).
        Do()
    fmt.Printf("err:%v\n", err)
}

@DeemoASCII
Copy link
Author

刚才我换用 Python 写了同样的代码做了同样的请求,但是 Python 可以请求成功。

import requests
resp = requests.get("http://zhaohutest1.mesoor.com/api/open-candidates/rd5.zhaopin.com-(mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1",headers={"Authorization":"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJmNmFhYTcyNy1iNDRmLTRiNDYtYWExNS1jYWZhYTA4NDg1NmIiLCJ1c2VyUm9sZSI6MTYsImlhdCI6MTU4ODA2ODMyMywiZXhwIjoxNTg4NjczMTIzfQ.ZcrFxAZwdDf6s2eGbDuhxyh3VaFxFtCZ35G8O6bwQqk"})
print(resp.text)
# '{"id":1696,"openid":"rd5.zhaopin.com-(mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1","degree":16,"status": ...

#如果我禁止重定向的话得到的是这样的结果
resp = requests.get("http://zhaohutest1.mesoor.com/api/open-candidates/rd5.zhaopin.com-(mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1",allow_redirects=False)
print(resp.text)
#'<html>\r\n<head><title>308 Permanent Redirect</title></head>\r\n<body>\r\n<center><h1>308 Permanent Redirect</h1></center>\r\n<hr><center>nginx/1.17.8</center>\r\n</body>\r\n</html>\r\n'

这里面是否存在没有考虑到的情况

@guonaihong
Copy link
Owner

guonaihong commented Apr 29, 2020

谢�了,我继续看下。
刚刚用了,python里面的token 并把url换成https可以访问的。如果急的话,可以用https访问接口。
我梳理下思路:
1.http直接访问用的是http 1.1 ,https是用http2。
2.然后服务端返回308,这时候转成http 2.0然后会报没有token的错误。

重定向逻辑是http标准库里面Transport对象控制下,我需要看下源码。

@DeemoASCII
Copy link
Author

我用 https 在开发了,毕竟这不是什么太难的事情,只不过刚好遇到了这个问题,而其他的库又能请求成功,感觉像是个 bug,谢谢你的解答

@guonaihong
Copy link
Owner

好的。我昨天又验证了下,这个现象和go 标准库有关系(下面的代码也不能处理)。
可以向 https://github.com/golang/go 提issue

package main

import (
    "io"
    "net/http"
    "os"
)

func main() {

    //httpsURL := "https://zhaohutest1.mesoor.com/api/open-candidates/rd5.zhaopin.com-(mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1"
    httpURL := "http://zhaohutest1.mesoor.com/api/open-candidates/rd5.zhaopin.com-(mSb21kCzwLIuPI9lwPiOajP2XmiSnCI_1_1"
    req, err := http.NewRequest("GET", httpURL, nil)
    if err != nil {
        panic(err.Error())
    }   

    req.Header.Add("host", "test1.mesoor.com")
    req.Header.Add("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJmNmFhYTcyNy1iNDRmLTRiNDYtYWExNS1jYWZhYTA4NDg1NmIiLCJ1c2VyUm9sZSI6MTYsImlhdCI6MTU4ODA2ODMyMywiZXhwIjoxNTg4NjczMTIzfQ.ZcrFxAZwdDf6s2eGbDuhxyh3VaFxFtCZ35G8O6bwQqk")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err.Error())
    }   

    defer resp.Body.Close()
    io.Copy(os.Stdout, resp.Body)

}

@guonaihong
Copy link
Owner

这个应该是标准库的bug,用你提的流程跑 Authorization这个header会丢失。厉害了你。

@guonaihong
Copy link
Owner

记录下,这个行为是net/http库的,已经提交pr给golang项目。
golang/go#38760

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants