Skip to content

KTOR-2832 Fix URLBuilder(urlString) parsing for schemeless URLs#5395

Closed
e5l wants to merge 2 commits intomainfrom
claude/KTOR-2832-urlbuilder-no-protocol
Closed

KTOR-2832 Fix URLBuilder(urlString) parsing for schemeless URLs#5395
e5l wants to merge 2 commits intomainfrom
claude/KTOR-2832-urlbuilder-no-protocol

Conversation

@e5l
Copy link
Copy Markdown
Member

@e5l e5l commented Feb 26, 2026

Summary

  • Fixes https://youtrack.jetbrains.com/issue/KTOR-2832
  • URLBuilder(urlString) now treats schemeless strings without a leading / as an authority (host with optional port and path) instead of a relative path
  • This fixes surprising behavior where URLBuilder("localhost") produced http://localhost/localhost, URLBuilder("google.com") produced http://localhost/google.com, and URLBuilder("localhost:8080") parsed localhost as a URL scheme

KTOR-2832

Test plan

  • Added 5 reproducer tests covering bare hostname, domain name, host:port, host/path, and host:port/path
  • Updated existing tests to reflect the new behavior for schemeless strings
  • All existing tests in the module continue to pass across all platforms (allTests)

🤖 Generated with Claude Code

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 26, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The URLBuilder constructor is redesigned to interpret schemeless strings as host/authority components by prepending "//" before delegating to takeFrom, while special schemes without authority (mailto, data, tel, about) are handled explicitly. Test cases updated to reflect new parsing behavior for schemeless input patterns.

Changes

Cohort / File(s) Summary
URL Builder Implementation
ktor-http/common/src/io/ktor/http/URLUtils.kt
Complete rewrite of URLBuilder(urlString: String) constructor with conditional logic to distinguish special schemes without authority, explicit scheme detection, and default host/authority interpretation for schemeless input. Introduces SPECIAL_SCHEMES_WITHOUT_AUTHORITY set.
URL Builder Tests
ktor-http/common/test/io/ktor/tests/http/URLBuilderTest.kt, ktor-http/common/test/io/ktor/tests/http/UrlTest.kt
Added test cases for schemeless string parsing as host/authority (e.g., "a", "a/b/c"), KTOR-2832 host-with-port scenarios, and updated isRelativePath expectations. Adjusted parseUrl behavior and special scheme handling in test assertions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • osipxd
  • bjhham
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing URLBuilder parsing to correctly handle schemeless URLs, directly referencing the KTOR-2832 issue.
Description check ✅ Passed The description addresses motivation (fixes KTOR-2832, explains the problem), solution (treats schemeless strings as authority), and test plan (5 reproducer tests added, existing tests updated). However, it does not explicitly identify the subsystem affected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/KTOR-2832-urlbuilder-no-protocol

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ktor-http/common/test/io/ktor/tests/http/UrlTest.kt`:
- Around line 368-369: The test currently assumes schemeless input should parse
as null, but parseUrl now treats schemeless strings as hosts; update UrlTest.kt
to reflect the new semantics by replacing the existing assertion with one that
asserts parseUrl("incorrecturl") is not null and that its host equals
"incorrecturl" (use the parseUrl function and the Url/host accessor in the
test), and also add/update the KDoc or a short migration note near the parseUrl
declaration stating that schemeless inputs are interpreted as hosts so callers
relying on null should adjust accordingly.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17f9fda and 618577c.

📒 Files selected for processing (3)
  • ktor-http/common/src/io/ktor/http/URLUtils.kt
  • ktor-http/common/test/io/ktor/tests/http/URLBuilderTest.kt
  • ktor-http/common/test/io/ktor/tests/http/UrlTest.kt

Comment thread ktor-http/common/test/io/ktor/tests/http/UrlTest.kt
e5l and others added 2 commits February 26, 2026 14:15
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When no scheme is present and the input doesn't start with '/',
the URLBuilder factory function now treats the string as an
authority (host with optional port and path) instead of a relative
path. This fixes surprising behavior where URLBuilder("localhost")
produced "http://localhost/localhost" and URLBuilder("localhost:8080")
was parsed with "localhost" as a scheme.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@e5l e5l force-pushed the claude/KTOR-2832-urlbuilder-no-protocol branch from 618577c to 60ec63a Compare February 26, 2026 13:16
@e5l e5l changed the base branch from main to release/3.x February 26, 2026 13:16
@e5l e5l requested a review from bjhham February 26, 2026 14:15
Copy link
Copy Markdown
Contributor

@bjhham bjhham left a comment

Choose a reason for hiding this comment

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

I think this one ought to be targetted for 4.0.0 because it's quite a significant behavioural change which many people may rely on.

The only way I see us mitigating the risk here is if we were to invoke some new logic for guessing whether or not the string looks like a host / authority (checking for localhost or matching on standard TLD's and IP patterns), then defaulting to a path on the negative condition.

@e5l e5l enabled auto-merge (squash) March 18, 2026 08:59
@e5l e5l changed the base branch from release/3.x to main March 18, 2026 09:02
@e5l
Copy link
Copy Markdown
Member Author

e5l commented Mar 18, 2026

Agreed — retargeted to main (4.0.0) since this is a significant behavioral change. Thanks for the feedback @bjhham!

@osipxd
Copy link
Copy Markdown
Member

osipxd commented Mar 18, 2026

retargeted to main (4.0.0)

Actually we don't have a branch to track next major release. I'd not introduce it right now. At least until we polish and automate the process of branch synchronization.

@e5l
Copy link
Copy Markdown
Member Author

e5l commented Mar 18, 2026

Closing for now — need to resolve branch targeting discussion (no branch for next major release yet). Will revisit when the process is settled.

@e5l e5l closed this Mar 18, 2026
auto-merge was automatically disabled March 18, 2026 14:14

Pull request was closed

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