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)
|
||||
- [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)
|
||||
- [http2 server push](#http2-server-push)
|
||||
- [Testing](#testing)
|
||||
- [Users](#users--)
|
||||
|
||||
@ -1656,6 +1657,55 @@ enough to call binding at once.
|
||||
can be called by `c.ShouldBind()` multiple times without any damage to
|
||||
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
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
type ResponseWriter interface {
|
||||
type responseWriterBase interface {
|
||||
http.ResponseWriter
|
||||
http.Hijacker
|
||||
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