diff --git a/_example/example03/main.go b/_example/example03/main.go index 97aabd3..ba48ec6 100644 --- a/_example/example03/main.go +++ b/_example/example03/main.go @@ -14,9 +14,6 @@ func main() { r.Use(timeout.New( timeout.WithTimeout(100*time.Microsecond), - timeout.WithHandler(func(c *gin.Context) { - c.String(http.StatusRequestTimeout, "timeout") - }), ), func(c *gin.Context) { c.Next() diff --git a/_example/example04/README.md b/_example/example04/README.md new file mode 100644 index 0000000..89ea79f --- /dev/null +++ b/_example/example04/README.md @@ -0,0 +1,69 @@ +# Example 04: Gin Timeout & Admin Middleware Demo + +This example demonstrates the use of the [`timeout`](https://github.com/gin-contrib/timeout) middleware and a custom admin (auth) middleware in a Gin web server. + +## How to Run + +```bash +cd _example/example04 +go run main.go +``` + +The server will start on [http://localhost:8080](http://localhost:8080). + +## Middleware Stack + +1. **Logger**: Logs all requests. +2. **Timeout**: Aborts requests taking longer than 500ms, returning HTTP 408 (Request Timeout) with body `timeout`. +3. **Auth Middleware**: If the query parameter `debug=true` is present, aborts with HTTP 401 (Unauthorized). +4. **Recovery**: Recovers from panics. + +## Route + +- `GET /` + Sleeps for 1 second, then responds with "Hello world!" (but will always timeout due to the 500ms limit). + +--- + +## Testing 408 (Request Timeout) + +Any request to `/` will trigger the timeout middleware, since the handler sleeps for 1 second (exceeding the 500ms timeout). + +```bash +curl -i http://localhost:8080/ +``` + +**Expected response:** + +```bash +HTTP/1.1 408 Request Timeout +Content-Type: text/plain; charset=utf-8 + +timeout +``` + +## Testing 401 (Unauthorized) + +To trigger the 401 response from the admin (auth) middleware, add the `debug=true` query parameter: + +```bash +curl -i "http://localhost:8080/?debug=true" +``` + +**Expected response:** + +```bash +HTTP/1.1 401 Unauthorized +Content-Type: text/plain; charset=utf-8 +``` + +> **Note:** +> Because the `/` handler always sleeps for 1 second, the timeout middleware (408) will usually trigger before the 401. +> To reliably test the 401, you can temporarily comment out the `time.Sleep(1000 * time.Millisecond)` line in `main.go` and restart the server. + +--- + +## Summary + +- **408**: Triggered by slow handler (default behavior). +- **401**: Triggered by `?debug=true` (if handler is fast enough). diff --git a/_example/example04/go.mod b/_example/example04/go.mod new file mode 100644 index 0000000..6dbd674 --- /dev/null +++ b/_example/example04/go.mod @@ -0,0 +1,38 @@ +module example04 + +go 1.24.3 + +require ( + github.com/gin-contrib/timeout v1.0.2 + github.com/gin-gonic/gin v1.10.1 +) + +require ( + github.com/bytedance/sonic v1.13.2 // indirect + github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/cloudwego/base64x v0.1.5 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v1.0.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.26.0 // indirect + github.com/goccy/go-json v0.10.5 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.16.0 // indirect + golang.org/x/crypto v0.37.0 // indirect + golang.org/x/net v0.38.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/text v0.24.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/gin-contrib/timeout => ../../ diff --git a/_example/example04/go.sum b/_example/example04/go.sum new file mode 100644 index 0000000..2da4720 --- /dev/null +++ b/_example/example04/go.sum @@ -0,0 +1,86 @@ +github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= +github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= +github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= +github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E= +github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= +github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= +github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= +github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U= +golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/_example/example04/main.go b/_example/example04/main.go new file mode 100644 index 0000000..d6c45db --- /dev/null +++ b/_example/example04/main.go @@ -0,0 +1,52 @@ +package main + +import ( + "log" + "net/http" + "time" + + "github.com/gin-contrib/timeout" + "github.com/gin-gonic/gin" +) + +func testResponse(c *gin.Context) { + c.String(http.StatusRequestTimeout, "timeout") +} + +// custom middleware straight from example +func timeoutMiddleware() gin.HandlerFunc { + return timeout.New( + timeout.WithTimeout(500*time.Millisecond), + timeout.WithResponse(testResponse), + ) +} + +// simple middleware to always throw a 401 +func authMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + debug := c.Query("debug") + if debug != "true" { + c.Next() + return + } + c.AbortWithStatus(401) + } +} + +func main() { + r := gin.New() + + // middleware + r.Use(gin.Logger()) + r.Use(timeoutMiddleware()) // 1. timeout middleware + r.Use(authMiddleware()) // 2. auth middleware + r.Use(gin.Recovery()) // recommend to use this middleware to recover from any panics in the handlers. + + r.GET("/", func(c *gin.Context) { + time.Sleep(1000 * time.Millisecond) + c.String(http.StatusOK, "Hello world!") + }) + if err := r.Run(":8080"); err != nil { + log.Fatal(err) + } +} diff --git a/option.go b/option.go index dfb29a2..4e700b1 100644 --- a/option.go +++ b/option.go @@ -17,13 +17,6 @@ func WithTimeout(timeout time.Duration) Option { } } -// WithHandler add gin handler -func WithHandler(h gin.HandlerFunc) Option { - return func(t *Timeout) { - t.handler = h - } -} - // WithResponse add gin handler func WithResponse(h gin.HandlerFunc) Option { return func(t *Timeout) { @@ -38,6 +31,5 @@ func defaultResponse(c *gin.Context) { // Timeout struct type Timeout struct { timeout time.Duration - handler gin.HandlerFunc response gin.HandlerFunc } diff --git a/timeout.go b/timeout.go index 1a8a625..ee20f1b 100644 --- a/timeout.go +++ b/timeout.go @@ -19,7 +19,6 @@ const ( func New(opts ...Option) gin.HandlerFunc { t := &Timeout{ timeout: defaultTimeout, - handler: nil, response: defaultResponse, } @@ -33,16 +32,6 @@ func New(opts ...Option) gin.HandlerFunc { opt(t) } - // Ensure handler is set - if t.handler == nil { - panic("timeout handler must not be nil") - } - - // If timeout is not set or is negative, return the original handler directly (no timeout logic). - if t.timeout <= 0 { - return t.handler - } - // Initialize the buffer pool for response writers. bufPool = &BufferPool{} @@ -80,7 +69,7 @@ func New(opts ...Option) gin.HandlerFunc { } }() // Use the copied context to avoid data race when running handler in a goroutine. - t.handler(cCopy) + c.Next() finish <- struct{}{} }() diff --git a/timeout_test.go b/timeout_test.go index ddff5b4..0dcae24 100644 --- a/timeout_test.go +++ b/timeout_test.go @@ -19,7 +19,26 @@ func emptySuccessResponse(c *gin.Context) { func TestTimeout(t *testing.T) { r := gin.New() - r.GET("/", New(WithTimeout(50*time.Microsecond), WithHandler(emptySuccessResponse))) + r.GET("/", New( + WithTimeout(50*time.Microsecond), + ), + emptySuccessResponse, + ) + + w := httptest.NewRecorder() + req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil) + r.ServeHTTP(w, req) + + assert.Equal(t, http.StatusRequestTimeout, w.Code) + assert.Equal(t, http.StatusText(http.StatusRequestTimeout), w.Body.String()) +} + +func TestTimeoutWithUse(t *testing.T) { + r := gin.New() + r.Use(New( + WithTimeout(50 * time.Microsecond), + )) + r.GET("/", emptySuccessResponse) w := httptest.NewRecorder() req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil) @@ -31,14 +50,18 @@ func TestTimeout(t *testing.T) { func TestWithoutTimeout(t *testing.T) { r := gin.New() - r.GET("/", New(WithTimeout(-1*time.Microsecond), WithHandler(emptySuccessResponse))) + r.GET("/", New( + WithTimeout(-1*time.Microsecond), + ), + emptySuccessResponse, + ) w := httptest.NewRecorder() req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) - assert.Equal(t, "", w.Body.String()) + assert.Equal(t, http.StatusRequestTimeout, w.Code) + assert.Equal(t, http.StatusText(http.StatusRequestTimeout), w.Body.String()) } func testResponse(c *gin.Context) { @@ -49,9 +72,10 @@ func TestCustomResponse(t *testing.T) { r := gin.New() r.GET("/", New( WithTimeout(100*time.Microsecond), - WithHandler(emptySuccessResponse), WithResponse(testResponse), - )) + ), + emptySuccessResponse, + ) w := httptest.NewRecorder() req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil) @@ -70,9 +94,10 @@ func TestSuccess(t *testing.T) { r := gin.New() r.GET("/", New( WithTimeout(1*time.Second), - WithHandler(emptySuccessResponse2), WithResponse(testResponse), - )) + ), + emptySuccessResponse2, + ) w := httptest.NewRecorder() req, _ := http.NewRequestWithContext(context.Background(), "GET", "/", nil) @@ -86,14 +111,15 @@ func TestLargeResponse(t *testing.T) { r := gin.New() r.GET("/slow", New( WithTimeout(1*time.Second), - WithHandler(func(c *gin.Context) { - time.Sleep(2 * time.Second) // wait almost same as timeout - c.String(http.StatusBadRequest, `{"error": "handler error"}`) - }), WithResponse(func(c *gin.Context) { c.String(http.StatusRequestTimeout, `{"error": "timeout error"}`) }), - )) + ), + func(c *gin.Context) { + time.Sleep(2 * time.Second) // wait almost same as timeout + c.String(http.StatusBadRequest, `{"error": "handler error"}`) + }, + ) wg := sync.WaitGroup{} for i := 0; i < 10; i++ { @@ -119,10 +145,12 @@ func TestNoNextAfterTimeout(t *testing.T) { called := false r.Use(New( WithTimeout(50*time.Millisecond), - WithHandler(func(c *gin.Context) { + ), + func(c *gin.Context) { time.Sleep(100 * time.Millisecond) c.String(http.StatusOK, "should not reach") - }))) + }, + ) r.Use(func(c *gin.Context) { called = true }) @@ -150,10 +178,11 @@ func TestTimeoutPanic(t *testing.T) { // Register the timeout middleware; the handler will panic. r.GET("/panic", New( WithTimeout(100*time.Millisecond), - WithHandler(func(c *gin.Context) { + ), + func(c *gin.Context) { panic("timeout panic test") - }), - )) + }, + ) w := httptest.NewRecorder() req, _ := http.NewRequestWithContext(context.Background(), "GET", "/panic", nil) diff --git a/writer_test.go b/writer_test.go index ecaa6eb..bc3b430 100644 --- a/writer_test.go +++ b/writer_test.go @@ -44,9 +44,6 @@ func TestWriter_Status(t *testing.T) { r.Use(New( WithTimeout(1*time.Second), - WithHandler(func(c *gin.Context) { - c.Next() - }), WithResponse(testResponse), )) @@ -75,7 +72,6 @@ func TestWriter_Status(t *testing.T) { func testNew(duration time.Duration) gin.HandlerFunc { return New( WithTimeout(duration), - WithHandler(func(c *gin.Context) { c.Next() }), WithResponse(timeoutHandler()), ) }