aboutsummaryrefslogtreecommitdiff
path: root/handler.go
diff options
context:
space:
mode:
authorAdnan Maolood <[email protected]>2021-02-24 08:18:21 -0500
committerAdnan Maolood <[email protected]>2021-02-24 08:18:23 -0500
commit069b473c2816e052dae82f81c812d21848056c78 (patch)
treea27594ee9f72a3aabf10f79c248fed1659eac8ca /handler.go
parentOnly use fs.go when fs.FS is available (diff)
downloadgo-gemini-069b473c2816e052dae82f81c812d21848056c78.tar.xz
go-gemini-069b473c2816e052dae82f81c812d21848056c78.zip
Implement TimeoutHandler by wrapping ResponseWriter
Diffstat (limited to 'handler.go')
-rw-r--r--handler.go57
1 files changed, 50 insertions, 7 deletions
diff --git a/handler.go b/handler.go
index e695c11..5c7d9aa 100644
--- a/handler.go
+++ b/handler.go
@@ -3,6 +3,7 @@ package gemini
import (
"bytes"
"context"
+ "io"
"net/url"
"strings"
"time"
@@ -96,22 +97,64 @@ func (t *timeoutHandler) ServeGemini(ctx context.Context, w ResponseWriter, r *R
ctx, cancel := context.WithTimeout(ctx, t.dt)
defer cancel()
- conn := w.Hijack()
-
- var b bytes.Buffer
- w.reset(nopCloser{&b})
+ buf := &bytes.Buffer{}
+ tw := &timeoutWriter{
+ wc: &contextWriter{
+ ctx: ctx,
+ cancel: cancel,
+ done: ctx.Done(),
+ wc: nopCloser{buf},
+ },
+ }
done := make(chan struct{})
go func() {
- t.h.ServeGemini(ctx, w, r)
+ t.h.ServeGemini(ctx, tw, r)
close(done)
}()
select {
case <-done:
- conn.Write(b.Bytes())
+ w.WriteHeader(tw.status, tw.meta)
+ w.Write(buf.Bytes())
case <-ctx.Done():
- w.reset(conn)
w.WriteHeader(StatusTemporaryFailure, "Timeout")
}
}
+
+type timeoutWriter struct {
+ ResponseWriter
+ wc io.WriteCloser
+ status Status
+ meta string
+ mediatype string
+ wroteHeader bool
+}
+
+func (w *timeoutWriter) SetMediaType(mediatype string) {
+ w.mediatype = mediatype
+}
+
+func (w *timeoutWriter) Write(b []byte) (int, error) {
+ if !w.wroteHeader {
+ w.WriteHeader(StatusSuccess, w.mediatype)
+ }
+ return w.wc.Write(b)
+}
+
+func (w *timeoutWriter) WriteHeader(status Status, meta string) {
+ if w.wroteHeader {
+ return
+ }
+ w.status = status
+ w.meta = meta
+ w.wroteHeader = true
+}
+
+func (w *timeoutWriter) Flush() error {
+ return nil
+}
+
+func (w *timeoutWriter) Close() error {
+ return w.wc.Close()
+}