Skip to content

fix: replace deprecated url.parse() with WHATWG URL API#2081

Open
roli-lpci wants to merge 3 commits intoredis:mainfrom
roli-lpci:fix/replace-url-parse-with-url-api
Open

fix: replace deprecated url.parse() with WHATWG URL API#2081
roli-lpci wants to merge 3 commits intoredis:mainfrom
roli-lpci:fix/replace-url-parse-with-url-api

Conversation

@roli-lpci
Copy link
Copy Markdown

@roli-lpci roli-lpci commented Feb 25, 2026

Summary

Replaces the deprecated Node.js url.parse() with the WHATWG URL API in the parseURL function, addressing #1747.

  • Replaced url.parse() with new URL() throughout parseURL()
  • Handles password-only auth URLs (redis://:password@host) correctly — decodeURIComponent() on both username and password
  • Preserves Unix socket paths with query parameters (/tmp/redis.sock?db=2)
  • Strips IPv6 hostname brackets to match legacy url.parse() behavior
  • Handles bare host:port strings by prepending redis:// protocol
  • Replaced .slashes check with explicit startsWith("redis://") / startsWith("rediss://")

Changes

  • lib/utils/index.ts: Rewrote parseURL function (+35/-13 lines)
  • Removed import { parse as urllibParse } from "url" (URL is a global)

Property mapping

url.parse() new URL() Notes
.auth .username + .password Must decodeURIComponent() — WHATWG URL percent-encodes
.hostname .hostname Strip [] brackets for IPv6
.port .port Returns '' instead of null (both falsy)
.pathname .pathname Same behavior for redis:// scheme
.query .searchParams Converted to plain object via forEach
.slashes N/A Replaced with startsWith() protocol check

Test plan

  • All 12 parseURL unit tests pass
  • All 6 Redis constructor tests pass (including password-only auth)
  • TypeScript compilation clean (tsc --noEmit)
  • ESLint passes (0 errors)
  • 136/136 unit tests pass (1 pre-existing sinon failure unrelated to this change)

roli-lpci and others added 3 commits February 25, 2026 05:02
Replace the deprecated Node.js `url.parse()` with the standard WHATWG
`new URL()` API in the `parseURL` function, resolving the DEP0169
deprecation warning about security implications.

Key changes:
- Remove `import { parse as urllibParse } from "url"`
- Use `new URL()` with a dummy `redis://` protocol prefix for URLs
  without a scheme (e.g. "127.0.0.1:6379")
- Handle Unix socket paths (starting with "/") as an early return since
  they are not valid URLs for the WHATWG parser
- Replace `.slashes` check (not available on WHATWG URL) with explicit
  protocol detection via `startsWith("redis://")` / `startsWith("rediss://")`
- Replace `.auth` with `.username` / `.password`, adding
  `decodeURIComponent()` since WHATWG URL percent-encodes special
  characters (e.g. colons in passwords)
- Replace `.query` object with `searchParams` iterated into a plain object
- Use `.hostname` directly instead of `.host` (avoids port-in-host issues)

Fixes redis#1747

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ackets

Address three edge cases in the url.parse() → new URL() migration:

1. Password-only auth (redis://:password@host) - WHATWG URL returns empty
   username (falsy), so check both username and password before extracting
   credentials. This is the default auth pattern for Redis 5 and below,
   AWS ElastiCache, and most managed Redis services.

2. Unix socket paths with query params (/tmp/redis.sock?db=2) - preserve
   query parameters instead of stripping them on early return.

3. IPv6 hostname brackets - WHATWG URL keeps brackets around IPv6
   addresses ([::1]), strip them to match url.parse() behavior.

Also removes dead urlStr alias variable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…wing

The isInt() function's type guard (value is string) incorrectly narrows
the url parameter to 'never' in the false branch since url is already
typed as string. Use rawUrl alias to work around the narrowing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jit-ci
Copy link
Copy Markdown

jit-ci bot commented Feb 25, 2026

Hi, I’m Jit, a friendly security platform designed to help developers build secure applications from day zero with an MVS (Minimal viable security) mindset.

In case there are security findings, they will be communicated to you as a comment inside the PR.

Hope you’ll enjoy using Jit.

Questions? Comments? Want to learn more? Get in touch with us.

@PavelPashov
Copy link
Copy Markdown
Contributor

@roli-lpci , thanks for the PR, I’ll take a look when I get a chance.

@roli-lpci
Copy link
Copy Markdown
Author

Quick note on the Node 24.x CI status — all 521 unit tests and 17 cluster tests pass on every Node version including 24.x. The only failing step is the Coveralls coverage upload, which hit a transient service outage (HTTP 530, DNS error 1016). Not related to the URL changes in this PR.

@windrexcz
Copy link
Copy Markdown

7/11, good enough
obrazek

@copilot fix this make no mistakes

@rit3sh-x
Copy link
Copy Markdown
Contributor

rit3sh-x commented Apr 4, 2026

@PavelPashov @roli-lpci I also worked on this and opened PR #2091, but I’ve closed it since this PR covers the same change.

Happy to help if needed.

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.

4 participants