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

从使用 Go 制作的生产服务器中获取 panic

从使用 Go 制作的生产服务器中获取 panic

Go
临摹微笑 2023-05-15 14:42:56
我感到恐慌,我试图理解它,但我不确定它为什么会恐慌。错误如下所示:main.HTTPSNonWWWRedirect.func1(0x9a5a20, 0xc42015c2a0, 0xc420441400)        /srv/www/go/src/srorapp.no/handler.go:119 +0x1efnet/http.HandlerFunc.ServeHTTP(0xc4200c5f20, 0x9a5a20, 0xc42015c2a0, 0xc420441400)        /usr/local/go/src/net/http/server.go:1918 +0x44net/http.serverHandler.ServeHTTP(0xc4200696c0, 0x9a5a20, 0xc42015c2a0, 0xc420441400)        /usr/local/go/src/net/http/server.go:2619 +0xb4net/http.(*conn).serve(0xc42006d180, 0x9a5fa0, 0xc42031e840)        /usr/local/go/src/net/http/server.go:1801 +0x71dcreated by net/http.(*Server).Serve        /usr/local/go/src/net/http/server.go:2720 +0x288它看起来像是从一个名为 HTTPSNonWWWRedirect 的函数中触发的。这是我创建的 http 中间件:// HTTPSNonWWWRedirect redirects http requests to https non www.func HTTPSNonWWWRedirect(next http.Handler) http.Handler {    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        if r.TLS != nil {            // If already using HTTPS then continue.            next.ServeHTTP(w, r)            return        }        u := *r.URL        u.Scheme = "https"        if r.Host[:3] != "www" {            u.Host = r.Host            http.Redirect(w, r, u.String(), http.StatusMovedPermanently)            return        }        u.Host = r.Host[4:]        http.Redirect(w, r, u.String(), http.StatusMovedPermanently)    })}此功能与以下一起使用:// NonWWWRedirect redirects www requests to non www.func NonWWWRedirect(next http.Handler) http.Handler {    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        if r.Host[:3] != "www" {            // If already non www, then continue.            next.ServeHTTP(w, r)            return        }        u := *r.URL        u.Host = r.Host[4:]        u.Scheme = utils.Scheme(r)        http.Redirect(w, r, u.String(), http.StatusMovedPermanently)    })}
查看完整描述

1 回答

?
qq_花开花谢_0

TA贡献1835条经验 获得超7个赞

1. 问题

包含handler.go:119一个if声明。您试图从标题中获取前三个字符Host。


if r.Host[:3] != "www" {

    u.Host = r.Host

    http.Redirect(w, r, u.String(), http.StatusMovedPermanently)

    return

}

正常情况下,r.Host会存储请求的URL信息。除非标Host头在请求中明确更改。来自net/http 包文档:

type Request struct {

    // ...


    // For server requests Host specifies the host on which the URL

    // is sought. Per RFC 7230, section 5.4, this is either the value

    // of the "Host" header or the host name given in the URL itself.

    // It may be of the form "host:port". For international domain

    // names, Host may be in Punycode or Unicode form. Use

    // golang.org/x/net/idna to convert it to either format if

    // needed.

    // To prevent DNS rebinding attacks, server Handlers should

    // validate that the Host header has a value for which the

    // Handler considers itself authoritative. The included

    // ServeMux supports patterns registered to particular host

    // names and thus protects its registered Handlers.

    //

    // For client requests Host optionally overrides the Host

    // header to send. If empty, the Request.Write method uses

    // the value of URL.Host. Host may contain an international

    // domain name.

    Host string


    // ...

}

所以恐慌的发生是因为r.Host填充了空字符串,或者一些字符数小于 3 的字符串。


2. 测试

我使用 go 创建了非常简单的 Web 应用程序,它打印r.Host[:3]. 我使用 curl 对其进行了测试,并将Host标头设置为空。


curl --verbose --header 'Host: ' http://localhost:8080

它会引发恐慌,我很确定这和你得到的一样是恐慌错误。


2018/12/07 08:11:54 http: panic serving 127.0.0.1:50889: runtime error: slice bounds out of range

goroutine 37 [running]:

net/http.(*conn).serve.func1(0xc0001380a0)

    /usr/local/opt/go/libexec/src/net/http/server.go:1746 +0xd0

panic(0x125c0c0, 0x14964d0)

    /usr/local/opt/go/libexec/src/runtime/panic.go:513 +0x1b9

main.main.func1(0x12efa80, 0xc00014c2a0, 0xc000162300)

    /Users/novalagung/Desktop/test.go:11 +0x13d

net/http.HandlerFunc.ServeHTTP(0x12bcd98, 0x12efa80, 0xc00014c2a0, 0xc000162300)

    /usr/local/opt/go/libexec/src/net/http/server.go:1964 +0x44

net/http.(*ServeMux).ServeHTTP(0x14a17a0, 0x12efa80, 0xc00014c2a0, 0xc000162300)

    /usr/local/opt/go/libexec/src/net/http/server.go:2361 +0x127

net/http.serverHandler.ServeHTTP(0xc000093110, 0x12efa80, 0xc00014c2a0, 0xc000162300)

    /usr/local/opt/go/libexec/src/net/http/server.go:2741 +0xab

net/http.(*conn).serve(0xc0001380a0, 0x12efc80, 0xc000146100)

    /usr/local/opt/go/libexec/src/net/http/server.go:1847 +0x646

created by net/http.(*Server).Serve

    /usr/local/opt/go/libexec/src/net/http/server.go:2851 +0x2f5

3.解决方案

解决方法很简单,只要确保该r.Host值不是空字符串且长度大于 2 即可。更好地使用strings.HasPrefix()来完成此操作。


if strings.HasPrefix(r.Host, "www") {

    u.Host = r.Host

    http.Redirect(w, r, u.String(), http.StatusMovedPermanently)

    return

}


查看完整回答
反对 回复 2023-05-15
  • 1 回答
  • 0 关注
  • 109 浏览
慕课专栏
更多

添加回答

举报

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