add new capability to limit accepted connections

add internal package which includes json package (#1504)

chore: update vendor version (#1520)

chore: update issue_implate (#1524)

docs: add fnproject to gin's user list (#1505)

example for RunLimited

example for RunLimited

add new capability to limit accepted connections

Add golang 1.11.x testing (#1514)

* Add golang 1.11.x testing

* remove the latest golang testing

See the issue: https://github.com/gin-gonic/gin/pull/1510

Update README.md (#1509)

change  `ShouldBindXML` to `ShouldBindJSON`

add internal package which includes json package (#1504)

chore: update vendor version (#1520)

chore: update issue_implate (#1524)

docs: add fnproject to gin's user list (#1505)

added new capability to limit the accepted requests

example for RunLimited

example for RunLimited
This commit is contained in:
Jim Lambert 2018-09-11 12:35:21 -04:00
parent 0da5b0c85a
commit abb9d470f2
13 changed files with 88 additions and 35 deletions

View File

@ -3,8 +3,8 @@
- Please provide source code and commit sha if you found a bug. - Please provide source code and commit sha if you found a bug.
- Review existing issues and provide feedback or react to them. - Review existing issues and provide feedback or react to them.
- go version:
- gin version (or commit ref): - gin version (or commit ref):
- git version:
- operating system: - operating system:
## Description ## Description

View File

@ -6,7 +6,7 @@ go:
- 1.8.x - 1.8.x
- 1.9.x - 1.9.x
- 1.10.x - 1.10.x
- master - 1.11.x
git: git:
depth: 10 depth: 10

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)
@ -557,7 +558,7 @@ func main() {
// Example for binding JSON ({"user": "manu", "password": "123"}) // Example for binding JSON ({"user": "manu", "password": "123"})
router.POST("/loginJSON", func(c *gin.Context) { router.POST("/loginJSON", func(c *gin.Context) {
var json Login var json Login
if err := c.ShouldBindXML(&json); err != nil { if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
@ -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.
@ -1885,5 +1909,6 @@ func TestPingRoute(t *testing.T) {
Awesome project lists using [Gin](https://github.com/gin-gonic/gin) web framework. Awesome project lists using [Gin](https://github.com/gin-gonic/gin) web framework.
* [drone](https://github.com/drone/drone): Drone is a Continuous Delivery platform built on Docker, written in Go * [drone](https://github.com/drone/drone): Drone is a Continuous Delivery platform built on Docker, written in Go.
* [gorush](https://github.com/appleboy/gorush): A push notification server written in Go. * [gorush](https://github.com/appleboy/gorush): A push notification server written in Go.
* [fnproject](https://github.com/fnproject/fn): The container native, cloud agnostic serverless platform.

View File

@ -9,7 +9,7 @@ import (
"io" "io"
"net/http" "net/http"
"github.com/gin-gonic/gin/json" "github.com/gin-gonic/gin/internal/json"
) )
// EnableDecoderUseNumber is used to call the UseNumber method on the JSON // EnableDecoderUseNumber is used to call the UseNumber method on the JSON

View File

@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/gin-gonic/gin/json" "github.com/gin-gonic/gin/internal/json"
) )
type ErrorType uint64 type ErrorType uint64

View File

@ -8,7 +8,7 @@ import (
"errors" "errors"
"testing" "testing"
"github.com/gin-gonic/gin/json" "github.com/gin-gonic/gin/internal/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

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.

View File

@ -10,7 +10,7 @@ import (
"html/template" "html/template"
"net/http" "net/http"
"github.com/gin-gonic/gin/json" "github.com/gin-gonic/gin/internal/json"
) )
type JSON struct { type JSON struct {

View File

@ -9,7 +9,7 @@ package render
import ( import (
"net/http" "net/http"
"github.com/gin-gonic/gin/json" "github.com/gin-gonic/gin/internal/json"
) )
type PureJSON struct { type PureJSON struct {

28
vendor/vendor.json vendored
View File

@ -27,8 +27,8 @@
"path": "github.com/json-iterator/go", "path": "github.com/json-iterator/go",
"revision": "1624edc4454b8682399def8740d46db5e4362ba4", "revision": "1624edc4454b8682399def8740d46db5e4362ba4",
"revisionTime": "2018-08-06T06:07:27Z", "revisionTime": "2018-08-06T06:07:27Z",
"version": "1.1.5", "version": "v1.1",
"versionExact": "1.1.5" "versionExact": "v1.1.5"
}, },
{ {
"checksumSHA1": "y/A5iuvwjytQE2CqVuphQRXR2nI=", "checksumSHA1": "y/A5iuvwjytQE2CqVuphQRXR2nI=",
@ -38,24 +38,6 @@
"version": "v0.0.3", "version": "v0.0.3",
"versionExact": "v0.0.3" "versionExact": "v0.0.3"
}, },
{
"checksumSHA1": "ZTcgWKWHsrX0RXYVXn5Xeb8Q0go=",
"path": "github.com/modern-go/concurrent",
"revision": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94",
"revisionTime": "2018-03-06T01:26:44Z"
},
{
"checksumSHA1": "qvH48wzTIV3QKSDqI0dLFtVjaDI=",
"path": "github.com/modern-go/reflect2",
"revision": "94122c33edd36123c84d5368cfb2b69df93a0ec8",
"revisionTime": "2018-07-18T01:23:57Z"
},
{
"checksumSHA1": "LuFv4/jlrmFNnDb/5SCSEPAM9vU=",
"path": "github.com/pmezard/go-difflib/difflib",
"revision": "792786c7400a136282c1664665ae0a8db921c6c2",
"revisionTime": "2016-01-10T10:55:54Z"
},
{ {
"checksumSHA1": "c6pbpF7eowwO59phRTpF8cQ80Z0=", "checksumSHA1": "c6pbpF7eowwO59phRTpF8cQ80Z0=",
"path": "github.com/stretchr/testify/assert", "path": "github.com/stretchr/testify/assert",
@ -79,12 +61,6 @@
"revision": "d4c55e66d8c3a2f3382d264b08e3e3454a66355a", "revision": "d4c55e66d8c3a2f3382d264b08e3e3454a66355a",
"revisionTime": "2016-10-18T08:54:36Z" "revisionTime": "2016-10-18T08:54:36Z"
}, },
{
"checksumSHA1": "7Gocawl8bm27cpAILtuf21xvVD8=",
"path": "golang.org/x/sys/unix",
"revision": "1c9583448a9c3aa0f9a6a5241bf73c0bd8aafded",
"revisionTime": "2018-08-15T07:37:39Z"
},
{ {
"checksumSHA1": "P/k5ZGf0lEBgpKgkwy++F7K1PSg=", "checksumSHA1": "P/k5ZGf0lEBgpKgkwy++F7K1PSg=",
"path": "gopkg.in/go-playground/validator.v8", "path": "gopkg.in/go-playground/validator.v8",