| 159 | } |
| 160 | |
| 161 | func fetchOne(c *http.Client, upstream, cmd string) ([]byte, error) { |
| 162 | u := fmt.Sprintf("http://%s/explain?cmd=%s", upstream, url.QueryEscape(cmd)) |
| 163 | ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second) |
| 164 | defer cancel() |
| 165 | req, err := http.NewRequestWithContext(ctx, "GET", u, nil) |
| 166 | if err != nil { |
| 167 | return nil, err |
| 168 | } |
| 169 | resp, err := c.Do(req) |
| 170 | if err != nil { |
| 171 | return nil, err |
| 172 | } |
| 173 | defer resp.Body.Close() |
| 174 | if resp.StatusCode != 200 { |
| 175 | return nil, fmt.Errorf("status %d", resp.StatusCode) |
| 176 | } |
| 177 | body, err := io.ReadAll(resp.Body) |
| 178 | if err != nil { |
| 179 | return nil, err |
| 180 | } |
| 181 | return body, nil |
| 182 | } |
| 183 | |
| 184 | func (b *Botshed) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { |
| 185 | if r.Method != http.MethodGet || !strings.HasPrefix(r.URL.Path, "/explain") { |