123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- // timer.go contains methods for storing, retrieving and checking
- // timer in a request context.
- package server
- import (
- "context"
- "net/http"
- "time"
- "github.com/imgproxy/imgproxy/v3/ierrors"
- )
- // timerSinceCtxKey represents a context key for start time.
- type timerSinceCtxKey struct{}
- // startRequestTimer starts a new request timer.
- func startRequestTimer(r *http.Request, timeout time.Duration) (*http.Request, context.CancelFunc) {
- ctx := r.Context()
- ctx = context.WithValue(ctx, timerSinceCtxKey{}, time.Now())
- ctx, cancel := context.WithTimeout(ctx, timeout)
- return r.WithContext(ctx), cancel
- }
- // requestStartedAt returns the duration since the timer started in the context.
- func requestStartedAt(ctx context.Context) time.Duration {
- if t, ok := ctx.Value(timerSinceCtxKey{}).(time.Time); ok {
- return time.Since(t)
- }
- return 0
- }
- // CheckTimeout checks if the request context has timed out or cancelled and returns
- // wrapped error.
- func CheckTimeout(ctx context.Context) error {
- select {
- case <-ctx.Done():
- d := requestStartedAt(ctx)
- err := ctx.Err()
- switch err {
- case context.Canceled:
- return newRequestCancelledError(d)
- case context.DeadlineExceeded:
- return newRequestTimeoutError(d)
- default:
- return ierrors.Wrap(err, 0, ierrors.WithCategory(categoryTimeout))
- }
- default:
- return nil
- }
- }
|