Skip to content

Instantly share code, notes, and snippets.

@klingtnet
Last active May 15, 2020 22:03
Show Gist options
  • Save klingtnet/27506ee36517aab289e4273397180384 to your computer and use it in GitHub Desktop.
Save klingtnet/27506ee36517aab289e4273397180384 to your computer and use it in GitHub Desktop.
A reader that detects the mime/content-type in Go
package main
import (
"bytes"
"io"
"log"
"net/http"
"github.com/gabriel-vasile/mimetype"
)
type ContentTypeReader struct {
buf [512]byte
cnt int
done bool
mimetype string
r io.Reader
}
func NewContentTypeReader(r io.Reader) *ContentTypeReader {
return &ContentTypeReader{
r: r,
}
}
func (ctr *ContentTypeReader) Read(b []byte) (n int, err error) {
n, err = ctr.r.Read(b)
if !ctr.done {
rem := 512-ctr.cnt
if n >= rem {
copy(ctr.buf[ctr.cnt:], b[:rem])
ctr.cnt += rem
ctr.done = true
} else {
copy(ctr.buf[ctr.cnt:ctr.cnt+n], b)
ctr.cnt += n
}
}
if err != nil {
if err == io.EOF {
// net/http.DetectContentType will show text/xml for SVGs, which is not wrong but inconvenient.
// ctr.mimetype = http.DetectContentType(ctr.buf[:ctr.cnt])
ctr.mimetype = mimetype.Detect(ctr.buf[:ctr.cnt]).String()
return
}
}
return
}
func (ctr *ContentTypeReader) Mimetype() string {
return ctr.mimetype
}
func main() {
resp, err := http.Get(`https://upload.wikimedia.org/wikipedia/commons/d/dd/Map_of_Europe_with_flags.svg`)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
ctr := NewContentTypeReader(resp.Body)
_, err = bytes.NewBuffer(nil).ReadFrom(ctr)
if err != nil {
log.Fatal(err)
}
log.Println("Mimetype:", ctr.Mimetype())
}
@klingtnet
Copy link
Author

A more simple solution using a LimitWriter: https://gist.github.com/miku/fe4fc9f53258b23741f41c38764fd2b6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment