Fiber 에는 timeout 미들웨어의 두 가지 구현이 존재합니다.
New
fiber.Handler
를 timeout으로 래핑합니다. 핸들러가 주어진 시간보다 오래 걸리면 timeout 에러가 설정되고 중앙 집중식 [ErrorHandler](https://docs.gofiber.io/error-handling)로 전달됩니다.
이는 race condition을 일으키므로 deprecated 되었습니다.
NewWithContext
fiber.Handler
래퍼로, context.WithTimeout
으로 컨텍스트를 생성하고 UserContext
에 전달합니다.
전달된 컨텍스트 실행(예: DB 작업, Http 호출)이 주어진 시간보다 오래 걸리면 timeout 에러가 설정되고 중앙 집중식 ErrorHandler
로 전달됩니다.
오래 실행되는 작업을 취소하지는 않습니다. 기본 실행은 context.Context
매개변수를 사용하여 timeout을 처리해야 합니다.
Signatures
func New(handler fiber.Handler, timeout time.Duration, timeoutErrors ...error) fiber.Handler
func NewWithContext(handler fiber.Handler, timeout time.Duration, timeoutErrors ...error) fiber.Handler
Examples
Fiber 웹 프레임워크의 일부인 미들웨어 패키지를 가져옵니다
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/timeout"
)
Fiber 앱을 초기화한 후에는 다음과 같은 가능성을 사용할 수 있습니다:
func main() {
app := fiber.New()
h := func(c *fiber.Ctx) error {
sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms")
if err := sleepWithContext(c.UserContext(), sleepTime); err != nil {
return fmt.Errorf("%w: execution error", err)
}
return nil
}
app.Get("/foo/:sleepTime", timeout.New(h, 2*time.Second))
log.Fatal(app.Listen(":3000"))
}
func sleepWithContext(ctx context.Context, d time.Duration) error {
timer := time.NewTimer(d)
select {
case <-ctx.Done():
if !timer.Stop() {
<-timer.C
}
return context.DeadlineExceeded
case <-timer.C:
}
return nil
}
curl로 http 200 테스트:
curl --location -I --request GET 'http://localhost:3000/foo/1000'
curl로 http 408 테스트:
curl --location -I --request GET 'http://localhost:3000/foo/3000'
커스텀 에러와 함께 사용:
var ErrFooTimeOut = errors.New("foo context canceled")
func main() {
app := fiber.New()
h := func(c *fiber.Ctx) error {
sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms")
if err := sleepWithContextWithCustomError(c.UserContext(), sleepTime); err != nil {
return fmt.Errorf("%w: execution error", err)
}
return nil
}
app.Get("/foo/:sleepTime", timeout.NewWithContext(h, 2*time.Second, ErrFooTimeOut))
log.Fatal(app.Listen(":3000"))
}
func sleepWithContextWithCustomError(ctx context.Context, d time.Duration) error {
timer := time.NewTimer(d)
select {
case <-ctx.Done():
if !timer.Stop() {
<-timer.C
}
return ErrFooTimeOut
case <-timer.C:
}
return nil
}
DB 호출과 함께 사용 예제:
func main() {
app := fiber.New()
db, _ := gorm.Open(postgres.Open("postgres://localhost/foodb"), &gorm.Config{})
handler := func(ctx *fiber.Ctx) error {
tran := db.WithContext(ctx.UserContext()).Begin()
if tran = tran.Exec("SELECT pg_sleep(50)"); tran.Error != nil {
return tran.Error
}
if tran = tran.Commit(); tran.Error != nil {
return tran.Error
}
return nil
}
app.Get("/foo", timeout.NewWithContext(handler, 10*time.Second))
log.Fatal(app.Listen(":3000"))
}
Last updated