Skip to content

Webmachine URL Map produces malformed JSON when listing resources. [JIRA: RIAK-2376] #102

@pyrrho

Description

@pyrrho

tl;dr -- Running curl -XGET http://localhost:10018/ -H "Accept: application/json" returns malformed JSON.

Call Stack:
https://github.com/basho/riak_api/blob/develop/src/riak_api_wm_urlmap.erl#L74-L75
https://github.com/basho/mochiweb/blob/master/src/mochijson.erl#L53-L56
https://github.com/basho/mochiweb/blob/master/src/mochijson.erl#L121-L122
https://github.com/basho/mochiweb/blob/master/src/mochijson.erl#L137-L153

I believe the Services variable in mochijson:encode({struct, Services}) should be transformed to aggregate URIs into tuples per Resource ({Resource, {Uri1, Uri2, ...} },) before being encoded.

Longer Version:

Manually prettified, the output I see running curl -XGET http://localhost:10018/ -H "Accept: application/json" on a 2.1.3 devrel is,

{
    "riak_kv_wm_bucket_type":"/types",
    "riak_kv_wm_buckets":"/buckets",
    "riak_kv_wm_buckets":"/riak",
    "riak_kv_wm_buckets":"/types",
    "riak_kv_wm_counter":"/buckets",
    "riak_kv_wm_crdt":"/types",
    "riak_kv_wm_index":"/buckets",
    "riak_kv_wm_index":"/types",
    "riak_kv_wm_keylist":"/buckets",
    "riak_kv_wm_keylist":"/types",
    "riak_kv_wm_link_walker":"/buckets",
    "riak_kv_wm_link_walker":"/riak",
    "riak_kv_wm_link_walker":"/types",
    "riak_kv_wm_mapred":"/mapred",
    "riak_kv_wm_object":"/buckets",
    "riak_kv_wm_object":"/riak",
    "riak_kv_wm_object":"/types",
    "riak_kv_wm_ping":"/ping",
    "riak_kv_wm_preflist":"/buckets",
    "riak_kv_wm_preflist":"/types",
    "riak_kv_wm_props":"/buckets",
    "riak_kv_wm_props":"/types",
    "riak_kv_wm_stats":"/stats",
    "riak_repl_wm_stats":"/riak-repl"
}

Note the multiple instances of e.g. "riak_kv_wm_buckets":. . . and "riak_kv_wm_object":. . .. In the case of duplicate names in JSON objects, the value associated with the last instance of a given name will be returned. As such, pushing the above through a JSON interpreter yields,

$ curl -XGET http://localhost:10018/ -H "Accept: application/json" | json_pp
{
   "riak_kv_wm_crdt" : "/types",
   "riak_kv_wm_link_walker" : "/types",
   "riak_kv_wm_preflist" : "/types",
   "riak_kv_wm_ping" : "/ping",
   "riak_kv_wm_index" : "/types",
   "riak_kv_wm_props" : "/types",
   "riak_kv_wm_object" : "/types",
   "riak_kv_wm_stats" : "/stats",
   "riak_kv_wm_counter" : "/buckets",
   "riak_repl_wm_stats" : "/riak-repl",
   "riak_kv_wm_buckets" : "/types",
   "riak_kv_wm_keylist" : "/types",
   "riak_kv_wm_bucket_type" : "/types",
   "riak_kv_wm_mapred" : "/mapred"
}

Rather than collapsing values down to a single string, we should very likely return a lists (e.g. "riak_kv_wm_buckets": ["/buckets", "/riak", "/types"],).

It should be well noted that systems that consume JSON output of the resources lists will need to be modified as well.
For example This issue was found when working through the Python Client code, comparing versions 2.0.2 and 2.4.0. Specifically,

In the former case, the client is expecting a single specific string to be returned -- in this case, "/buckets". In the later, the fact that the single specific string was suddenly "/types" was essentially ignored. It would be reasonably easy to update these calls to look for a certain element in returned lists, and act according to their existence/absence.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions