Support content negotiation for semantic web and media types
What does this MR do and why?
Closes #1135
This MR introduces HTTP content negotiation (Accept header parsing and MIME-based file resolution) into GitLab Pages, enabling semantic web and linked data publishing (such as FOAF, RDF, Turtle, JSON-LD, N-Triples, N3, OWL) alongside regular web pages.
Background & Problem
Previously, when a client requested an extensionless URL (e.g. GET /alice or GET /) without a file extension, GitLab Pages only resolved to .html (or index.html). Clients requesting semantic representations using headers like Accept: text/turtle or Accept: application/rdf+xml would either receive HTML or a 404, preventing static sites hosted on GitLab Pages from serving linked data and semantic web content using standard URI patterns.
Solution
-
RFC 9110 Compliant
AcceptHeader Parser:- Parses
Acceptheader quality values (q=0.0-1.0) and specificity weights (exacttype/subtype>type/*>*/*). - Discards zero-quality entries (
q=0).
- Parses
-
MIME and Extension Resolution:
- Maps requested media types to corresponding extensions:
application/rdf+xml->.rdftext/turtle->.ttltext/n3->.n3application/n-triples->.ntapplication/ld+json->.jsonldapplication/owl+xml->.owltext/html,application/xhtml+xml->.html
- Dynamically resolves through candidate file extensions based on client preference.
- Preserves backward compatibility: falls back to
.htmlif no preferred semantic format exists on disk.
- Maps requested media types to corresponding extensions:
-
HTTP Caching:
- Sets
Vary: Acceptheader on responses that underwent content negotiation so intermediate caches and CDNs cache variants accurately.
- Sets
-
Testing:
- Unit tests for RFC 9110 Accept header parser (
TestParseAcceptHeader). - Integration tests in
TestReader_ContentNegotiationcovering:- Directory index content negotiation (
/withAccept: application/rdf+xml->index.rdf) - File content negotiation (
/pagewithAccept: application/rdf+xml->page.rdf,text/turtle->page.ttl,application/ld+json->page.jsonld) - Quality weighted selection (
text/turtle;q=0.9, application/rdf+xml;q=0.8) - Fallback to
.htmlwhen requested format does not exist - Default behavior without
Acceptheader - Direct extension requests bypass negotiation and do not set
Vary: Accept
- Directory index content negotiation (
- Unit tests for RFC 9110 Accept header parser (