Merge abb9d470f2a8d475c58bf0c1c8f69822ffe86d01 into 3f27866f806536be319b3e342001dd4e0fb81691

This commit is contained in:
Jim Lambert 2018-09-12 15:29:16 +00:00 committed by GitHub
commit b30b1d9ee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 0 deletions

View File

@ -58,6 +58,7 @@ Gin is a web framework written in Go (Golang). It features a martini-like API wi
- [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) - [http2 server push](#http2-server-push)
- [Support limiting the number of accepted requests using netutil.LimitListener](#RunLimited)
- [Testing](#testing) - [Testing](#testing)
- [Users](#users) - [Users](#users)
@ -1835,6 +1836,29 @@ func main() {
} }
``` ```
### RunLimited
Limit the number of accepted requests via [netutils.LimitListener](https://godoc.org/golang.org/x/net/netutil)
[embedmd]:# (examples/run-limited/main.go go)
```go
package main
import "github.com/gin-gonic/gin"
const maxConnections = 10
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.RunLimited(maxConnections, ":80") // listen and serve on 0.0.0.0:8080
}
```
## Testing ## Testing
The `net/http/httptest` package is preferable way for HTTP testing. The `net/http/httptest` package is preferable way for HTTP testing.

View File

@ -0,0 +1,14 @@
package main
import "github.com/gin-gonic/gin"
const maxConnections = 10
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.RunLimited(maxConnections, ":80") // listen and serve on 0.0.0.0:8080
}

38
gin.go
View File

@ -10,8 +10,10 @@ import (
"net/http" "net/http"
"os" "os"
"sync" "sync"
"time"
"github.com/gin-gonic/gin/render" "github.com/gin-gonic/gin/render"
"golang.org/x/net/netutil"
) )
const ( const (
@ -288,6 +290,42 @@ func (engine *Engine) Run(addr ...string) (err error) {
return return
} }
// RunLimited - use netuil.LimitListener to limit the number of inbound accepts
func (engine *GalapagosEngine) RunLimited(limit int, addr ...string) (err error) {
defer func() { debugPrintError(err) }()
address := resolveAddress(addr)
debugPrint("Listening and serving HTTP on %s\n", address)
// err = http.ListenAndServe(address, engine)
srv := &http.Server{Addr: address, Handler: engine}
address = srv.Addr
if address == "" {
address = ":http"
}
ln, err := net.Listen("tcp", address)
if err != nil {
return err
}
lnLimited := netutil.LimitListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, limit)
return srv.Serve(lnLimited)
}
type tcpKeepAliveListener struct {
*net.TCPListener
}
func (ln tcpKeepAliveListener) Accept() (net.Conn, error) {
tc, err := ln.AcceptTCP()
if err != nil {
return nil, err
}
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(3 * time.Minute)
return tc, nil
}
// RunTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests. // RunTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests.
// It is a shortcut for http.ListenAndServeTLS(addr, certFile, keyFile, router) // It is a shortcut for http.ListenAndServeTLS(addr, certFile, keyFile, router)
// Note: this method will block the calling goroutine indefinitely unless an error happens. // Note: this method will block the calling goroutine indefinitely unless an error happens.