deno
deno copied to clipboard
URLPattern breaks on request.url for Unix socket listeners
When using Deno.listen({ path: "/tmp/file.sock", transport: "unix" })
for HTTP requests, in a request handler, the request.url
appears as http+unix://%2Ftmp%2Ffile%2Esock/url-path
. Unfortunately these Unix-socket URLs won't parse in the URLPattern interface.
While many of the URL router tools I've seen work totally off of paths and creating URLPattern objects from pathnames, I found myself wanting to process URL query parameters, and the simplest way to do this is going back to the full request.url
. Doing this while also using Unix socket listeners currently requires a touch of search-replace foo. Ideally this would "just work" someday.
We need to checking our implementation is bad or if this is a gap on the spec. @lucacasonato thoughts?
@wwoast what is the pattern you are trying to match against?
I was investigating this and came across something interesting:
with the sample code of new URLPattern({pathname: "/url-path"}).exec("http+unix://%2Ftmp%2Ffile%2Esock/url-path")
, running this in deno works (gives a resulting match), but in chrome this gives us null
.
on chrome new URL("http+unix://%2Ftmp%2Ffile%2Esock/url-path")
gives us an empty host and pathname: "//%2Ftmp%2Ffile%2Esock/url-path"
, whereas in deno we get host: "%2Ftmp%2Ffile%2Esock"
and pathname: "/url-path"
, meaning that either chrome is wrong or rust-url is wrong in this regard, though it doesnt seem to be related to this issue from what I understand from the original issue.
@crowlKats I get exceptions thrown when I try and provide the full URL as the initial input: const test = new URLPattern("http+unix://%2Ftmp%2Ffile%2Esock/url-path");
I assumed the reason this wasn't working was because Unix socket URIs were a "bespoke Deno thing" at the moment, and the JS engine stuff for URLPattern
didn't happen to know about it. It just caught me off guard when passing request.url
to URLPattern that was generated from a connection on a Unix socket.
oh i see. hm unsure how this could be fixed, as +
is a modifier in urlpattern syntax. whats your usecase for passing the full url as a pattern?
I suppose my only use-case is that passing request.url
to URLPattern is a convenience for simple base URLs where you wouldn't naturally expect to have any collisions with URLPattern metacharacters.
If there wasn't an onerous cost to changing the protocol string for Unix socket URIs, it would be nice if the convention for these URIs just worked as arguments to URLPattern.
Then again once you realize you need a workaround, it's not too painful:
const synthetic = "https://localhost/" + request.url.split("/").slice(3)
const url = new URLPattern(synthetic)
To help close this issue if possible, I wanted to propose an invariant (based on my casual expectation and my reading of MDN).
All
request.url
values should be well-formed base URLs
If this invariant is true, this issue sticks around and if not, it gets closed.
Answering my own question -- other URLPattern metacharacters do appear in the "base URL" when you open a Firefox console and inspect a Request object, i.e. new Request("https://gmail.com/mail?message=1")
. The ?
metacharacter that leads the query parameters wouldn't pass the URLPattern constructor.
I think it's reasonable to close this issue -- though I'm happy to investigate if there are related issues to this.