// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package http import ( "bytes" "encoding/binary" ) // The algorithm uses at most sniffLen bytes to make its decision. const sniffLen = 512 // DetectContentType implements the algorithm described // at https://mimesniff.spec.whatwg.org/ to determine the // Content-Type of the given data. It considers at most the // first 512 bytes of data. DetectContentType always returns // a valid MIME type: if it cannot determine a more specific one, it // returns "application/octet-stream". func DetectContentType(data []byte) string { if len(data) > sniffLen { data = data[:sniffLen] } // Index of the first non-whitespace byte in data. firstNonWS := 0 for ; firstNonWS < len(data) && isWS(data[firstNonWS]); firstNonWS++ { } for _, sig := range sniffSignatures { if ct := sig.match(data, firstNonWS); ct != "" { return ct } } return "application/octet-stream" // fallback } // isWS reports whether the provided byte is a whitespace byte (0xWS) // as defined in https://mimesniff.spec.whatwg.org/#terminology. func isWS(b byte) bool { switch b { case '\t', '\n', '\x0c', '\r', ' ': return true } return false } // isTT reports whether the provided byte is a tag-terminating byte (0xTT) // as defined in https://mimesniff.spec.whatwg.org/#terminology. func isTT(b byte) bool { switch b { case ' ', '>': return true } return false } type sniffSig interface { // match returns the MIME type of the data, or "" if unknown. match(data []byte, firstNonWS int) string } // Data matching the table in section 6. var sniffSignatures = []sniffSig{ htmlSig("