contenttype

package
v1.126.5 Latest Latest
Warning

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

Go to latest
Published: Aug 29, 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.

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