| 213 | } |
| 214 | |
| 215 | func (c *Compressor) serveRef(w http.ResponseWriter, r *http.Request, headers http.Header, cref ref) { |
| 216 | select { |
| 217 | case <-r.Context().Done(): |
| 218 | w.WriteHeader(http.StatusServiceUnavailable) |
| 219 | return |
| 220 | case <-cref.done: |
| 221 | cachePath := cref.key.filePath(c.cacheDir) |
| 222 | cacheFile, err := os.Open(cachePath) |
| 223 | if err != nil { |
| 224 | c.logger.Error(context.Background(), "failed to open compressed cache file", |
| 225 | slog.F("cache_path", cachePath), slog.F("url_path", cref.key.urlPath), slog.Error(err)) |
| 226 | // fall back to uncompressed |
| 227 | http.FileServer(c.orig).ServeHTTP(w, r) |
| 228 | } |
| 229 | defer cacheFile.Close() |
| 230 | |
| 231 | // we need to remove or modify the Content-Length, if any, set by the FileServer because it will be for |
| 232 | // uncompressed data and wrong. |
| 233 | info, err := cacheFile.Stat() |
| 234 | if err != nil { |
| 235 | c.logger.Error(context.Background(), "failed to stat compressed cache file", |
| 236 | slog.F("cache_path", cachePath), slog.F("url_path", cref.key.urlPath), slog.Error(err)) |
| 237 | headers.Del("Content-Length") |
| 238 | } else { |
| 239 | headers.Set("Content-Length", fmt.Sprintf("%d", info.Size())) |
| 240 | } |
| 241 | |
| 242 | for key, values := range headers { |
| 243 | w.Header()[key] = values |
| 244 | } |
| 245 | w.Header().Set("Content-Encoding", cref.key.encoding) |
| 246 | w.Header().Add("Vary", "Accept-Encoding") |
| 247 | w.WriteHeader(http.StatusOK) |
| 248 | _, err = io.Copy(w, cacheFile) |
| 249 | if err != nil { |
| 250 | // most commonly, the writer will hang up before we are done. |
| 251 | c.logger.Debug(context.Background(), "failed to write compressed cache file", slog.Error(err)) |
| 252 | } |
| 253 | return |
| 254 | case <-cref.err: |
| 255 | // fall back to uncompressed |
| 256 | http.FileServer(c.orig).ServeHTTP(w, r) |
| 257 | return |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | func (c *Compressor) getRef(encoding string, r *http.Request) ref { |
| 262 | ck := getCacheKey(encoding, r) |