v158 · network · mime sniffing

Spec-compliant XML MIME type detection

The WHATWG MIME Sniffing Standard says any valid MIME type whose subtype ends in +xml is an XML MIME type — text/example+xml and image/example+xml included. Chrome historically applied that suffix rule only to application/*. Chrome 158 aligns with the spec, so PerformanceResourceTiming.contentType now minimizes every +xml response to a consistent application/xml — with image/svg+xml deliberately unchanged.

concepts

  1. The classification matrix

    Fetch the same XML body served under eight different content types from this site's own server, and read back the browser's real contentType for each — the new text/*+xml rows, the application/* rows that always worked, the image/svg+xml exception, and non-XML controls.

  2. Serve your own subtype

    Type any top-level type and subtype, have the server actually serve it, and see how this browser classifies it — including the server's real 400 when the MIME string is not a valid token.

  3. Bucketing a real page's resources

    The practical payoff: group this page's own live resource-timing entries by contentType, the way a RUM tool would — and see where a consistent XML bucket does (and does not) change the picture.

why it shipped

The MIME Sniffing Standard defines an XML MIME type as any whose subtype ends in +xml, plus the two classics text/xml and application/xml. Chromium's implementation applied the suffix rule only to application/*, so a response served as text/example+xml fell out of the XML category: PerformanceResourceTiming.contentType — which reports the minimized MIME type so analytics code gets a small, stable vocabulary — reported its raw type instead of application/xml (and an unsupported type like image/example+xml got no bucket at all — measured on a pre-158 build in this demo's matrix).

Aligning with the spec gives developers one consistent XML bucket when inspecting resource timing data, whatever top-level type an API chose for its +xml format. The one deliberate exception stays: image/svg+xml minimizes to itself, because SVG is its own supported image format, not generic XML.

the API

const [entry] = performance.getEntriesByName(resourceUrl);

// Chrome 157 and earlier:  text/example+xml   →  "text/example+xml" (raw)
//                          image/example+xml  →  "" (no bucket)
// Chrome 158:              both               →  "application/xml"
// Both:                    image/svg+xml      →  "image/svg+xml"
entry.contentType;

Nothing changes about how responses are parsed or rendered — this is the classification surface that resource timing (and anything else built on "is this an XML MIME type") reports.

research notes — use-case portfolio

Angles built: basic/canonical (minimize-inspector — the fixed served-vs-observed matrix over this site's own serve route), configuration/inspection tool (custom-subtype — arbitrary validated MIME strings served for real), and practical product use case (resource-audit — live RUM-style bucketing of this page's own entries). Edge/failure is carried inside the first two rather than a fourth folder: the svg exception row, the non-XML control rows, and the server's real 400 rejection of invalid MIME tokens are the feature's edge surface (source: the minimize-a-supported-MIME-type algorithm, mimesniff §4). A novel composition angle would re-demonstrate the same single observable (contentType) and is recorded as not applicable. Exact surface: MIME Sniffing "XML MIME type" (*/*+xml), observed via PerformanceResourceTiming.contentType; runtime flag SpecCompliantXmlMimeTypes; implementation CL 8301932.

references