(w http.ResponseWriter, r *http.Request, file blob.Ref)
| 298 | } |
| 299 | |
| 300 | func (dh *DownloadHandler) ServeFile(w http.ResponseWriter, r *http.Request, file blob.Ref) { |
| 301 | ctx := r.Context() |
| 302 | if r.Method != "GET" && r.Method != "HEAD" { |
| 303 | http.Error(w, "Invalid download method", http.StatusBadRequest) |
| 304 | return |
| 305 | } |
| 306 | |
| 307 | if r.Header.Get("If-Modified-Since") != "" { |
| 308 | // Immutable, so any copy's a good copy. |
| 309 | w.WriteHeader(http.StatusNotModified) |
| 310 | return |
| 311 | } |
| 312 | |
| 313 | dh.r = r |
| 314 | fi, packed, err := dh.fileInfo(ctx, file) |
| 315 | if err != nil { |
| 316 | http.Error(w, "Can't serve file: "+err.Error(), http.StatusInternalServerError) |
| 317 | return |
| 318 | } |
| 319 | if !fi.mode.IsRegular() { |
| 320 | http.Error(w, "Not a regular file", http.StatusBadRequest) |
| 321 | return |
| 322 | } |
| 323 | defer fi.close() |
| 324 | |
| 325 | h := w.Header() |
| 326 | h.Set("Content-Length", fmt.Sprint(fi.size)) |
| 327 | h.Set("Expires", time.Now().UTC().Add(oneYear).Format(http.TimeFormat)) |
| 328 | if packed { |
| 329 | h.Set("X-Camlistore-Packed", "1") |
| 330 | } |
| 331 | |
| 332 | fileName := func(ext string) string { |
| 333 | if fi.name != "" { |
| 334 | return fi.name |
| 335 | } |
| 336 | return "file-" + file.String() + ext |
| 337 | } |
| 338 | |
| 339 | if r.FormValue("inline") == "1" || dh.forceInline { |
| 340 | // TODO(mpl): investigate why at least text files have an incorrect MIME. |
| 341 | if fi.mime == "application/octet-stream" { |
| 342 | // Since e.g. plain text files are seen as "application/octet-stream", we force |
| 343 | // check for that, so we can have the browser display them as text if they are |
| 344 | // indeed actually text. |
| 345 | text, err := isText(fi.rs) |
| 346 | if err != nil { |
| 347 | // TODO: https://perkeep.org/issues/1060 |
| 348 | httputil.ServeError(w, r, fmt.Errorf("cannot verify MIME type of file: %v", err)) |
| 349 | return |
| 350 | } |
| 351 | if text { |
| 352 | fi.mime = "text/plain" |
| 353 | } |
| 354 | } |
| 355 | h.Set("Content-Disposition", "inline") |
| 356 | } else { |
| 357 | w.Header().Set("Content-Disposition", "attachment; filename="+fileName(".dat")) |
no test coverage detected