Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [#504] Route supports configure timeout #97

Merged
merged 32 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8bd8af2
Update context.go
KlassnayaAfrodita Oct 9, 2024
6e09e22
Update context_test.go
KlassnayaAfrodita Oct 10, 2024
25ba222
Update route.go
KlassnayaAfrodita Oct 11, 2024
c7f81ea
Create timeoutMiddleware.go
KlassnayaAfrodita Oct 13, 2024
4963969
Update route.go
KlassnayaAfrodita Oct 13, 2024
c0c1222
Update timeoutMiddleware.go
KlassnayaAfrodita Oct 13, 2024
d890362
Update timeoutMiddleware.go
KlassnayaAfrodita Oct 13, 2024
b3a3267
Update route.go
KlassnayaAfrodita Oct 13, 2024
11475d3
Update route.go
KlassnayaAfrodita Oct 13, 2024
94b45f0
Update timeoutMiddleware.go
KlassnayaAfrodita Oct 13, 2024
4ec125d
Update timeoutMiddleware.go
KlassnayaAfrodita Oct 15, 2024
02287ab
Rename timeoutMiddleware.go to timeout_middleware.go
KlassnayaAfrodita Oct 15, 2024
e920b4a
Rename tls.go to tls_middleware.go
KlassnayaAfrodita Oct 15, 2024
c07c05d
Update timeout_middleware.go
KlassnayaAfrodita Oct 15, 2024
9a463c5
Update timeout_middleware.go
KlassnayaAfrodita Oct 16, 2024
3e30263
Update timeout_middleware.go
KlassnayaAfrodita Oct 17, 2024
0fa7a3c
Update route.go
KlassnayaAfrodita Oct 17, 2024
53e56ac
Update route_test.go
KlassnayaAfrodita Oct 17, 2024
f3c2a10
Update route_test.go
KlassnayaAfrodita Oct 18, 2024
ec3ded3
Update route_test.go
KlassnayaAfrodita Oct 18, 2024
22e1c33
Update route_test.go
KlassnayaAfrodita Oct 19, 2024
087bf1b
Update timeout_middleware.go
KlassnayaAfrodita Oct 24, 2024
86f5d3b
Update route.go
KlassnayaAfrodita Oct 24, 2024
18ee0ea
Update route_test.go
KlassnayaAfrodita Oct 24, 2024
ec70760
Update route_test.go
KlassnayaAfrodita Oct 24, 2024
c67ff88
Update timeout_middleware.go
KlassnayaAfrodita Oct 24, 2024
051970a
Update timeout_middleware.go
KlassnayaAfrodita Oct 24, 2024
66aa240
Update route_test.go
KlassnayaAfrodita Oct 25, 2024
7a0668e
optimize timeout middleware
hwbrzzl Oct 25, 2024
b4c16c6
Merge pull request #1 from KlassnayaAfrodita/bowen/timeout-middleware
KlassnayaAfrodita Oct 26, 2024
8fd8b39
Merge branch 'master' into patch-1
KlassnayaAfrodita Oct 26, 2024
49bbdd6
Update middleware_timeout_test.go
KlassnayaAfrodita Oct 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ func (c *Context) WithValue(key any, value any) {
c.instance.Set(goravelContextKey, goravelCtx)
}

func (c *Context) WithContext(ctx context.Context) {
// Changing the request context to a new context
c.instance.Request = c.instance.Request.WithContext(ctx)
}

func (c *Context) Context() context.Context { return c }

func (c *Context) Deadline() (deadline time.Time, ok bool) {
Expand Down
33 changes: 33 additions & 0 deletions context_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package gin

import (
"context"
"testing"
"time"

"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -30,3 +32,34 @@ func TestContext(t *testing.T) {
assert.Equal(t, "one", ctx.Value(1))
assert.Equal(t, "two point two", ctx.Value(2.2))
}

func TestWithContext(t *testing.T) {
httpCtx := Background()

timeoutCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

httpCtx.WithContext(timeoutCtx)

ctx := httpCtx.Context()
assert.Equal(t, timeoutCtx, ctx)

deadline, ok := ctx.Deadline()
assert.True(t, ok, "Deadline should be set")
assert.WithinDuration(t, time.Now().Add(2*time.Second), deadline, 50*time.Millisecond, "Deadline should be approximately 2 seconds from now")

select {
case <-ctx.Done():
assert.Fail(t, "context should not be done yet")
default:

}
time.Sleep(2 * time.Second)

select {
case <-ctx.Done():
assert.Equal(t, context.DeadlineExceeded, ctx.Err(), "context should be exceeded")
default:
assert.Fail(t, "context should be done after timeout")
}
}
3 changes: 2 additions & 1 deletion route.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add test cases for the new logic in route_test.go.

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func NewRoute(config config.Config, parameters map[string]any) (*Route, error) {
engine := gin.New()
engine.MaxMultipartMemory = int64(config.GetInt("http.drivers.gin.body_limit", 4096)) << 10
engine.Use(gin.Recovery()) // recovery middleware

if debugLog := getDebugLog(config); debugLog != nil {
engine.Use(debugLog)
}
Expand Down Expand Up @@ -77,7 +78,7 @@ func (r *Route) Fallback(handler httpcontract.HandlerFunc) {
}

func (r *Route) GlobalMiddleware(middlewares ...httpcontract.Middleware) {
middlewares = append(middlewares, Cors(), Tls())
middlewares = append(middlewares, Cors(), Tls(), TimeoutMiddleware(r.config))
r.instance.Use(middlewaresToGinHandlers(middlewares)...)
r.Router = NewGroup(
r.config,
Expand Down
34 changes: 34 additions & 0 deletions route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,40 @@
}
}

func longMiddleware(_ config.Config) contractshttp.Middleware {
return func(ctx contractshttp.Context) {
time.Sleep(2 * time.Second)
ctx.Request().Next()
}
}

func TestTimeoutMiddlewareIntegration(t *testing.T) {
mockConfig := configmocks.NewConfig(t)
mockConfig.EXPECT().GetInt("http.timeout_request", 3).Return(1).Once()

mockConfig.EXPECT().GetInt("http.drivers.gin.body_limit", 4096).Return(4096).Once()

mockConfig.EXPECT().GetBool("app.debug").Return(false).Once()

route, err := NewRoute(mockConfig, nil)
assert.Nil(t, err)

route.GlobalMiddleware(TimeoutMiddleware(mockConfig), longMiddleware(mockConfig)

Check failure on line 509 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

missing ',' before newline in argument list

Check failure on line 509 in route_test.go

View workflow job for this annotation

GitHub Actions / codecov / codecov

missing ',' before newline in argument list

Check failure on line 509 in route_test.go

View workflow job for this annotation

GitHub Actions / test / ubuntu (1.22)

missing ',' before newline in argument list

Check failure on line 509 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / lint

syntax error: unexpected newline in argument list; possibly missing comma or )

Check failure on line 509 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / lint

missing ',' before newline in argument list (typecheck)

Check failure on line 509 in route_test.go

View workflow job for this annotation

GitHub Actions / test / windows (1.22)

missing ',' before newline in argument list

Check failure on line 509 in route_test.go

View workflow job for this annotation

GitHub Actions / test / ubuntu (1.23)

missing ',' before newline in argument list

Check failure on line 509 in route_test.go

View workflow job for this annotation

GitHub Actions / test / windows (1.23)

missing ',' before newline in argument list

route.Get("/", func(ctx contractshttp.Context) contractshttp.Response {

Check failure on line 511 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / lint

syntax error: unexpected name contractshttp at end of statement
time.Sleep(2 * time.Second)
return ctx.Response().String(200, "Hello, World!")
})

Check failure on line 514 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

missing ',' before newline in argument list

Check failure on line 514 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / lint

syntax error: unexpected ) after top level declaration (typecheck)

Check failure on line 514 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / lint

missing ',' before newline in argument list (typecheck)

w := httptest.NewRecorder()

Check failure on line 516 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

missing ',' in argument list

Check failure on line 516 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

missing ',' before newline in argument list

Check failure on line 516 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / lint

missing ',' in argument list (typecheck)
req, _ := http.NewRequest("GET", "/", nil)

Check failure on line 517 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

missing ',' in argument list

Check failure on line 517 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

missing ',' before newline in argument list

Check failure on line 517 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / lint

missing ',' in argument list (typecheck)

route.ServeHTTP(w, req)

Check failure on line 519 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

missing ',' before newline in argument list

Check failure on line 519 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / lint

missing ',' before newline in argument list (typecheck)

assert.Equal(t, http.StatusGatewayTimeout, w.Code)

Check failure on line 521 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

missing ',' before newline in argument list
}

Check failure on line 522 in route_test.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

expected operand, found '}'


type CreateUser struct {
Name string `form:"name" json:"name"`
}
Expand Down
32 changes: 32 additions & 0 deletions timeout_middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package gin

import (
"context"
"net/http"
"time"

contractshttp "github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/config"
)

// TimeoutMiddleware creates middleware to set a timeout for a request
func TimeoutMiddleware(config config.Config) contractshttp.Middleware {
return func(ctx contractshttp.Context) {
timeout := time.Duration(config.GetInt("http.timeout_request", 1)) * time.Second
timeoutCtx, cancel := context.WithTimeout(ctx.Context(), timeout)
defer cancel()

ctx.WithContext(timeoutCtx)

Check failure on line 19 in timeout_middleware.go

View workflow job for this annotation

GitHub Actions / lint / nilaway

ctx.WithContext undefined (type "github.com/goravel/framework/contracts/http".Context has no field or method WithContext)

Check failure on line 19 in timeout_middleware.go

View workflow job for this annotation

GitHub Actions / codecov / codecov

ctx.WithContext undefined (type "github.com/goravel/framework/contracts/http".Context has no field or method WithContext)

Check failure on line 19 in timeout_middleware.go

View workflow job for this annotation

GitHub Actions / test / ubuntu (1.22)

ctx.WithContext undefined (type "github.com/goravel/framework/contracts/http".Context has no field or method WithContext)

Check failure on line 19 in timeout_middleware.go

View workflow job for this annotation

GitHub Actions / lint / lint

ctx.WithContext undefined (type "github.com/goravel/framework/contracts/http".Context has no field or method WithContext)) (typecheck)

Check failure on line 19 in timeout_middleware.go

View workflow job for this annotation

GitHub Actions / test / ubuntu (1.23)

ctx.WithContext undefined (type "github.com/goravel/framework/contracts/http".Context has no field or method WithContext)

Check failure on line 19 in timeout_middleware.go

View workflow job for this annotation

GitHub Actions / test / windows (1.23)

ctx.WithContext undefined (type "github.com/goravel/framework/contracts/http".Context has no field or method WithContext)

go ctx.Request().Next()

select {
case <-ctx.Request().Origin().Context().Done():
if timeoutCtx.Err() == context.DeadlineExceeded {
ctx.Response().Writer().WriteHeader(http.StatusGatewayTimeout)
_, _ = ctx.Response().Writer().Write([]byte("Request timed out"))
hwbrzzl marked this conversation as resolved.
Show resolved Hide resolved
ctx.Request().AbortWithStatus(http.StatusGatewayTimeout)
}
}
}
}
File renamed without changes.
Loading