<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Manish Kumar</title>
    <description>The latest articles on DEV Community by Manish Kumar (@manishpatel00).</description>
    <link>https://dev.to/manishpatel00</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3954729%2F246be7d9-f7c2-4fed-9730-64b44fbcfdd5.jpg</url>
      <title>DEV Community: Manish Kumar</title>
      <link>https://dev.to/manishpatel00</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manishpatel00"/>
    <language>en</language>
    <item>
      <title>Deep Dive: Implementing RFC 9110 HTTP Content Negotiation for Semantic Web in GitLab Pages</title>
      <dc:creator>Manish Kumar</dc:creator>
      <pubDate>Sat, 07 Nov 2026 18:45:29 +0000</pubDate>
      <link>https://dev.to/manishpatel00/deep-dive-implementing-rfc-9110-http-content-negotiation-for-semantic-web-in-gitlab-pages-a47</link>
      <guid>https://dev.to/manishpatel00/deep-dive-implementing-rfc-9110-http-content-negotiation-for-semantic-web-in-gitlab-pages-a47</guid>
      <description>&lt;h1&gt;
  
  
  Engineering HTTP Content Negotiation in GitLab Pages: RFC 9110, Semantic Web, and Production-Grade Request Resolution
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;How I implemented media-type negotiation for Linked Data resources in GitLab Pages using Go, bounded parsing, MIME resolution, virtual filesystem lookups, and HTTP cache semantics.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Static hosting appears straightforward: receive a request, resolve a path, read a file, and return a response.&lt;/p&gt;

&lt;p&gt;However, that model becomes limiting when a URL represents a logical resource rather than a particular file.&lt;/p&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/alice&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.gitlab.io&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text/turtle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client is not necessarily asking for an HTML document. It may be requesting an RDF representation of a person, an ontology, or another Linked Data resource.&lt;/p&gt;

&lt;p&gt;A browser might request the same URL with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: text/html
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A semantic crawler might request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: application/rdf+xml
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And an application consuming structured linked data might request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: application/ld+json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three requests refer to the same URI, but they express different representation preferences.&lt;/p&gt;

&lt;p&gt;This is the problem addressed by HTTP content negotiation.&lt;/p&gt;

&lt;p&gt;I implemented this capability in GitLab Pages through &lt;a href="https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/1384" rel="noopener noreferrer"&gt;Merge Request !1384&lt;/a&gt;, addressing the long-standing &lt;a href="https://gitlab.com/gitlab-org/gitlab-pages/-/issues/1135" rel="noopener noreferrer"&gt;Issue #1135&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The implementation introduces media-type-aware resolution for extensionless paths, allowing GitLab Pages to serve Semantic Web representations while preserving its existing HTML fallback behavior.&lt;/p&gt;

&lt;p&gt;This article explores the engineering decisions behind the implementation, including HTTP semantics, parsing strategy, resource bounds, MIME-to-extension resolution, virtual filesystem integration, cache correctness, and testing.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Understanding the Architectural Problem
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 Traditional static-file resolution
&lt;/h3&gt;

&lt;p&gt;A conventional static hosting system generally follows a predictable mapping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request URL          Resolved file

/about               /about.html
/docs                /docs.html
/                     /index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The URL-to-file mapping is primarily path-driven.&lt;/p&gt;

&lt;p&gt;This works well for traditional websites, but it introduces a limitation when multiple representations of the same logical resource need to be exposed through one URI.&lt;/p&gt;

&lt;p&gt;For example, a Semantic Web publisher might maintain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public/
├── alice.html
├── alice.rdf
├── alice.ttl
├── alice.jsonld
├── alice.nt
└── index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The existing extensionless resolution mechanism has no reason to distinguish these representations based on the request headers.&lt;/p&gt;

&lt;p&gt;Consequently, a request for &lt;code&gt;/alice&lt;/code&gt; may resolve to &lt;code&gt;alice.html&lt;/code&gt;, even when the client explicitly prefers RDF or Turtle.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2 The desired behavior
&lt;/h3&gt;

&lt;p&gt;The objective was to extend the existing resolution mechanism without changing the established behavior of ordinary static websites.&lt;/p&gt;

&lt;p&gt;The expected mapping becomes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Accept header&lt;/th&gt;
&lt;th&gt;Preferred representation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;text/html&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alice.html&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;application/rdf+xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alice.rdf&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;text/turtle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alice.ttl&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;application/ld+json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alice.jsonld&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;application/n-triples&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alice.nt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The same principle must work for directory index resources.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /
Accept: application/rdf+xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should be able to resolve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/index.rdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when that representation exists.&lt;/p&gt;

&lt;p&gt;The important architectural constraint was that content negotiation should extend the existing file resolution pipeline rather than introduce an independent serving mechanism.&lt;/p&gt;

&lt;p&gt;This keeps the behavior integrated with GitLab Pages' existing virtual filesystem and content-type detection infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. HTTP Content Negotiation and RFC 9110
&lt;/h2&gt;

&lt;p&gt;The implementation is based on the HTTP &lt;code&gt;Accept&lt;/code&gt; request header, specified in RFC 9110, Section 12.5.1.&lt;/p&gt;

&lt;p&gt;The header allows a client to communicate which response media types it can accept and how it prioritizes them.&lt;/p&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: text/turtle;q=0.9,
        application/rdf+xml;q=0.8,
        text/html;q=0.5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client expresses three preferences:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Turtle is preferred.&lt;/li&gt;
&lt;li&gt;RDF/XML is an acceptable alternative.&lt;/li&gt;
&lt;li&gt;HTML is less preferred.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;q&lt;/code&gt; parameter is called a quality value.&lt;/p&gt;

&lt;p&gt;RFC 9110 defines its valid range as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 &amp;lt;= q &amp;lt;= 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A missing quality value defaults to &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A value of &lt;code&gt;0&lt;/code&gt; means that the corresponding media range is not acceptable.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Media-range specificity
&lt;/h3&gt;

&lt;p&gt;HTTP also supports wildcard media ranges.&lt;/p&gt;

&lt;p&gt;There are three relevant forms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Media range&lt;/th&gt;
&lt;th&gt;Specificity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text/html&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;*/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For equal quality values, the implementation uses specificity as a secondary ordering criterion.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: */*;q=0.8,
        text/*;q=0.8,
        text/html;q=0.8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting candidate ordering is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text/html
text/*
*/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The original header position is retained as a further tie-breaker.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 An important RFC distinction
&lt;/h3&gt;

&lt;p&gt;There is a subtle difference between sorting media-range candidates and calculating the effective quality of a concrete representation.&lt;/p&gt;

&lt;p&gt;RFC 9110 specifies that the most specific matching media range determines the quality associated with a representation.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: text/*;q=0.3,
        text/html;q=0.9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The effective quality for &lt;code&gt;text/html&lt;/code&gt; is determined by the explicit &lt;code&gt;text/html&lt;/code&gt; range, not by treating both entries as independent preferences for that representation.&lt;/p&gt;

&lt;p&gt;This distinction matters when implementing a general-purpose HTTP negotiation engine.&lt;/p&gt;

&lt;p&gt;In this implementation, the candidate parser establishes an ordered list of supported media-type preferences, using quality, specificity, and original order. The filesystem resolver then attempts those candidates in order.&lt;/p&gt;

&lt;p&gt;The implementation is deliberately scoped to the supported media types and file-extension resolution required by the GitLab Pages feature.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Designing a Bounded Accept Header Parser
&lt;/h2&gt;

&lt;p&gt;The parser is one of the most important parts of this implementation.&lt;/p&gt;

&lt;p&gt;An HTTP header is external input. It must be handled defensively, especially in infrastructure that processes requests at scale.&lt;/p&gt;

&lt;p&gt;A parser that works correctly for ordinary browser requests can still behave poorly when presented with malformed, oversized, or adversarial input.&lt;/p&gt;

&lt;p&gt;The implementation introduces a dedicated parser in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;internal/serving/disk/negotiate.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of mixing header parsing directly into filesystem resolution, the logic is separated into smaller responsibilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;parseAcceptHeader()
    |
    +-- parseCandidate()
    |       |
    |       +-- mime.ParseMediaType()
    |       +-- parseQuality()
    |       +-- mimeSpecificity()
    |
    +-- sortCandidates()
    |
    +-- return ordered candidates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separation makes the parser easier to reason about and allows it to be tested independently.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Candidate representation
&lt;/h3&gt;

&lt;p&gt;Each parsed media range is represented by a small structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;mimeCandidate&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mediaType&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;quality&lt;/span&gt;     &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;specificity&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;       &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each field serves a specific purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mediaType&lt;/code&gt;: Normalized media type used for MIME mapping.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;quality&lt;/code&gt;: Client-provided preference weight.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;specificity&lt;/code&gt;: Specificity classification.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;order&lt;/code&gt;: Original position in the request header.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keeping the original position is important because sorting must remain deterministic when multiple candidates have identical quality and specificity.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Parsing quality values safely
&lt;/h3&gt;

&lt;p&gt;Go's &lt;code&gt;strconv.ParseFloat&lt;/code&gt; is useful for converting numeric strings into floating-point values.&lt;/p&gt;

&lt;p&gt;However, successful parsing alone does not guarantee a valid HTTP quality value.&lt;/p&gt;

&lt;p&gt;For example, floating-point parsing can accept special values such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NaN
+Inf
-Inf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These values must not enter a sorting algorithm that expects ordinary comparable quality values.&lt;/p&gt;

&lt;p&gt;In particular, &lt;code&gt;NaN&lt;/code&gt; has unusual comparison behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A sorting comparator operating on such values can violate the assumptions expected by the sorting implementation.&lt;/p&gt;

&lt;p&gt;The parser therefore validates the result explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;parseQValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qStr&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;qStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qStr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsInf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0.0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This establishes several useful invariants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parsing errors are rejected.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NaN&lt;/code&gt; is rejected.&lt;/li&gt;
&lt;li&gt;Positive and negative infinity are rejected.&lt;/li&gt;
&lt;li&gt;Negative values are rejected.&lt;/li&gt;
&lt;li&gt;Values greater than one are rejected.&lt;/li&gt;
&lt;li&gt;Only finite values within the expected range are accepted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One standards detail is worth distinguishing: RFC 9110's &lt;code&gt;qvalue&lt;/code&gt; grammar permits at most three decimal digits. The range validation above enforces the numeric bounds but is not, by itself, a complete lexical validator for that grammar.&lt;/p&gt;

&lt;p&gt;The key engineering principle is to validate untrusted numeric input before it participates in ordering decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Handling malformed media-type parameters
&lt;/h3&gt;

&lt;p&gt;The implementation uses Go's standard library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;mime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseMediaType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This provides structured parsing of media types and parameters.&lt;/p&gt;

&lt;p&gt;However, malformed input creates an important edge case.&lt;/p&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: text/html; malformed; q=0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If parsing fails and the implementation blindly assigns the default quality of &lt;code&gt;1&lt;/code&gt;, it could accidentally reintroduce a representation the client explicitly excluded.&lt;/p&gt;

&lt;p&gt;To avoid that behavior, the implementation has a fallback path that extracts the &lt;code&gt;q&lt;/code&gt; parameter from the raw entry when structured parsing fails.&lt;/p&gt;

&lt;p&gt;The relevant logic is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;parseQuality&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rawPart&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;qStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"q"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parseQValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qStr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rawPart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;";"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;rawPart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s"&gt;";"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s"&gt;"q="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parseQValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a defensive parsing decision: malformed syntax should not cause an explicitly excluded media type to be treated as fully acceptable.&lt;/p&gt;

&lt;p&gt;It also demonstrates why error handling should consider the semantics of the input, rather than simply returning a default value whenever parsing fails.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4 Bounding parser work
&lt;/h3&gt;

&lt;p&gt;Another important concern is resource consumption.&lt;/p&gt;

&lt;p&gt;An attacker could send an &lt;code&gt;Accept&lt;/code&gt; header containing a very large number of comma-separated entries.&lt;/p&gt;

&lt;p&gt;Even if each individual entry is inexpensive to parse, processing an unbounded number of entries creates unnecessary CPU and allocation pressure.&lt;/p&gt;

&lt;p&gt;The implementation introduces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;maxAcceptParts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parsing loop is bounded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;parsedParts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;parsedParts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;maxAcceptParts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;parsedParts&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IndexByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;','&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;
        &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Parse and validate the candidate.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An important detail is that the counter tracks entries inspected, not just valid candidates appended.&lt;/p&gt;

&lt;p&gt;Why does this matter?&lt;/p&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: text/html,
        text/html,
        text/html,
        text/html,
        ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the limit only applied to successfully appended candidates, repeated duplicate entries could still force the parser to inspect a large amount of input.&lt;/p&gt;

&lt;p&gt;By counting every inspected entry, the implementation establishes a predictable upper bound on parsing iterations.&lt;/p&gt;

&lt;p&gt;This is a small implementation detail with meaningful operational consequences.&lt;/p&gt;

&lt;p&gt;It also keeps the candidate slice bounded, which limits subsequent sorting and allocation work.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.5 Deduplicating media types
&lt;/h3&gt;

&lt;p&gt;The parser maintains a set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;seenTypes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After parsing and validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;seenTypes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mediaType&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;seenTypes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mediaType&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}{}&lt;/span&gt;
&lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This avoids retaining repeated entries for the same normalized media type.&lt;/p&gt;

&lt;p&gt;Without deduplication, duplicate entries could trigger redundant resolution attempts and complicate deterministic behavior.&lt;/p&gt;

&lt;p&gt;The implementation uses a map for efficient membership checks.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.6 Deterministic candidate ordering
&lt;/h3&gt;

&lt;p&gt;The candidates are sorted using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;sortCandidates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;mimeCandidate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliceStable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quality&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;specificity&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;specificity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;specificity&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;specificity&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ordering criteria are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Higher quality first.&lt;/li&gt;
&lt;li&gt;Higher specificity first.&lt;/li&gt;
&lt;li&gt;Earlier position in the original header first.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Stable sorting provides an additional guarantee that equal candidates do not acquire arbitrary ordering.&lt;/p&gt;

&lt;p&gt;This makes the parser's output deterministic and easier to test.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. MIME-to-Extension Resolution
&lt;/h2&gt;

&lt;p&gt;Once the request preferences have been parsed, the next problem is translating media types into filesystem candidates.&lt;/p&gt;

&lt;p&gt;HTTP clients communicate using MIME types.&lt;/p&gt;

&lt;p&gt;Static hosting systems store resources using filenames and extensions.&lt;/p&gt;

&lt;p&gt;The implementation needs a mapping between these two representations.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 Supported media types
&lt;/h3&gt;

&lt;p&gt;The implementation defines explicit mappings for the supported Semantic Web formats:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Media type&lt;/th&gt;
&lt;th&gt;File extension&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;application/rdf+xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.rdf&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text/turtle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.ttl&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;application/x-turtle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.ttl&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text/n3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.n3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text/rdf+n3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.n3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;application/n-triples&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.nt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;application/ld+json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.jsonld&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;application/owl+xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.owx&lt;/code&gt;, &lt;code&gt;.owl&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text/html&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.html&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;application/xhtml+xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.html&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The mapping is maintained centrally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;knownMimeExtensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mimeRdfXML&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extRDF&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;mimeTurtle&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extTTL&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;mimeXTurtle&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extTTL&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;mimeN3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extN3&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;mimeRdfN3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extN3&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;mimeNTriples&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extNT&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;mimeLdJSON&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extJSONLD&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;mimeOwlXML&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extOWX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extOwl&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;mimeTextHTML&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extHTML&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;mimeXhtmlXML&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extHTML&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important design decision is that MIME support is explicit.&lt;/p&gt;

&lt;p&gt;The resolver does not attempt to derive arbitrary file extensions from arbitrary client-supplied media types.&lt;/p&gt;

&lt;p&gt;That keeps the supported surface predictable and avoids turning request headers into unrestricted filesystem path construction.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Multiple extensions for one representation
&lt;/h3&gt;

&lt;p&gt;Some media types can correspond to more than one established filename convention.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;mimeOwlXML&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;extOWX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extOwl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resolver checks the supported extensions in the configured order.&lt;/p&gt;

&lt;p&gt;This provides compatibility with existing naming conventions without duplicating the negotiation logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 MIME type detection must match the selected file
&lt;/h3&gt;

&lt;p&gt;Selecting the correct file is only half of the problem.&lt;/p&gt;

&lt;p&gt;The HTTP response must also communicate the correct media type.&lt;/p&gt;

&lt;p&gt;GitLab Pages already contains extension-based content-type detection.&lt;/p&gt;

&lt;p&gt;The implementation extends that mapping to include Semantic Web extensions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.rdf
.ttl
.n3
.nt
.jsonld
.owl
.owx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps file resolution and response metadata aligned.&lt;/p&gt;

&lt;p&gt;A server should not return a Turtle file with an unrelated HTML content type simply because the original URL did not contain an extension.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Integrating Negotiation with the Virtual Filesystem
&lt;/h2&gt;

&lt;p&gt;The resolver should not bypass the existing storage abstraction.&lt;/p&gt;

&lt;p&gt;GitLab Pages uses a virtual filesystem layer, which allows the serving implementation to work with its supported storage backends without embedding backend-specific file access logic into content negotiation.&lt;/p&gt;

&lt;p&gt;The negotiation implementation therefore operates through the existing VFS interfaces.&lt;/p&gt;

&lt;p&gt;The central function is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;negotiatePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="n"&gt;vfs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;basePath&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its responsibilities are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the request's &lt;code&gt;Accept&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;Parse the supported media-type candidates.&lt;/li&gt;
&lt;li&gt;Translate candidates into file extensions.&lt;/li&gt;
&lt;li&gt;Probe the VFS for existing representations.&lt;/li&gt;
&lt;li&gt;Return the first matching path.&lt;/li&gt;
&lt;li&gt;Fall back to HTML when no preferred representation exists.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  5.1 Resolution pipeline
&lt;/h3&gt;

&lt;p&gt;The high-level flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 HTTP Request
                      |
                      v
              Read Accept Header
                      |
                      v
             Parse Media Ranges
                      |
                      v
          Validate Quality and Specificity
                      |
                      v
             Sort Candidates
                      |
                      v
           Map MIME Types to Extensions
                      |
                      v
             Probe Virtual Filesystem
                      |
             +--------+--------+
             |                 |
          Found              Not Found
             |                 |
             v                 v
        Return Path       Try Next Candidate
                               |
                               v
                         HTML Fallback
                               |
                       +-------+-------+
                       |               |
                     Found          Missing
                       |               |
                       v               v
                   Return Path       Error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture separates negotiation policy from the actual storage implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2 Probing candidate extensions
&lt;/h3&gt;

&lt;p&gt;The resolver uses a dedicated helper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;tryExtensions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="n"&gt;vfs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;basePath&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;exts&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;seenExts&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The helper iterates through candidate extensions and resolves each path using the existing path resolution mechanism.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;exts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;seenExts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;seenExts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}{}&lt;/span&gt;

    &lt;span class="n"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resolvePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;basePath&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two important decisions here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First: reuse the existing resolver.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The implementation does not introduce a separate filesystem access path just for semantic resources.&lt;/p&gt;

&lt;p&gt;This preserves existing VFS behavior and keeps storage-specific concerns out of the negotiation code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second: deduplicate extensions across candidates.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Different MIME types can map to the same extension.&lt;/p&gt;

&lt;p&gt;For example, both &lt;code&gt;text/turtle&lt;/code&gt; and &lt;code&gt;application/x-turtle&lt;/code&gt; map to &lt;code&gt;.ttl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Without deduplication, the same path could be probed more than once.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;seenExts&lt;/code&gt; map prevents redundant resolution attempts.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3 Complexity and operational cost
&lt;/h3&gt;

&lt;p&gt;Let:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(n) be the maximum number of inspected Accept entries.&lt;/li&gt;
&lt;li&gt;(e) be the maximum number of extensions associated with a supported media type.&lt;/li&gt;
&lt;li&gt;(p) be the number of unique candidate paths actually probed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the parser bound set to 16, the sorting cost is:&lt;/p&gt;

&lt;p&gt;[&lt;br&gt;
O(n \log n)&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;Candidate deduplication and extension lookup are expected constant-time map operations.&lt;/p&gt;

&lt;p&gt;The filesystem resolution cost depends on the number of unique candidates and the underlying VFS backend.&lt;/p&gt;

&lt;p&gt;The important operational property is that parsing and candidate generation are bounded, and duplicate path probes are avoided.&lt;/p&gt;

&lt;p&gt;This does not imply a universal latency guarantee: actual lookup performance remains dependent on the storage implementation.&lt;/p&gt;


&lt;h2&gt;
  
  
  6. Backward Compatibility and HTML Fallback
&lt;/h2&gt;

&lt;p&gt;Introducing content negotiation into a mature static hosting platform creates a compatibility requirement.&lt;/p&gt;

&lt;p&gt;Existing projects should not need to rename files or change their URLs.&lt;/p&gt;

&lt;p&gt;The original behavior must remain available.&lt;/p&gt;

&lt;p&gt;The resolver therefore uses HTML as its final fallback.&lt;/p&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public/
├── alice.html
└── alice.ttl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A client requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /alice
Accept: application/rdf+xml
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no &lt;code&gt;alice.rdf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The resolver checks the preferred representation, finds that it does not exist, and falls back to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alice.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the requested Turtle representation exists, it can be selected instead.&lt;/p&gt;

&lt;p&gt;This behavior is important because it allows semantic resources to be introduced incrementally.&lt;/p&gt;

&lt;p&gt;A project can publish HTML today and add RDF, Turtle, or JSON-LD representations without redesigning its URL structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.1 Requests without a usable Accept header
&lt;/h3&gt;

&lt;p&gt;When the header is absent or produces no usable candidates, the implementation resolves the HTML representation.&lt;/p&gt;

&lt;p&gt;This preserves the traditional behavior of extensionless static URLs.&lt;/p&gt;

&lt;p&gt;It also has an important caching implication: the URL is still negotiable even when the current request does not provide a usable preference.&lt;/p&gt;

&lt;p&gt;That distinction becomes relevant in the next section.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. HTTP Caching and the Vary: Accept Header
&lt;/h2&gt;

&lt;p&gt;Caching is one of the easiest parts of content negotiation to overlook.&lt;/p&gt;

&lt;p&gt;Suppose a client requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /alice
Accept: text/html
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Type: text/html
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A shared cache stores the response under &lt;code&gt;/alice&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now another client requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /alice
Accept: text/turtle
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the cache does not know that the response depends on the &lt;code&gt;Accept&lt;/code&gt; header, it might reuse the previously cached HTML representation.&lt;/p&gt;

&lt;p&gt;The result is incorrect content delivery.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.1 Why Vary matters
&lt;/h3&gt;

&lt;p&gt;HTTP defines the &lt;code&gt;Vary&lt;/code&gt; response header to communicate which request headers influenced representation selection.&lt;/p&gt;

&lt;p&gt;For content-negotiated responses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Vary: Accept
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells compliant caches that the &lt;code&gt;Accept&lt;/code&gt; request header is part of the cache key for the response variant.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/alice + Accept: text/html
    |
    v
alice.html

/alice + Accept: text/turtle
    |
    v
alice.ttl

/alice + Accept: application/rdf+xml
    |
    v
alice.rdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cache must distinguish these variants.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.2 The important case: missing Accept headers
&lt;/h3&gt;

&lt;p&gt;A subtle but important implementation detail is that &lt;code&gt;Vary: Accept&lt;/code&gt; is relevant even when the current request has no usable Accept header.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A client requests &lt;code&gt;/alice&lt;/code&gt; without an &lt;code&gt;Accept&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;GitLab Pages serves &lt;code&gt;alice.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Another client requests &lt;code&gt;/alice&lt;/code&gt; with &lt;code&gt;Accept: text/turtle&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the first response is cached without accounting for &lt;code&gt;Accept&lt;/code&gt;, the cache could incorrectly reuse HTML for the second request.&lt;/p&gt;

&lt;p&gt;The implementation therefore retains the negotiation state even when it falls back to HTML because there are no usable candidates.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.3 Direct file requests
&lt;/h3&gt;

&lt;p&gt;There is also an important distinction between negotiated and explicit file requests.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /alice.ttl
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This request already identifies a specific representation through its URL.&lt;/p&gt;

&lt;p&gt;It does not need content negotiation to determine the extension.&lt;/p&gt;

&lt;p&gt;The implementation keeps direct extension requests outside the negotiation path, avoiding unnecessary &lt;code&gt;Vary: Accept&lt;/code&gt; behavior.&lt;/p&gt;

&lt;p&gt;This is a useful example of applying HTTP caching semantics only where the representation actually depends on request negotiation.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Feature-Flagged Rollout
&lt;/h2&gt;

&lt;p&gt;A production infrastructure change should not unexpectedly alter the behavior of existing deployments.&lt;/p&gt;

&lt;p&gt;The implementation introduces a dedicated feature flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ContentNegotiation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;EnvVariable&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"FF_ENABLE_CONTENT_NEGOTIATION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;defaultEnabled&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The flag provides an explicit control over the new functionality.&lt;/p&gt;

&lt;p&gt;When disabled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Existing extensionless URL resolution remains unchanged.&lt;/li&gt;
&lt;li&gt;Traditional HTML resolution continues to work.&lt;/li&gt;
&lt;li&gt;Existing static sites do not automatically enter the new negotiation flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When enabled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The request's &lt;code&gt;Accept&lt;/code&gt; header is considered.&lt;/li&gt;
&lt;li&gt;Supported Semantic Web media types can be resolved.&lt;/li&gt;
&lt;li&gt;Existing HTML fallback behavior is retained.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The default-disabled configuration provides a controlled introduction of the feature.&lt;/p&gt;

&lt;p&gt;This is particularly important in infrastructure software, where even a seemingly small change to path resolution can affect a large number of unrelated applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Testing Strategy: Validate Behavior, Not Just Parsing
&lt;/h2&gt;

&lt;p&gt;A parser that passes a few unit tests is not sufficient for a feature that changes request resolution.&lt;/p&gt;

&lt;p&gt;The implementation includes both parser-level and integration-level tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.1 Parser unit tests
&lt;/h3&gt;

&lt;p&gt;The dedicated parser tests cover cases such as:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test case&lt;/th&gt;
&lt;th&gt;Expected behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Empty Accept header&lt;/td&gt;
&lt;td&gt;No candidates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single media type&lt;/td&gt;
&lt;td&gt;Default quality of 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple media types&lt;/td&gt;
&lt;td&gt;Quality-based ordering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Equal quality values&lt;/td&gt;
&lt;td&gt;Specificity-based ordering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Equal quality and specificity&lt;/td&gt;
&lt;td&gt;Original order preserved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;q=0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Candidate excluded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;q=NaN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Candidate rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;q=Inf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Candidate rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quality above 1&lt;/td&gt;
&lt;td&gt;Candidate rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Negative quality&lt;/td&gt;
&lt;td&gt;Candidate rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Malformed entry containing &lt;code&gt;q=0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Explicit exclusion preserved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate media types&lt;/td&gt;
&lt;td&gt;Duplicate candidates removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Excessive header entries&lt;/td&gt;
&lt;td&gt;Parsing remains bounded&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These tests are particularly valuable because they validate invariants rather than only testing ordinary inputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.2 Integration tests
&lt;/h3&gt;

&lt;p&gt;The integration tests exercise the actual content-resolution path.&lt;/p&gt;

&lt;p&gt;Important scenarios include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semantic file resolution&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/alice + application/rdf+xml -&amp;gt; alice.rdf
/alice + text/turtle         -&amp;gt; alice.ttl
/alice + application/ld+json -&amp;gt; alice.jsonld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Directory index resolution&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/ + application/rdf+xml -&amp;gt; index.rdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Quality-weighted selection&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: text/turtle;q=0.9,
        application/rdf+xml;q=0.8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resolver should prefer the Turtle representation when both corresponding files are available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fallback behavior&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the requested semantic representation does not exist, the resolver should attempt the HTML file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default behavior&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A request without a usable Accept header should retain HTML resolution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicit extension requests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Direct requests for files such as &lt;code&gt;/alice.ttl&lt;/code&gt; should bypass negotiation.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.3 Why both layers matter
&lt;/h3&gt;

&lt;p&gt;Unit tests answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does the parser correctly interpret and order supported media-type preferences?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Integration tests answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does the complete serving pipeline select the correct file and preserve the expected HTTP behavior?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Both are necessary.&lt;/p&gt;

&lt;p&gt;A parser can be correct while the resolver is wrong. Likewise, filesystem resolution can work while response metadata or cache headers are incorrect.&lt;/p&gt;

&lt;p&gt;Testing the complete behavior is what makes this type of infrastructure change reliable.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Engineering Trade-offs and Lessons
&lt;/h2&gt;

&lt;p&gt;Several decisions in this implementation are worth highlighting.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.1 Explicit MIME mappings over arbitrary extension derivation
&lt;/h3&gt;

&lt;p&gt;Mapping supported MIME types explicitly is more predictable than deriving filesystem extensions from arbitrary request input.&lt;/p&gt;

&lt;p&gt;It limits the resolution surface and makes supported behavior easier to review.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.2 Bounded parsing over unbounded flexibility
&lt;/h3&gt;

&lt;p&gt;HTTP headers are client-controlled.&lt;/p&gt;

&lt;p&gt;A fixed maximum number of inspected entries gives the parser a predictable processing budget.&lt;/p&gt;

&lt;p&gt;This is especially useful in high-throughput request-serving systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.3 Reusing the VFS abstraction
&lt;/h3&gt;

&lt;p&gt;Filesystem resolution should remain the responsibility of the existing storage layer.&lt;/p&gt;

&lt;p&gt;Integrating negotiation through the VFS avoids introducing storage-specific assumptions into HTTP parsing logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.4 Cache correctness is part of protocol correctness
&lt;/h3&gt;

&lt;p&gt;Serving the correct file is not sufficient if an intermediary cache can deliver the wrong representation to another client.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Vary: Accept&lt;/code&gt; is part of the feature's correctness, not an optional performance optimization.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.5 Backward compatibility must be intentional
&lt;/h3&gt;

&lt;p&gt;A new resolution strategy should not silently redefine existing URLs.&lt;/p&gt;

&lt;p&gt;Feature flags and HTML fallback behavior provide a controlled path toward introducing the new capability.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Final Architecture
&lt;/h2&gt;

&lt;p&gt;The complete implementation can be understood as five cooperating layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  HTTP Request
                       |
                       v
             Accept Header Parser
                       |
                       v
             Preference Ordering
                       |
                       v
              MIME Extension Map
                       |
                       v
             VFS Path Resolution
                       |
                       v
             Content-Type Detection
                       |
                       v
                HTTP Response
                       |
                       v
                Vary: Accept
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each layer has a clear responsibility:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTTP parsing&lt;/td&gt;
&lt;td&gt;Interpret client media-type preferences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Candidate ordering&lt;/td&gt;
&lt;td&gt;Establish deterministic preference order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MIME mapping&lt;/td&gt;
&lt;td&gt;Translate supported media types to extensions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VFS resolution&lt;/td&gt;
&lt;td&gt;Locate the first available representation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP response&lt;/td&gt;
&lt;td&gt;Return the selected resource with correct metadata and cache variation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The result is an extension to GitLab Pages' existing static serving architecture rather than a separate content-serving subsystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Conclusion
&lt;/h2&gt;

&lt;p&gt;Implementing HTTP content negotiation in GitLab Pages was an interesting exercise in connecting protocol semantics with an existing production serving architecture.&lt;/p&gt;

&lt;p&gt;The challenge was not simply recognizing &lt;code&gt;Accept: text/turtle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The implementation needed to account for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP quality values and media-range specificity.&lt;/li&gt;
&lt;li&gt;Malformed and non-finite numeric inputs.&lt;/li&gt;
&lt;li&gt;Bounded parsing of untrusted request headers.&lt;/li&gt;
&lt;li&gt;Duplicate candidate and filesystem lookup elimination.&lt;/li&gt;
&lt;li&gt;MIME-to-extension mapping.&lt;/li&gt;
&lt;li&gt;Virtual filesystem integration.&lt;/li&gt;
&lt;li&gt;HTML fallback and backward compatibility.&lt;/li&gt;
&lt;li&gt;Correct cache variation through &lt;code&gt;Vary: Accept&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Controlled rollout through feature flags.&lt;/li&gt;
&lt;li&gt;Unit and integration-level validation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These details illustrate an important engineering principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A production-ready protocol feature is not just about implementing the happy path. It is about preserving correctness across parsing, resolution, storage, caching, and compatibility boundaries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This contribution gave me an opportunity to work deeper into Go-based infrastructure, HTTP semantics, and the design considerations involved in extending an established open-source platform.&lt;/p&gt;

&lt;p&gt;The work is part of my contribution to GitLab Pages through the community merge request below.&lt;/p&gt;




&lt;h3&gt;
  
  
  References and Implementation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Merge Request:&lt;/strong&gt; &lt;a href="https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/1384" rel="noopener noreferrer"&gt;GitLab Pages !1384 – Support content negotiation for semantic web and media types&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Original Issue:&lt;/strong&gt; &lt;a href="https://gitlab.com/gitlab-org/gitlab-pages/-/issues/1135" rel="noopener noreferrer"&gt;GitLab Pages #1135 – Content Negotiation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP Standard:&lt;/strong&gt; &lt;a href="https://www.rfc-editor.org/rfc/rfc9110" rel="noopener noreferrer"&gt;RFC 9110 – HTTP Semantics&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relevant Section:&lt;/strong&gt; &lt;a href="https://www.rfc-editor.org/rfc/rfc9110#section-12.5.1" rel="noopener noreferrer"&gt;RFC 9110 – Section 12.5.1: Accept&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go Standard Library:&lt;/strong&gt; &lt;a href="https://pkg.go.dev/mime" rel="noopener noreferrer"&gt;mime package&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go Standard Library:&lt;/strong&gt; &lt;a href="https://pkg.go.dev/strconv" rel="noopener noreferrer"&gt;strconv package&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Manish Kumar&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitLab:&lt;/strong&gt; &lt;a href="https://gitlab.com/manishpatel953249" rel="noopener noreferrer"&gt;@manishpatel953249&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project:&lt;/strong&gt; GitLab Pages&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Building, understanding, and contributing to production-grade open-source infrastructure.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>softwaredevelopment</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
