Skip to content

KTOR-8199 Decode URL-encoded path before matching watch patterns#5586

Merged
osipxd merged 1 commit intoktorio:mainfrom
fru1tworld:fix/8199-autoreload-watch-spaces
May 8, 2026
Merged

KTOR-8199 Decode URL-encoded path before matching watch patterns#5586
osipxd merged 1 commit intoktorio:mainfrom
fru1tworld:fix/8199-autoreload-watch-spaces

Conversation

@fru1tworld
Copy link
Copy Markdown
Contributor

Subsystem
Server, Auto-reload

Motivation
KTOR-8199 Autoreloading: default watch patterns don't match anything when project path contains spaces

The default watch pattern is WORKING_DIRECTORY_PATH = SystemFileSystem.resolve(Path(".")).toString(), which preserves literal characters from the filesystem path (e.g. a space when the project lives under /Users/me/my project/...). The classpath URLs passed to checkUrlMatches expose their path in URL-encoded form (/Users/me/my%20project/build/...), so the substring match always fails and the engine logs:

No ktor.deployment.watch patterns match classpath entries, automatic reload is not active

The same file already URL-decodes the path inside watchUrls() (URLDecoder.decode(path, "utf-8")), so the encoded-vs-decoded mismatch was inconsistent within the same module.

Solution
Decode url.path before normalizing separators and matching against the pattern, mirroring the existing watchUrls() call site. The fix generalizes to any URL-encoded segment, not just spaces.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

The PR enhances URL matching robustness by updating checkUrlMatches to decode percent-encoded URL paths before performing path normalization and substring matching. A corresponding test validates the fix with URL-encoded spaces.

Changes

URL Path Decoding Enhancement

Layer / File(s) Summary
Core Implementation
ktor-server/ktor-server-core/jvm/src/io/ktor/server/engine/EmbeddedServerJvm.kt
The checkUrlMatches function is updated to decode url.path using UTF-8 URLDecoder before normalizing path separators, replacing the prior approach that only normalized separators without decoding. Early-exit behavior when url.path is absent is preserved.
Test Coverage
ktor-server/ktor-server-core/jvm/test/io/ktor/server/engine/EmbeddedServerTest.kt
A new test case verifies that checkUrlMatches correctly matches URL-encoded spaces (%20) in the path against a pattern using the decoded form.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: decoding URL-encoded paths before matching watch patterns, referencing the related issue KTOR-8199.
Description check ✅ Passed The description includes all required sections (Subsystem, Motivation, Solution) with comprehensive details about the problem, its root cause, and the implemented fix.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

🧹 Nitpick comments (2)
ktor-server/ktor-server-core/jvm/test/io/ktor/server/engine/EmbeddedServerTest.kt (1)

2-2: 💤 Low value

Update copyright year to 2025.

The copyright year in this file shows 2024, while the main source file uses 2025. Consider updating for consistency.

♻️ Proposed fix
-/*
- * Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
- */
+/*
+ * Copyright 2014-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
+ */
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ktor-server/ktor-server-core/jvm/test/io/ktor/server/engine/EmbeddedServerTest.kt`
at line 2, Update the copyright year in EmbeddedServerTest.kt from 2014-2024 to
2014-2025 to match the main source files; open the file (EmbeddedServerTest.kt)
and edit the header comment line that currently contains "Copyright 2014-2024"
so it reads "Copyright 2014-2025".
ktor-server/ktor-server-core/jvm/src/io/ktor/server/engine/EmbeddedServerJvm.kt (1)

496-496: ⚡ Quick win

Prefer Charsets.UTF_8 over string literal.

Use the Charsets.UTF_8 constant instead of the string literal "utf-8" for better type safety and consistency with Kotlin conventions.

♻️ Proposed fix
-    val urlPath = URLDecoder.decode(rawPath, "utf-8").replace(File.separatorChar, '/')
+    val urlPath = URLDecoder.decode(rawPath, Charsets.UTF_8.name()).replace(File.separatorChar, '/')

Or if using Kotlin 1.5+, you can use the extension function:

-    val urlPath = URLDecoder.decode(rawPath, "utf-8").replace(File.separatorChar, '/')
+    val urlPath = rawPath.decodeURLQueryComponent().replace(File.separatorChar, '/')

Note: The second option requires import io.ktor.http.decodeURLQueryComponent from ktor-http, which is already imported in this file (line 9).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ktor-server/ktor-server-core/jvm/src/io/ktor/server/engine/EmbeddedServerJvm.kt`
at line 496, Replace the string literal "utf-8" in the URL decoding call with
the Kotlin charset constant to follow conventions: update the
URLDecoder.decode(rawPath, "utf-8") usage (in the urlPath assignment in
EmbeddedServerJvm.kt) to use Charsets.UTF_8 (or, if you prefer the ktor helper,
call the existing decodeURLQueryComponent extension on rawPath) so the charset
is type-safe and consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@ktor-server/ktor-server-core/jvm/src/io/ktor/server/engine/EmbeddedServerJvm.kt`:
- Line 496: Replace the string literal "utf-8" in the URL decoding call with the
Kotlin charset constant to follow conventions: update the
URLDecoder.decode(rawPath, "utf-8") usage (in the urlPath assignment in
EmbeddedServerJvm.kt) to use Charsets.UTF_8 (or, if you prefer the ktor helper,
call the existing decodeURLQueryComponent extension on rawPath) so the charset
is type-safe and consistent.

In
`@ktor-server/ktor-server-core/jvm/test/io/ktor/server/engine/EmbeddedServerTest.kt`:
- Line 2: Update the copyright year in EmbeddedServerTest.kt from 2014-2024 to
2014-2025 to match the main source files; open the file (EmbeddedServerTest.kt)
and edit the header comment line that currently contains "Copyright 2014-2024"
so it reads "Copyright 2014-2025".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 58cbaaa9-1e47-4e76-8b4d-afb90deb1375

📥 Commits

Reviewing files that changed from the base of the PR and between 2413814 and 67c4c6e.

📒 Files selected for processing (2)
  • ktor-server/ktor-server-core/jvm/src/io/ktor/server/engine/EmbeddedServerJvm.kt
  • ktor-server/ktor-server-core/jvm/test/io/ktor/server/engine/EmbeddedServerTest.kt

Copy link
Copy Markdown
Member

@osipxd osipxd left a comment

Choose a reason for hiding this comment

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

Thank you for the fix!

@osipxd osipxd merged commit 6d662e1 into ktorio:main May 8, 2026
22 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.

2 participants