-
Notifications
You must be signed in to change notification settings - Fork 540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(fetch): add support for file urls in fetch #1239
Conversation
e0525c3
to
1d0539c
Compare
1d0539c
to
2b5a7c2
Compare
@@ -882,7 +883,7 @@ async function schemeFetch (fetchParams) { | |||
case 'file:': { | |||
// For now, unfortunate as it is, file URLs are left as an exercise for the reader. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's from the spec itself, other comments also include the text from the spec itself.
async function fileFetch (fetchParams) { | ||
const { request } = fetchParams | ||
const url = requestCurrentURL(request) | ||
const context = this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is context just not this
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's the same style that's used in other methods, so I wanted to keep it the same.
const url = requestCurrentURL(request) | ||
const context = this | ||
if (request.method !== 'GET') { | ||
return makeNetworkError(`Fetching files only supports the GET method. Received ${request.method}`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do browsers do with HEAD?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at what Deno does, I even kept the message the same. I assume that Chrome behaves in a similar way, but I'll check it out.
response.aborted = true | ||
stream.destroy(new AbortError()) | ||
} else { | ||
stream.destroy(new TypeError('terminated')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not specific to these PR but these errors should have codes?
(That seems orthogonal though)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at what's done in other methods, so changes might need to get made in other places as well.
t.ok(err.cause) | ||
t.equal(err.cause.code, 'ENOENT') | ||
} | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test AbortSignal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, tests are the main thing that's missing and why I've put this as a draft (also need to see what to do with headers)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good progress
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a way to control the security of this. There are quite a few possible attacks when reading files from disk on servers.
My opinion is that we should aim to a "close by default" approach vs "open by default".
I would recommend we add a "FileSystemEnabledAgent" that can direct requests to disk in case we need it to be. This entity will be responsible to configure what paths could be served.
This kind of change would make this less portable (which was one of the reasons why this was requested), as I assume that other implementation don't have such constructions (I'll check them out). Is going out of spec and adding a flag or forcing |
So your concern is that we get an external URL from the user and they send over a |
That's not correct. In the browser this is managed by CSP and others. Unfortunately Node.js is not a browser and we have to deal with more strict security constraints, so I don't think this can be enabled by default without checks. |
Exactly that. Moreover I might want to send a URL to read a file that is restricted in a given folder. |
Yes, of course. What I meant was that I didn't think the fetch method had such parameters. I edited my message after you already quoted me, where I asked if you meant that we should add some kind of global configuration for fetch that would allow such behaviour? |
We usually include those configuration inside the |
Asked about this in Deno btw: denoland/deno#11925 (comment) |
I think there should also be some warning that this behavior can change at any times; once (or if - file uris have been left to the implementation for years now) the spec includes steps for handling file:// urls, this will have to be rewritten and it's very likely that the behavior will change. I believe that only Firefox and Deno handle file urls at the moment as well, which means it's not technically spec compliant and not widely available. |
While it's not a web option, could we just have an option to // file.js
const myResource = new URL("./resource.txt", import.meta.url);
const resourceText = await fetch(myResource, {
// If file.js is loaded in Node.js then myResource will be some file:// url in which
// case Node.js will see this option and allow it,
// In browsers myResource will generally be a https:// url and will just ignore this
// options proceeding per normal
allowFileURLs: true,
}).then(res => res.text()); By having such an option, other |
I agree that this feature is useful, and I'd be happy to get this into undici if we can agree on how to make everyone happy with its security. |
Go ahead and add this option, I think it's a good addition. I would use a more ugly-and-prefixed name for it to avoid any potential conflicts with whatwg. Anyhow, I'd recommend you to open an issue at wintercg/fetch. |
I would prefer to leave this to wintercg/fetch#5 instead of implementing a non-spec compliant solution. |
This PR adds support for file urls in fetch
refs: nodejs/node#42003
According to the fetch spec, file urls are "left as an exercise for the reader."
https://fetch.spec.whatwg.org/#scheme-fetch