fix: open Windows file URLs that name a drive letter - #1592
Open
sushantlokhande14 wants to merge 1 commit into
Open
sushantlokhande14 wants to merge 1 commit into
sushantlokhande14 wants to merge 1 commit into
Conversation
A file URL for a Windows path puts the drive letter after a leading slash, as
RFC 8089 requires: file:///C:/logs/app.log parses to the path
"/C:/logs/app.log". newFileSinkFromURL passed that path straight to
os.OpenFile, which Windows rejects ("The filename, directory name, or volume
label syntax is incorrect"), so every file URL naming a local drive failed,
with or without an explicit localhost host.
On Windows, drop the slash ahead of a drive letter before opening the file.
Windows accepts the forward slashes that remain, so no further translation is
needed. Whether to apply the rule is a field on the sink registry, defaulting
to runtime.GOOS, so the Windows handling is exercised on every platform
through the existing openFile stub rather than only on Windows machines.
The file URL cases in TestOpen and TestOpenOtherErrors built URLs by appending
the temp path to "file://", which produces "file://C:\..." on Windows. They now
build the RFC 8089 form, which is byte-identical on Unix-like systems.
Refs uber-go#621
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1592 +/- ##
==========================================
+ Coverage 98.85% 98.88% +0.03%
==========================================
Files 53 53
Lines 3047 3057 +10
==========================================
+ Hits 3012 3023 +11
+ Misses 35 34 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #621.
Problem
RFC 8089 puts a Windows drive letter after a leading slash, so
file:///C:/logs/app.logparses to the path/C:/logs/app.log.newFileSinkFromURLpassed that straight toos.OpenFile, and Windows cannot open it.Reproduced on Windows 11, Go 1.26.5, against master. The same file, named three ways:
A plain absolute path works, because #1159 routes those through
filepath.IsAbs. Every file URL naming a local drive fails, with or without an explicitlocalhosthost. That is the gap #1159 called out in its own description: "this change does not bring full Windows support ... Windows file URIs don't work."Fix
On Windows, drop the slash ahead of a drive letter before opening. Windows accepts the forward slashes that remain, so no other translation is needed — verified directly with
os.OpenFileon aC:/...path.Whether to apply the rule is a field on
sinkRegistry, defaulting toruntime.GOOS == "windows", rather than aruntime.GOOScheck at the call site. That is deliberate: on #621 @abhinav noted the issue stayed open partly because "none of the active maintainers have Windows machines" and the edit-test-debug loop was too slow. CI here is Ubuntu-only andsink_windows_test.gonever runs in it. Making this a registry field means the Windows behaviour is exercised on every platform, in CI, through theopenFilestub #1159 already added.The prefix test is deliberately strict: a slash, an ASCII letter, a colon, then a slash. Anything shorter or otherwise shaped is returned unchanged.
Tests
TestFileURLPathcovers the helper directly (8 cases, both platform modes): drive letters upper and lower, a path with no drive, a bare/C:, a non-letter "drive", empty input, and non-Windows inputs that must keep the leading slash.TestWindowsFileURLsdrives the real path throughnewSinkwithisWindowsforced on andopenFilestubbed, asserting the exact filename opened — empty host, explicitlocalhost, and a percent-encoded space. Both run on Linux.Reverting only the call site (
sr.fileURLPath(u.Path)back tou.Path) makes all threeTestWindowsFileURLscases fail, so the test guards the fix rather than the helper.Test construction on Windows
TestOpenandTestOpenOtherErrorsbuilt file URLs by appending the temp path to"file://". On Unix that yieldsfile:///tmp/...because the path already starts with a slash. On Windows it puts the drive in the host position, producing an unparseable URL, which is why those tests fail there today. They now build the RFC 8089 form. The output is byte-identical on Unix-like systems, andTestOpenpasses on Windows as a result.Verification
go test .on Windows:TestOpen,TestOpenOtherErrors,TestFileURLPath,TestWindowsFileURLsand the existingTestWindowsPathsall pass.TestOpenandTestOpenOtherErrorsfailed before this change.TestConfig,TestConfigWithSamplingHookandzapcore.TestIOCore(temp-file cleanup while a log file is still open),TestStacktraceFiltersVendorZap, andExample_basicConfiguration.gofmtandgofumptclean on all three files;golangci-lint run ./...reports nothing for them.Relationship to #624
#624 (2018) proposed the same basic idea and is still open, but has not been touched in years. This supersedes it rather than duplicating it:
u.Path[2]with no length check, so a URL likefile:///apanicsnewFileSink, which Open absolute paths as files, limited Windows support #1159 replaced in 2022Its review also stalled on whether the change was needed at all, with two slashes suggested instead. #621 settled that two days later: "It looks like it has to be 3 slashes."
Note on #1398
#1398 adds a
..check immediately above the line this touches. If that lands first, this becomessr.newFileSinkFromPath(sr.fileURLPath(u.Path))after that check — happy to rebase in whichever order suits you.Non-goals
UNC URLs (
file://server/share/...) are still rejected by the existing host check. A barefile:///C:with no trailing slash is left unchanged, since it names a drive rather than a file. The temp-file cleanup failures above are a separate issue.AI tool usage
AI assistance (Claude Code) was used to locate this defect and draft the patch and tests. I reviewed every line, ran everything above locally on Windows, and can defend the change end to end.