猿问

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

我感到恐慌,我试图理解它,但我不确定它为什么会恐慌。错误如下所示:


main.HTTPSNonWWWRedirect.func1(0x9a5a20, 0xc42015c2a0, 0xc420441400)

        /srv/www/go/src/srorapp.no/handler.go:119 +0x1ef

net/http.HandlerFunc.ServeHTTP(0xc4200c5f20, 0x9a5a20, 0xc42015c2a0, 0xc420441400)

        /usr/local/go/src/net/http/server.go:1918 +0x44

net/http.serverHandler.ServeHTTP(0xc4200696c0, 0x9a5a20, 0xc42015c2a0, 0xc420441400)

        /usr/local/go/src/net/http/server.go:2619 +0xb4

net/http.(*conn).serve(0xc42006d180, 0x9a5fa0, 0xc42031e840)

        /usr/local/go/src/net/http/server.go:1801 +0x71d

created 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)

    })

}


临摹微笑
浏览 110回答 1
1回答

qq_花开花谢_0

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 rangegoroutine 37 [running]:net/http.(*conn).serve.func1(0xc0001380a0)    /usr/local/opt/go/libexec/src/net/http/server.go:1746 +0xd0panic(0x125c0c0, 0x14964d0)    /usr/local/opt/go/libexec/src/runtime/panic.go:513 +0x1b9main.main.func1(0x12efa80, 0xc00014c2a0, 0xc000162300)    /Users/novalagung/Desktop/test.go:11 +0x13dnet/http.HandlerFunc.ServeHTTP(0x12bcd98, 0x12efa80, 0xc00014c2a0, 0xc000162300)    /usr/local/opt/go/libexec/src/net/http/server.go:1964 +0x44net/http.(*ServeMux).ServeHTTP(0x14a17a0, 0x12efa80, 0xc00014c2a0, 0xc000162300)    /usr/local/opt/go/libexec/src/net/http/server.go:2361 +0x127net/http.serverHandler.ServeHTTP(0xc000093110, 0x12efa80, 0xc00014c2a0, 0xc000162300)    /usr/local/opt/go/libexec/src/net/http/server.go:2741 +0xabnet/http.(*conn).serve(0xc0001380a0, 0x12efc80, 0xc000146100)    /usr/local/opt/go/libexec/src/net/http/server.go:1847 +0x646created by net/http.(*Server).Serve    /usr/local/opt/go/libexec/src/net/http/server.go:2851 +0x2f53.解决方案解决方法很简单,只要确保该r.Host值不是空字符串且长度大于 2 即可。更好地使用strings.HasPrefix()来完成此操作。if strings.HasPrefix(r.Host, "www") {    u.Host = r.Host    http.Redirect(w, r, u.String(), http.StatusMovedPermanently)    return}
随时随地看视频慕课网APP

相关分类

Go
我要回答