Page MenuHomePhabricator

Support Promise-Non-Write-API-Action in m3api?
Open, Needs TriagePublic

Description

I learned a few months ago that MediaWiki supports a Promise-Non-Write-API-Action: true header on POST requests; if this header is used, the request is still routed like a GET request, possibly to a data center with less latency than the read-write data center. (@Krinkle mentioned that the QUERY method might eventually make this header obsolete.)

Should we support sending this header in m3api? And if yes, should it be a separate request option (e.g. { method: 'POST', promiseNonWriteApiAction: true }) or be part of the method (e.g. { method: 'POST+Promise-Non-Write-API-Action' })?

Issue migrated from #31.

Event Timeline

Copying @Krinkle’s comment together with my very belated reply:

The client could bundle a list of read-only MW actions, and automatically add Promise-Non-Write-API-Action: true if a POST request calls one of these actions.

Possible, but then that bloats the library a little bit, and ideally the list of read-only actions would be extensible by clients to support MediaWiki extensions that m3api doesn’t know about… to me it seems like a bit too much complexity for a feature that nobody’s explicitly asked so far.

How many known actual use cases are there for this header anyway? (I.e. API modules which take inputs that might be too long for a GET request?) The documentation only mentions parse; looking through the API sandbox, I think compare might potentially qualify as well. Given that this whole feature is just a performance optimization, I think I could live with hard-coding a check for just those two API modules, and add the header unconditionally for them, but not for query etc.

Alternatively, you could be bold and accept the method QUERY today, and translate it to POST with Promise-Non-Write-API-Action: true.

I don’t like this, because then it’s not clear when I can stop doing this translation. m3api should be useful for any MediaWiki site, but I can’t know when an arbitrary third-party wiki starts supporting QUERY. If m3api translates QUERY to POST + header, then people might use “QUERY” with wikis that don’t actually support the header, and it would “work” (it would just do nothing, the header would be ignored), but then break when m3api changes to send actual QUERY methods.

On the other hand, if I do nothing, then it’s up to the application author to know when QUERY will work or not, and I don’t have to change anything in the library. (Both browsers and Node.js already let you send QUERY – or any other fictional method – using fetch() today, which is a bit weird but I’m not complaining.)

How many known actual use cases are there for this header anyway? (I.e. API modules which take inputs that might be too long for a GET request?) The documentation only mentions parse; looking through the API sandbox, I think compare might potentially qualify as well. Given that this whole feature is just a performance optimization, I think I could live with hard-coding a check for just those two API modules, and add the header unconditionally for them, but not for query etc.

I've personally hit the limit in the real world when fetching Wikipedia pages (mostly churches, which happen to have quite long names) by their Cyrillic titles using query. The calculation goes something like this: 50 (amount of titles) * 30 (characters per title) * 2 (bytes per character for Cyrillic encoded in UTF-8) * 3 (percent encoded since it's non-ASCII) = 9000, which is already above the limit. That one character expands to a whole of 6 bytes is quite unfortunate.

On the other hand, if I do nothing, then it’s up to the application author to know when QUERY will work or not, and I don’t have to change anything in the library. (Both browsers and Node.js already let you send QUERY – or any other fictional method – using fetch() today, which is a bit weird but I’m not complaining.)

Lol, no, that’s not how it works. I included some code in the library that explicitly only allows GET and POST 🤦

So this task remains valid, though I’ll probably repurpose it into “support sending QUERY requests”, assuming T410883 doesn’t get stalled for ages. I was planning to refactor the internal interface for network requests anyway, this might be a good opportunity for that.