diff options
| author | Adnan Maolood <[email protected]> | 2021-02-24 08:18:21 -0500 |
|---|---|---|
| committer | Adnan Maolood <[email protected]> | 2021-02-24 08:18:23 -0500 |
| commit | 069b473c2816e052dae82f81c812d21848056c78 (patch) | |
| tree | a27594ee9f72a3aabf10f79c248fed1659eac8ca /handler.go | |
| parent | Only use fs.go when fs.FS is available (diff) | |
| download | go-gemini-069b473c2816e052dae82f81c812d21848056c78.tar.xz go-gemini-069b473c2816e052dae82f81c812d21848056c78.zip | |
Implement TimeoutHandler by wrapping ResponseWriter
Diffstat (limited to 'handler.go')
| -rw-r--r-- | handler.go | 57 |
1 files changed, 50 insertions, 7 deletions
@@ -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() +} |