contenttype

package
v1.127.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package contenttype detects and normalizes the media type of stored content.

Every platform write path that accepts content from an outside source (an upstream API response, a multipart upload, a tool argument) reaches this package. A declared type that is specific is always honored; a declared type that is absent or generic is replaced with a type sniffed from the content itself, so a JSON payload an upstream API labeled text/plain still reaches the viewer as application/json.

Detection contract

  • A specific declared type wins. Detection only runs when the declaration is empty or generic (see IsGeneric).
  • The one exception is a caller that has the filename and uses DetectFile: a declaration both the extension and the content contradict loses to what those two agree on. A .csv uploaded from a machine that declared application/vnd.ms-excel is stored as a CSV.
  • Binary families come from http.DetectContentType, which recognizes images, audio, video, PDF and archives from their magic bytes.
  • Structured text (JSON, NDJSON, XML, YAML, CSV, TSV) is layered on top, because http.DetectContentType reports every one of them as text/plain.
  • Detection reads a bounded prefix, never the whole payload, so streaming writers do not have to buffer.

Active-type rule

Detection never promotes content to an active type (see IsActive). Active types execute script when a viewer renders them, so they render only when an author declared them deliberately. Content that sniffs as HTML but was declared text/plain stays text/plain; content that sniffs as HTML with no declaration at all becomes text/plain. This keeps a mislabeled upload from turning itself into script-bearing content.

Scriptable-document rule

IsActive answers what detection may produce. It does not answer whether stored bytes may render inline on the platform's origin, which is a wider question: XML is safe to name from content and unsafe to render, because a browser navigating to it builds a document that honors an <?xml-stylesheet?> processing instruction. IsScriptableDocument answers that one, over a superset of the active types.

Index

Constants

View Source
const (
	// JSON is the canonical type for JSON documents.
	JSON = "application/json"
	// NDJSON is the canonical type for newline-delimited JSON.
	NDJSON = "application/x-ndjson"
	// CSV is the canonical type for comma-separated values.
	CSV = "text/csv"
	// TSV is the canonical type for tab-separated values.
	TSV = "text/tab-separated-values"
	// XML is the canonical type for XML documents.
	XML = "application/xml"
	// YAML is the canonical type for YAML documents.
	YAML = "application/yaml"
	// Markdown is the canonical type for Markdown documents.
	Markdown = "text/markdown"
	// PlainText is the canonical type for unstructured text.
	PlainText = "text/plain"
	// HTML is the canonical type for HTML documents. Active.
	HTML = "text/html"
	// JSX is the canonical type for React/JSX components. Active.
	JSX = "text/jsx"
	// SVG is the canonical type for SVG images. Active.
	SVG = "image/svg+xml"
	// XHTML is the canonical type for XHTML documents. Active: a browser
	// renders XHTML natively and runs the script inside it.
	XHTML = "application/xhtml+xml"
	// JavaScript is the canonical type for standalone JavaScript source.
	JavaScript = "text/javascript"
	// PDF is the canonical type for PDF documents.
	PDF = "application/pdf"
	// OctetStream is the type for content of unknown or unrecognized shape.
	OctetStream = "application/octet-stream"
)

Canonical media types. Detection and normalization collapse every alias of a family onto exactly one of these values, so downstream consumers (renderer registry, extension mapping, viewer selection) match on one string per family.

View Source
const BinarySniffLen = 512

BinarySniffLen is the prefix length http.DetectContentType examines. Reading more than this for the binary sniff cannot change its answer.

View Source
const StructuredSniffLen = 8192

StructuredSniffLen is the prefix length the structured-text heuristics examine. It is large enough to hold several rows of a CSV or the opening tokens of a JSON document while staying cheap for a streaming writer to hold in memory.

Variables

This section is empty.

Functions

func Detect

func Detect(declared string, prefix []byte) string

Detect returns the canonical media type for content whose first bytes are prefix and whose writer declared declared.

A specific declaration is returned unchanged (normalized). A generic or absent declaration is replaced by the type sniffed from prefix, subject to the active-type rule: a sniff that lands on HTML, JSX, SVG or JavaScript is discarded in favor of the declaration (or text/plain when there was none).

prefix should hold at least BinarySniffLen bytes for binary families and up to StructuredSniffLen bytes for the structured-text heuristics; a shorter prefix simply yields a less confident answer.

func DetectBytes

func DetectBytes(declared string, data []byte) string

DetectBytes is Detect over a complete payload, truncating to the sniff window.

func DetectFile added in v1.125.2

func DetectFile(declared, filename string, prefix []byte) string

DetectFile is Detect for content that arrived under a filename.

A specific declaration still wins, with one exception: when the filename's extension and the content itself both name a different family, that family wins. Neither signal is enough on its own -- a name is not evidence about bytes, and content may not upgrade itself past a declaration -- but a declaration contradicted by both is wrong about what it labels.

This is what makes a .csv usable when the uploading machine declared application/vnd.ms-excel, which is what Windows sends for .csv when Excel is installed. It does not promote a mislabeled binary on the strength of its name: a .csv holding a PNG sniffs as image/png, disagrees with the name, and keeps its declaration.

When the declaration is generic or absent and the content turns out to be unstructured text, the extension is consulted on its own: nothing else has an answer, and a family with no content signature -- markdown above all -- is otherwise unreachable. See namedTextType for what that will and will not name.

A filename of "" makes this identical to Detect.

func DetectFileBytes added in v1.125.2

func DetectFileBytes(declared, filename string, data []byte) string

DetectFileBytes is DetectFile over a complete payload, truncating to the sniff window.

func DetectStream

func DetectStream(declared string, body io.Reader) (string, io.Reader, error)

DetectStream classifies a stream without buffering it. It reads at most StructuredSniffLen bytes to run detection, then returns a reader that replays those bytes ahead of the untouched remainder, so the caller can go on streaming the body to storage.

A read error other than EOF is returned to the caller along with a reader that still replays whatever was consumed, so no bytes are lost.

func Extension

func Extension(ct string) string

Extension returns the file extension for a media type, including the leading dot. Unrecognized types fall back to ".bin".

func IsActive

func IsActive(ct string) bool

IsActive reports whether a media type renders as executable markup or script. Detection never upgrades content into one of these types.

func IsGeneric

func IsGeneric(ct string) bool

IsGeneric reports whether a declared media type is uninformative enough that the content itself should be consulted.

func IsImage added in v1.126.3

func IsImage(ct string) bool

IsImage reports whether a media type names an image family. It is the accept decision for a slot that holds a picture and nothing else -- a brand logo, a thumbnail -- taken over the type this package resolved rather than over a Content-Type header a caller read for itself.

Every image family qualifies, including SVG: a caller that must distinguish vector from raster compares against SVG directly, because the two are inlined differently (markup for one, a data: URI for the other) even though both are images.

func IsScriptableDocument added in v1.117.0

func IsScriptableDocument(ct string) bool

IsScriptableDocument reports whether a browser navigating to a response of this type builds a document whose render tree the author of the bytes controls. Stored content of such a type must never be served for inline rendering on the platform's origin.

Any `+xml` structured suffix qualifies, so an XML dialect that has no entry in scriptableDocumentTypes is still covered.

func IsStorableText added in v1.117.0

func IsStorableText(ct string) bool

IsStorableText reports whether a declared media type may be stored by a write path that carries its content as a string.

func IsTextual

func IsTextual(ct string) bool

IsTextual reports whether a canonical media type holds human-readable text, and so can be loaded into a text editor or embedded in a page as a string.

func Normalize

func Normalize(declared string) string

Normalize reduces a declared media type to its canonical, parameter-free, lowercase form. It returns the empty string when the input is empty or is not a well-formed media type.

func StorableTextTypes added in v1.117.0

func StorableTextTypes() []string

StorableTextTypes returns the canonical types IsStorableText accepts, sorted, so a rejected write can name what it would have taken instead.

func TypeForFilename added in v1.125.2

func TypeForFilename(name string) string

TypeForFilename returns the canonical media type a filename's extension names, or the empty string when the name carries no extension, the extension is unknown, or it names a family detection may not produce on its own.

The answer is a claim about the name, not about the bytes. Nothing decides a stored type on this alone; see DetectFile.

Types

type Family added in v1.126.4

type Family struct {
	// Type is the canonical media type: the one spelling every alias of the
	// family normalizes to.
	Type string
	// Extension is the extension the stored object key carries, leading dot
	// included.
	Extension string
	// Storable reports whether IsStorableText accepts the type.
	Storable bool
}

Family is one media type the platform names, with the file extension a stored object of that type carries and whether a write path that receives its content as a string may be told to store it.

func Catalog added in v1.126.4

func Catalog() []Family

Catalog returns every media type this package names, sorted by type.

It exists so the platform's own documentation of what a caller may declare is generated from the tables that decide it rather than transcribed beside them: a family added to the extension table appears in the documentation on the next build, and a page cannot list a type the code does not handle.

The extension table is the enumeration because it is the widest set with a canonical spelling -- every family the platform detects, stores an object key for, or renders is in it. The storable subset is marked rather than separated so a caller of this decides how to present the difference.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL