(w http.ResponseWriter, r *http.Request)
| 63 | } |
| 64 | |
| 65 | func (h *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
| 66 | ctx := h.testContext |
| 67 | if ctx == nil { |
| 68 | var cancelCtx context.CancelFunc |
| 69 | ctx, cancelCtx = context.WithTimeout(r.Context(), h.dt) |
| 70 | defer cancelCtx() |
| 71 | } |
| 72 | r = r.WithContext(ctx) |
| 73 | done := make(chan struct{}) |
| 74 | tw := &timeoutWriter{ |
| 75 | w: w, |
| 76 | h: make(http.Header), |
| 77 | req: r, |
| 78 | } |
| 79 | panicChan := make(chan interface{}, 1) |
| 80 | go func() { |
| 81 | defer func() { |
| 82 | if p := recover(); p != nil { |
| 83 | panicChan <- p |
| 84 | } |
| 85 | }() |
| 86 | h.handler.ServeHTTP(tw, r) |
| 87 | close(done) |
| 88 | }() |
| 89 | select { |
| 90 | case p := <-panicChan: |
| 91 | panic(p) |
| 92 | |
| 93 | case <-done: |
| 94 | tw.mu.Lock() |
| 95 | defer tw.mu.Unlock() |
| 96 | dst := w.Header() |
| 97 | for k, vv := range tw.h { |
| 98 | dst[k] = vv |
| 99 | } |
| 100 | if !tw.wroteHeader { |
| 101 | tw.code = http.StatusOK |
| 102 | w.WriteHeader(tw.code) |
| 103 | } |
| 104 | |
| 105 | case <-ctx.Done(): |
| 106 | tw.mu.Lock() |
| 107 | defer tw.mu.Unlock() |
| 108 | w.WriteHeader(http.StatusServiceUnavailable) |
| 109 | io.WriteString(w, h.errorBody()) |
| 110 | tw.timedOut = true |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | type timeoutWriter struct { |
| 115 | w http.ResponseWriter |
nothing calls this directly
no test coverage detected