2020-11-27 12:33:31 +00:00
|
|
|
package layer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
2021-08-18 13:48:58 +00:00
|
|
|
type (
|
|
|
|
detector struct {
|
|
|
|
io.Reader
|
|
|
|
err error
|
|
|
|
data []byte
|
|
|
|
}
|
|
|
|
errReader struct {
|
|
|
|
data []byte
|
|
|
|
err error
|
|
|
|
offset int
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
const contentTypeDetectSize = 512
|
2020-11-27 12:33:31 +00:00
|
|
|
|
2021-08-18 13:48:58 +00:00
|
|
|
func newReader(data []byte, err error) *errReader {
|
|
|
|
return &errReader{data: data, err: err}
|
2020-11-27 12:33:31 +00:00
|
|
|
}
|
|
|
|
|
2021-08-18 13:48:58 +00:00
|
|
|
func (r *errReader) Read(b []byte) (int, error) {
|
|
|
|
if r.offset >= len(r.data) {
|
|
|
|
return 0, io.EOF
|
|
|
|
}
|
|
|
|
n := copy(b, r.data[r.offset:])
|
|
|
|
r.offset += n
|
|
|
|
if r.offset >= len(r.data) {
|
|
|
|
return n, r.err
|
|
|
|
}
|
|
|
|
return n, nil
|
2020-11-27 12:33:31 +00:00
|
|
|
}
|
|
|
|
|
2021-08-18 13:48:58 +00:00
|
|
|
func newDetector(reader io.Reader) *detector {
|
|
|
|
return &detector{
|
|
|
|
data: make([]byte, contentTypeDetectSize),
|
|
|
|
Reader: reader,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *detector) Detect() (string, error) {
|
|
|
|
n, err := d.Reader.Read(d.data)
|
|
|
|
if err != nil && err != io.EOF {
|
|
|
|
d.err = err
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
d.data = d.data[:n]
|
|
|
|
return http.DetectContentType(d.data), nil
|
|
|
|
}
|
2020-11-27 12:33:31 +00:00
|
|
|
|
2021-08-18 13:48:58 +00:00
|
|
|
func (d *detector) MultiReader() io.Reader {
|
|
|
|
return io.MultiReader(newReader(d.data, d.err), d.Reader)
|
2020-11-27 12:33:31 +00:00
|
|
|
}
|