Page MenuHomePhabricator

alternative multiple-value separator is ignored
Open, Needs TriagePublicBUG REPORT

Description

List of steps to reproduce (step by step, including full links if applicable):
If any value passed contains the pipe character (|), use the alternative multiple-value separator for correct operation.

If a value must contain the pipe character, use U+001F (Unit Separator) as the separator and prefix the value with U+001F, e.g. param=%1Fvalue1%1Fvalue2.

..

api = new mw.Api;
api.postWithEditToken( {format: 'json', action: 'options', change:'userjs-Test=%1F{"foo1":{},"foo2":{},"foo3":"[[link|name]]"}' } ).then( function ( data ) { console.log(data);});

reload page

mw.user.options.get('userjs-Test')

What happens?:
"%1F{\"foo1\":{},\"foo2\":{},\"foo3\":\"[[link"

What should have happened instead?:
"{\"foo1\":{},\"foo2\":{},\"foo3\":\"[[link|name]]"}"

Event Timeline

Umherirrender edited projects, added JavaScript; removed MediaWiki-Action-API.
Umherirrender subscribed.

You can use

api.postWithEditToken( {format: 'json', action: 'options', change: [ 'userjs-Test={"foo1":{},"foo2":{},"foo3":"[[link|name]]"}' ] } ).then( function ( data ) { console.log(data);});

and mw.API would add the 1F as needed. If you use %1F in the {} it gets url-encoded by mw.API and is not working as expected.

Use

api.postWithEditToken( {format: 'json', action: 'options', change:'\x1Fuserjs-Test={"foo1":{},"foo2":{},"foo3":"[[link|name]]"}' } ).then( function ( data ) { console.log(data);});

to get the 1F url-encoded correctly (and not twice)

That's not what the documentation says. I don't care if the software or the documentation is at fault here. Documentation says jump, I jump, and my preference got truncated.

Parameters that take multiple values are normally submitted with the values separated using the pipe character, e.g. param=value1|value2 or param=value1%7Cvalue2. If a value must contain the pipe character, use U+001F (Unit Separator) as the separator and prefix the value with U+001F, e.g. param=%1Fvalue1%1Fvalue2.

The param of the documentation is change in your example, not userjs-Test or {"foo1":{},"foo2":{},"foo3":"[[link|name]]"}.
The value1 is userjs-Test={"foo1":{},"foo2":{},"foo3":"[[link|name]]"}. I suggest to use the \x1F at the begin of the value and that works. The use of %1F does not work, because it gets urlencoded. Same when using %7B instead of {, which get stored in the database as given (%7B).

@AlexisJazz: Which exact documentation sentence (quote) where (URL)?

@AlexisJazz: Which exact documentation sentence (quote) where (URL)?

I had linked it in the task description so I'm not sure what you mean?

Parameters that take multiple values are normally submitted with the values separated using the pipe character, e.g. param=value1|value2 or param=value1%7Cvalue2. If a value must contain the pipe character, use U+001F (Unit Separator) as the separator and prefix the value with U+001F, e.g. param=%1Fvalue1%1Fvalue2.

The param of the documentation is change in your example, not userjs-Test or {"foo1":{},"foo2":{},"foo3":"[[link|name]]"}.
The value1 is userjs-Test={"foo1":{},"foo2":{},"foo3":"[[link|name]]"}. I suggest to use the \x1F at the begin of the value and that works. The use of %1F does not work, because it gets urlencoded. Same when using %7B instead of {, which get stored in the database as given (%7B).

I'm confused.

api = new mw.Api;
api.postWithEditToken( {format: 'json', action: 'options', change: 'userjs-Test1=testvalue1|userjs-Test2=testvalue2' } ).then( function ( data ) { console.log(data);});

reload
mw.user.options.get('userjs-Test1') returns "testvalue1".
mw.user.options.get('userjs-Test2') returns "testvalue2".
So this works. https://en.wikipedia.org/w/api.php?action=help&modules=options says "If any value passed contains the pipe character (|), use the alternative multiple-value separator for correct operation." So I did. And it didn't work.

You can write

api = new mw.Api;
api.postWithEditToken( {format: 'json', action: 'options', change: 'userjs-Test1=testvalue1|userjs-Test2=testvalue2' } ).then( function ( data ) { console.log(data);});

as this (to get mw.Api adding | or \x1F)

api = new mw.Api;
api.postWithEditToken( {format: 'json', action: 'options', change: [ 'userjs-Test1=testvalue1', 'userjs-Test2=testvalue2' ] } ).then( function ( data ) { console.log(data);});

or this (to add it directly in the arguments)

api = new mw.Api;
api.postWithEditToken( {format: 'json', action: 'options', change: '\x1Fuserjs-Test1=testvalue1\x1Fuserjs-Test2=testvalue2' } ).then( function ( data ) { console.log(data);});

but https://en.wikipedia.org/w/api.php?action=help&modules=options says how the api call has to look for the server, when using api.php directly. When using mw.Api some doc is at https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api, but that does not inform about multi-value arguments at all.

You can write

api = new mw.Api;
api.postWithEditToken( {format: 'json', action: 'options', change: 'userjs-Test1=testvalue1|userjs-Test2=testvalue2' } ).then( function ( data ) { console.log(data);});

as this (to get mw.Api adding | or \x1F)

api = new mw.Api;
api.postWithEditToken( {format: 'json', action: 'options', change: [ 'userjs-Test1=testvalue1', 'userjs-Test2=testvalue2' ] } ).then( function ( data ) { console.log(data);});

or this (to add it directly in the arguments)

api = new mw.Api;
api.postWithEditToken( {format: 'json', action: 'options', change: '\x1Fuserjs-Test1=testvalue1\x1Fuserjs-Test2=testvalue2' } ).then( function ( data ) { console.log(data);});

but https://en.wikipedia.org/w/api.php?action=help&modules=options says how the api call has to look for the server, when using api.php directly. When using mw.Api some doc is at https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api, but that does not inform about multi-value arguments at all.

In addition to that, as api.php?action=help is what you'd be reading when trying to figure out how to make some API call, it would be helpful if it would link the mw.Api documentation (which will need to actually include the relevant information) where data fed to mw.Api differs significantly from using api.php directly.

Side note: for the longest time I didn't even know mw.Api exists at all. Scripts I had read didn't use it and hardly anyone ever links doc.wikimedia.org. I found out when some WMF developer casually used it for an example of something unrelated. mw.Api needs better PR.

mw.Api is a helper/framework to make requests against api.php on wiki pages of MediaWiki wikis. To read action=help you can also visit Special:ApiSandbox on that wiki and use a gui to build up your query

It provides some solution for abstraction things of api.php like the multi-value separator linked in the task description (or handling of bool parameters). As mw.Api and api.php are two things, there should not linked together. When writing a bot in python or any other language it is not helpful to get a link to a javascript framwork, even it is build-in into MediaWiki (since 1.19/cb0cf72eba9ff456b4c4e0b5ca54f498265cf82f).

To call api.php it is also possible to use $.ajax or some old things like document.write + script tag.

mw.Api is a helper/framework to make requests against api.php on wiki pages of MediaWiki wikis. To read action=help you can also visit Special:ApiSandbox on that wiki and use a gui to build up your query

It provides some solution for abstraction things of api.php like the multi-value separator linked in the task description (or handling of bool parameters). As mw.Api and api.php are two things, there should not linked together. When writing a bot in python or any other language it is not helpful to get a link to a javascript framwork, even it is build-in into MediaWiki (since 1.19/cb0cf72eba9ff456b4c4e0b5ca54f498265cf82f).

To call api.php it is also possible to use $.ajax or some old things like document.write + script tag.

https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api already links https://www.mediawiki.org/wiki/API:Main_page. A line on https://www.mediawiki.org/w/api.php?action=help&modules=main#main/datatypes like "Note that the mw.Api Javascript helper can handle multiple values as an array." (and documenting that on the mw.Api docs) would be really helpful. If there are also special considerations for $.ajax or some another language there could be a note for those as well.