Skip to content

Commit 6123581

Browse files
Fix 500 Internal Server Error on empty files. (#189)
* Fix 500 Internal Server Error on empty files. * Fixes #187. * Gofmt. * Remove unnecessary set to zero. * Fix etag on empty files. Prevent setting content type on zero-sized bodies.
1 parent bb6bf30 commit 6123581

2 files changed

Lines changed: 25 additions & 14 deletions

File tree

internal/middlewares/etag.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func Etag(enabled bool, maxBodySize int64) func(http.Handler) http.Handler {
6464
}
6565

6666
// Only proceed if the response was fully buffered and status code is in the 200 range.
67-
if rw.size <= rw.maxSize && rw.err == nil && rw.statusCode >= 200 && rw.statusCode < 300 {
67+
if rw.size > 0 && rw.size <= rw.maxSize && rw.err == nil && rw.statusCode >= 200 && rw.statusCode < 300 {
6868
// Compute the ETag.
6969
etag := fmt.Sprintf("\"%x\"", hasher.Sum(nil))
7070
// Set the ETag header.

internal/server/handlers.go

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"errors"
66
"fmt"
7+
"io"
78
"net/http"
89
"os"
910
"path"
@@ -305,31 +306,35 @@ func (s *Server) serveFile(statusCode int, location string, w http.ResponseWrite
305306
}
306307

307308
var data [512]byte
308-
if _, err := f.Read(data[:]); err != nil {
309+
n, err := f.Read(data[:])
310+
if err != nil && !errors.Is(err, io.EOF) {
309311
http.Error(w, err.Error(), http.StatusInternalServerError)
310312
return
311313
}
312314

313-
if contentType == "" {
314-
if local := http.DetectContentType(data[:]); local != "application/octet-stream" {
315+
// Only detect content type if we have content to examine
316+
if contentType == "" && n > 0 {
317+
if local := http.DetectContentType(data[:n]); local != "application/octet-stream" {
315318
contentType = local
316319
}
317320
}
318321

322+
// Only attempt charset detection if we have content to examine
319323
charset := ""
320-
if utf8.Valid(data[:]) {
321-
charset = "utf-8"
322-
}
323-
324-
if charset == "" {
325-
res, err := chardet.NewTextDetector().DetectBest(data[:])
326-
if err == nil && res.Confidence > 50 && res.Charset != "" {
327-
charset = res.Charset
324+
if n > 0 && contentType != "" && !strings.HasPrefix(contentType, "application/octet-stream") {
325+
if utf8.Valid(data[:n]) {
326+
charset = "utf-8"
327+
} else {
328+
res, err := chardet.NewTextDetector().DetectBest(data[:n])
329+
if err == nil && res.Confidence > 50 && res.Charset != "" {
330+
charset = res.Charset
331+
}
328332
}
329333
}
330334

331-
if contentType != "" && contentType != "application/octet-stream" {
332-
if charset != "" {
335+
if contentType != "" {
336+
// Add charset for text-based content types only
337+
if charset != "" && contentType != "application/octet-stream" {
333338
contentType += "; charset=" + charset
334339
}
335340

@@ -342,6 +347,12 @@ func (s *Server) serveFile(statusCode int, location string, w http.ResponseWrite
342347
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", filename))
343348
}
344349

350+
// Reset file position to beginning after reading first bytes for content detection
351+
if _, err := f.Seek(0, io.SeekStart); err != nil {
352+
http.Error(w, err.Error(), http.StatusInternalServerError)
353+
return
354+
}
355+
345356
// Check if the caller changed the status code, if not, simply call
346357
// the appropriate handler/
347358
if statusCode == 0 {

0 commit comments

Comments
 (0)