-
Notifications
You must be signed in to change notification settings - Fork 0
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
Support file parameters (upload) #26
Comments
Let’s make this part of the 1.0 milestone (and probably try to get it done before 0.8, which would otherwise just be the release that drops Node 12 compat with no new features). If it turns out to be more difficult or less doable than expected, we can always kick it out again. |
If we bump the Node requirement from 16 to 18 (cf. #25), then we get a whole lot of nice things that are useful for this feature, I think:
At that point, we could even drop axios, and just use http-cookie-agent with Node’s native There is one issue with this, which is that adding a
(In Node 20, it’s stable.) But given that it works, and you can suppress the warning with |
Try to use browser APIs in Node.js as much as possible, now that Node supports fetch(). This requires bumping our Node.js requirement to version 18.2.0 (fetch() is available since Node 18.0.0, but the dispatcher option needed by http-cookie-agent only since 18.2.0), so we can also drop the second GitHub Actions job. fetch.js is now the base implementation of both node.js and browser.js; fetch-node.js adds cookie support, while fetch-browser.js renames the user-agent header to api-user-agent because Chrome doesn’t care about web standards that clearly say user-agent is allowed to be set. Unfortunately, http-cookie-agent still requires undici to be installed even when it’s also built into Node, because Node doesn’t expose the necessary internals to use the dispatcher option mentioned above. Related to #26 (though we don’t actually support file uploads yet) as well as #25.
95e551f implements a replacement of axios with native
My feeling is that this isn’t just unsatisfying due to undici slightly burdening the I think I’ll put together an implementation of file uploads based on axios, and see how that shakes out. The native |
I’ll have to try it out (probably tomorrow) to be sure, but I think with axios we can even support file parameters without bumping the Node requirement to 18. Axios will accept |
I’ve had this vaguely planned for a while, and now seems like a good time to do it, as we’re about to add more allowed param types for #26.
So I’m running into several problems. Uploads on the Beta cluster have been broken for months (T340908), so I can’t integration-test this as well as I hoped. I think the available options are testing against the production cluster instead (see discussion with @legoktm), or still testing against the beta cluster and just treating I also only managed to make diff --git a/axios.js b/axios.js
index d93e4fbf34..68f99f1f21 100644
--- a/axios.js
+++ b/axios.js
@@ -39,6 +39,10 @@ class AxiosSession extends Session {
}
async internalPost( apiUrl, urlParams, bodyParams, headers ) {
+ const bodyFormData = new FormData();
+ for ( const [ paramName, paramValue ] of Object.entries( bodyParams ) ) {
+ bodyFormData.append( paramName, paramValue, typeof paramValue === 'string' ? {} : { filename: 'whatever.jpg' } );
+ }
const response = await this.session.request( {
method: 'POST',
baseURL: apiUrl, Because MediaWiki will refuse to process a file as upload unless it has a file name in the Content-Disposition (even though it’s not going to use that file name), but at the same time, non-file parameters must not have a file name. So we need to tell I think I might try the native fetch + undici version again and see if |
Okay, an
But what’s still missing, and may or may not be doable at all, is integration with |
Would a Also, we are already using Axios in Wikidocumentaries. |
No, |
Hahaaa, this is the entirety of the diff needed to make diff --git a/fetch.js b/fetch.js
index ad31477586..f3e0033996 100644
--- a/fetch.js
+++ b/fetch.js
@@ -45,10 +45,14 @@ class FetchSession extends Session {
async internalPost( apiUrl, urlParams, bodyParams, headers ) {
const url = new URL( apiUrl );
url.search = new URLSearchParams( urlParams );
+ const body = new FormData();
+ for ( const [ paramName, paramValue ] of Object.entries( bodyParams ) ) {
+ body.append( paramName, paramValue );
+ }
const response = await fetch( url, {
...this.getFetchOptions( headers ),
method: 'POST',
- body: new URLSearchParams( bodyParams ),
+ body,
} );
return transformResponse( response );
} (If anyone’s curious, I’m creating the param values as That’s a pretty strong argument in favor of native fetch, I have to say. |
Awesome - thank you! Time spent to find the simplest approach is well spent. Could @zexigong start testing this already by |
I didn’t push any commit with that diff yet, but I can if it helps you testing. |
When we’re using native fetch() everywhere, this is quite simple: we just have to specify the body as FormData instead of URLSearchParams. Implements #26.
Alright, pushed to the |
Beta is not stable enough, and uploads in particular have been broken for months (T340908 [1]), so if I want to integration-test file parameters (#26), I either need to tolerate those errors or target production. Based on a discussion with @legoktm [2], using Test Wikipedia for this seems fine. Also update the example command(s) in .env.example to avoid a race condition: with cp+chmod, another user can open the file while it’s still world-readable, then read secrets from the open file descriptor later, since permissions are only checked on open(2) not read(2). [1]: https://phabricator.wikimedia.org/T340908 [2]: https://wikis.world/@legoktm/110639639612274985
Try to use browser APIs in Node.js as much as possible, now that Node supports fetch(). This requires bumping our Node.js requirement to version 18.2.0 (fetch() is available since Node 18.0.0, but the dispatcher option needed by http-cookie-agent only since 18.2.0), so we can also drop the second GitHub Actions job. fetch.js is now the base implementation of both node.js and browser.js; fetch-node.js adds cookie support, while fetch-browser.js renames the user-agent header to api-user-agent because Chrome doesn’t care about web standards that clearly say user-agent is allowed to be set. Unfortunately, http-cookie-agent still requires undici to be installed even when it’s also built into Node, because Node doesn’t expose the necessary internals to use the dispatcher option mentioned above. Related to #26 (though we don’t actually support file uploads yet) as well as #25. This also shrinks our non-dev node_modules from 2913282 to 2073521 bytes, a 28% reduction, which is pretty sweet.
When we’re using native fetch() everywhere, this is quite simple: we just have to specify the body as FormData instead of URLSearchParams. Implements #26.
When we’re using native fetch() everywhere, this is quite simple: we just have to specify the body as FormData instead of URLSearchParams. (Although the tests need to import File from buffer in Node 18.) Implements #26.
And now merged on |
Released in v0.8.0 the other day. @tuukka I’d be interested to know if it works for you or not :) |
I don’t think we support this yet, but we should. (I’ll need to look into what the API should look like – probably
Blob
as parameter type? But let’s see what e.g.fetch()
accepts.)The text was updated successfully, but these errors were encountered: