1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-12-23 22:11:10 +02:00
Files
imgproxy/server/timer.go
Sergei Aleksandrovich e33254005d Refactored errors (#1578)
* Refactored errors

* Make monitoring and errorreport accept `errctx.Error` instead of `error`

* Add server.Error; Remove category from errctx; Make HTTP handlers respond with *server.Error

* Remove stackSkip from errctx.Wrap; Add errctx.WrapWithStackSkip
2025-11-20 01:26:21 +06:00

52 lines
1.3 KiB
Go

// 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/errctx"
)
// 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) errctx.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 errctx.Wrap(err)
}
default:
return nil
}
}