Add Pusher() function for support http2 server push (#1273)
gin already support http2, while previously not support server push. Add Pusher() function to extend the ResponseWriter interface. ```golang // get http.Pusher if pusher := c.Writer.Pusher(); pusher != nil { // use pusher.Push() to do server push } ``` <img width="881" alt="screen shot 2018-03-07 at 11 20 49 pm" src="https://user-images.githubusercontent.com/16014993/37100619-680c00c6-225e-11e8-9352-76ec3bd62894.png">
This commit is contained in:
parent
87d536c001
commit
bf85b32c1d
50
README.md
50
README.md
@ -54,6 +54,7 @@ Gin is a web framework written in Go (Golang). It features a martini-like API wi
|
|||||||
- [Build a single binary with templates](#build-a-single-binary-with-templates)
|
- [Build a single binary with templates](#build-a-single-binary-with-templates)
|
||||||
- [Bind form-data request with custom struct](#bind-form-data-request-with-custom-struct)
|
- [Bind form-data request with custom struct](#bind-form-data-request-with-custom-struct)
|
||||||
- [Try to bind body into different structs](#try-to-bind-body-into-different-structs)
|
- [Try to bind body into different structs](#try-to-bind-body-into-different-structs)
|
||||||
|
- [http2 server push](#http2-server-push)
|
||||||
- [Testing](#testing)
|
- [Testing](#testing)
|
||||||
- [Users](#users--)
|
- [Users](#users--)
|
||||||
|
|
||||||
@ -1656,6 +1657,55 @@ enough to call binding at once.
|
|||||||
can be called by `c.ShouldBind()` multiple times without any damage to
|
can be called by `c.ShouldBind()` multiple times without any damage to
|
||||||
performance (See [#1341](https://github.com/gin-gonic/gin/pull/1341)).
|
performance (See [#1341](https://github.com/gin-gonic/gin/pull/1341)).
|
||||||
|
|
||||||
|
### http2 server push
|
||||||
|
|
||||||
|
http.Pusher is supported only **go1.8+**. See the [golang blog](https://blog.golang.org/h2push) for detail information.
|
||||||
|
|
||||||
|
[embedmd]:# (examples/http-pusher/main.go go)
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var html = template.Must(template.New("https").Parse(`
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Https Test</title>
|
||||||
|
<script src="/assets/app.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 style="color:red;">Welcome, Ginner!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`))
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := gin.Default()
|
||||||
|
r.Static("/assets", "./assets")
|
||||||
|
r.SetHTMLTemplate(html)
|
||||||
|
|
||||||
|
r.GET("/", func(c *gin.Context) {
|
||||||
|
if pusher := c.Writer.Pusher(); pusher != nil {
|
||||||
|
// use pusher.Push() to do server push
|
||||||
|
if err := pusher.Push("/assets/app.js", nil); err != nil {
|
||||||
|
log.Printf("Failed to push: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.HTML(200, "https", gin.H{
|
||||||
|
"status": "success",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen and Server in https://127.0.0.1:8080
|
||||||
|
r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
The `net/http/httptest` package is preferable way for HTTP testing.
|
The `net/http/httptest` package is preferable way for HTTP testing.
|
||||||
|
1
examples/http-pusher/assets/app.js
Normal file
1
examples/http-pusher/assets/app.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
console.log("http2 pusher");
|
41
examples/http-pusher/main.go
Normal file
41
examples/http-pusher/main.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var html = template.Must(template.New("https").Parse(`
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Https Test</title>
|
||||||
|
<script src="/assets/app.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 style="color:red;">Welcome, Ginner!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`))
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := gin.Default()
|
||||||
|
r.Static("/assets", "./assets")
|
||||||
|
r.SetHTMLTemplate(html)
|
||||||
|
|
||||||
|
r.GET("/", func(c *gin.Context) {
|
||||||
|
if pusher := c.Writer.Pusher(); pusher != nil {
|
||||||
|
// use pusher.Push() to do server push
|
||||||
|
if err := pusher.Push("/assets/app.js", nil); err != nil {
|
||||||
|
log.Printf("Failed to push: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.HTML(200, "https", gin.H{
|
||||||
|
"status": "success",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen and Server in https://127.0.0.1:8080
|
||||||
|
r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")
|
||||||
|
}
|
15
examples/http-pusher/testdata/ca.pem
vendored
Normal file
15
examples/http-pusher/testdata/ca.pem
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV
|
||||||
|
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
|
||||||
|
aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla
|
||||||
|
Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
|
||||||
|
YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT
|
||||||
|
BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7
|
||||||
|
+L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu
|
||||||
|
g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd
|
||||||
|
Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV
|
||||||
|
HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau
|
||||||
|
sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m
|
||||||
|
oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG
|
||||||
|
Dfcog5wrJytaQ6UA0wE=
|
||||||
|
-----END CERTIFICATE-----
|
16
examples/http-pusher/testdata/server.key
vendored
Normal file
16
examples/http-pusher/testdata/server.key
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD
|
||||||
|
M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf
|
||||||
|
3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY
|
||||||
|
AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm
|
||||||
|
V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY
|
||||||
|
tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p
|
||||||
|
dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q
|
||||||
|
K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR
|
||||||
|
81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff
|
||||||
|
DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd
|
||||||
|
aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2
|
||||||
|
ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3
|
||||||
|
XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe
|
||||||
|
F98XJ7tIFfJq
|
||||||
|
-----END PRIVATE KEY-----
|
16
examples/http-pusher/testdata/server.pem
vendored
Normal file
16
examples/http-pusher/testdata/server.pem
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
|
||||||
|
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
|
||||||
|
dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
|
||||||
|
MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
|
||||||
|
BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
|
||||||
|
ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
|
||||||
|
LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
|
||||||
|
zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
|
||||||
|
9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
|
||||||
|
CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
|
||||||
|
em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
|
||||||
|
CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
|
||||||
|
hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
|
||||||
|
y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
|
||||||
|
-----END CERTIFICATE-----
|
@ -16,7 +16,7 @@ const (
|
|||||||
defaultStatus = 200
|
defaultStatus = 200
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResponseWriter interface {
|
type responseWriterBase interface {
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
http.Hijacker
|
http.Hijacker
|
||||||
http.Flusher
|
http.Flusher
|
||||||
|
12
response_writer_1.7.go
Normal file
12
response_writer_1.7.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// +build !go1.8
|
||||||
|
|
||||||
|
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gin
|
||||||
|
|
||||||
|
// ResponseWriter ...
|
||||||
|
type ResponseWriter interface {
|
||||||
|
responseWriterBase
|
||||||
|
}
|
25
response_writer_1.8.go
Normal file
25
response_writer_1.8.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// +build go1.8
|
||||||
|
|
||||||
|
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ResponseWriter ...
|
||||||
|
type ResponseWriter interface {
|
||||||
|
responseWriterBase
|
||||||
|
// get the http.Pusher for server push
|
||||||
|
Pusher() http.Pusher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *responseWriter) Pusher() (pusher http.Pusher) {
|
||||||
|
if pusher, ok := w.ResponseWriter.(http.Pusher); ok {
|
||||||
|
return pusher
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user