Skip to content

fix: normalize scheme to lowercase (RFC 3986 §6.2.2.1)#182

Merged
zekth merged 1 commit into
fastify:mainfrom
spokodev:fix/normalize-scheme-lowercase
Jun 18, 2026
Merged

fix: normalize scheme to lowercase (RFC 3986 §6.2.2.1)#182
zekth merged 1 commit into
fastify:mainfrom
spokodev:fix/normalize-scheme-lowercase

Conversation

@spokodev

Copy link
Copy Markdown
Contributor

What

parse() does not lowercase the scheme, although it already lowercases the host:

const fastUri = require('fast-uri')

fastUri.parse('HTTP://EXAMPLE.com/p').scheme   // 'HTTP'  (host is 'example.com')
fastUri.normalize('HTTP://EXAMPLE.com/p')      // 'HTTP://example.com/p'

Why it's a bug

  • RFC 3986 §6.2.2.1 (Case Normalization): "the scheme and host are case-insensitive and therefore should be normalized to lowercase." The host is normalized; the scheme is not.
  • equal() already lowercases the scheme when comparing (fastUri.equal('HTTP://a', 'http://a') === true), so the library already treats the scheme as case-insensitive — normalize()/parse() were just inconsistent with that.
  • uri-js (which this library aims to be iso-compatible with) returns the lowercased scheme:
require('uri-js').parse('HTTP://EXAMPLE.com/p').scheme   // 'http'
require('uri-js').normalize('HTTP://EXAMPLE.com/p')      // 'http://example.com/p'

Change

Lowercase the scheme at parse time, next to where the host is already lowercased — one line, no new branches.

Tests

Added test/scheme-normalization.test.js (red before the change, green after). Full npm run test:unit passes (878).

RFC 3986 §6.2.2.1: the scheme is case-insensitive and should be
normalized to lowercase. `parse()` already lowercases the host but kept
the scheme verbatim, so `parse('HTTP://x').scheme` was `'HTTP'` and
`normalize('HTTP://EXAMPLE.com/')` returned `'HTTP://example.com/'` — an
uppercase scheme next to a lowercased host. `equal()` already compares
schemes case-insensitively, and uri-js returns `'http'`.

Lowercase the scheme at parse time, consistent with the host.

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@zekth zekth left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm thanks

@zekth zekth merged commit 46060c2 into fastify:main Jun 18, 2026
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants