diff options
| author | Adnan Maolood <[email protected]> | 2021-02-23 22:12:04 -0500 |
|---|---|---|
| committer | Adnan Maolood <[email protected]> | 2021-02-23 22:12:04 -0500 |
| commit | f08efa330f7fbb8c7d0866f091fde7ace8ad1347 (patch) | |
| tree | 6ee8e3ffe82ab91cf5c5d26f2793b088be03b3eb | |
| parent | Unexport NewResponseWriter (diff) | |
| download | go-gemini-f08efa330f7fbb8c7d0866f091fde7ace8ad1347.tar.xz go-gemini-f08efa330f7fbb8c7d0866f091fde7ace8ad1347.zip | |
Move TimeoutHandler to handler.go
| -rw-r--r-- | handler.go | 44 | ||||
| -rw-r--r-- | timeout.go | 49 |
2 files changed, 44 insertions, 49 deletions
@@ -1,9 +1,11 @@ package gemini import ( + "bytes" "context" "net/url" "strings" + "time" ) // A Handler responds to a Gemini request. @@ -72,3 +74,45 @@ func StripPrefix(prefix string, h Handler) Handler { } }) } + +// TimeoutHandler returns a Handler that runs h with the given time limit. +// +// The new Handler calls h.ServeGemini to handle each request, but +// if a call runs for longer than its time limit, the handler responds with a +// 40 Temporary Failure error. After such a timeout, writes by h to its +// ResponseWriter will return ErrHandlerTimeout. +func TimeoutHandler(h Handler, dt time.Duration) Handler { + return &timeoutHandler{ + h: h, + dt: dt, + } +} + +type timeoutHandler struct { + h Handler + dt time.Duration +} + +func (t *timeoutHandler) ServeGemini(ctx context.Context, w *ResponseWriter, r *Request) { + ctx, cancel := context.WithTimeout(ctx, t.dt) + defer cancel() + + conn := w.Hijack() + + var b bytes.Buffer + w.reset(nopCloser{&b}) + + done := make(chan struct{}) + go func() { + t.h.ServeGemini(ctx, w, r) + close(done) + }() + + select { + case <-done: + conn.Write(b.Bytes()) + case <-ctx.Done(): + w.reset(conn) + w.WriteHeader(StatusTemporaryFailure, "Timeout") + } +} diff --git a/timeout.go b/timeout.go deleted file mode 100644 index d879a84..0000000 --- a/timeout.go +++ /dev/null @@ -1,49 +0,0 @@ -package gemini - -import ( - "bytes" - "context" - "time" -) - -// TimeoutHandler returns a Handler that runs h with the given time limit. -// -// The new Handler calls h.ServeGemini to handle each request, but -// if a call runs for longer than its time limit, the handler responds with a -// 40 Temporary Failure error. After such a timeout, writes by h to its -// ResponseWriter will return ErrHandlerTimeout. -func TimeoutHandler(h Handler, dt time.Duration) Handler { - return &timeoutHandler{ - h: h, - dt: dt, - } -} - -type timeoutHandler struct { - h Handler - dt time.Duration -} - -func (t *timeoutHandler) ServeGemini(ctx context.Context, w *ResponseWriter, r *Request) { - ctx, cancel := context.WithTimeout(ctx, t.dt) - defer cancel() - - conn := w.Hijack() - - var b bytes.Buffer - w.reset(nopCloser{&b}) - - done := make(chan struct{}) - go func() { - t.h.ServeGemini(ctx, w, r) - close(done) - }() - - select { - case <-done: - conn.Write(b.Bytes()) - case <-ctx.Done(): - w.reset(conn) - w.WriteHeader(StatusTemporaryFailure, "Timeout") - } -} |