content_type_writer.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. package util
  2. import (
  3. "net/http"
  4. "strings"
  5. )
  6. // ContentTypeWriter is an implementation of http.ResponseWriter that will detect the content type and set the
  7. // Content-Type and (optionally) Content-Disposition headers accordingly.
  8. //
  9. // It will always set a Content-Type based on http.DetectContentType, but will never send the "text/html"
  10. // content type.
  11. type ContentTypeWriter struct {
  12. w http.ResponseWriter
  13. filename string
  14. sniffed bool
  15. }
  16. // NewContentTypeWriter creates a new ContentTypeWriter
  17. func NewContentTypeWriter(w http.ResponseWriter, filename string) *ContentTypeWriter {
  18. return &ContentTypeWriter{w, filename, false}
  19. }
  20. func (w *ContentTypeWriter) Write(p []byte) (n int, err error) {
  21. if w.sniffed {
  22. return w.w.Write(p)
  23. }
  24. // Detect and set Content-Type header
  25. // Fix content types that we don't want to inline-render in the browser. In particular,
  26. // we don't want to render HTML in the browser for security reasons.
  27. contentType, _ := DetectContentType(p, w.filename)
  28. if strings.HasPrefix(contentType, "text/html") {
  29. contentType = strings.ReplaceAll(contentType, "text/html", "text/plain")
  30. } else if contentType == "application/octet-stream" {
  31. contentType = "" // Reset to let downstream http.ResponseWriter take care of it
  32. }
  33. if contentType != "" {
  34. w.w.Header().Set("Content-Type", contentType)
  35. }
  36. w.sniffed = true
  37. return w.w.Write(p)
  38. }