Updated Answer
Turning to your questions (as opposed to moving a little tangentially in my original answer: D), here are my opinions:
1) My main opinion on this is that I do not like d . As a client consuming an API, I find it confusing. What does it mean? data?
Other options look good. Columns nice because it is calling the user with a request.
If you are paginating, then the other option may be something like page or slice , because it makes it clear to the client that they do not receive the entire contents of the collection.
{ "offset": 0, "limit": 100, "page" : [ ... ] }
2) TBH, I don’t think that it greatly affects how you do it, however, if it were me, I probably would not send the envelope back, since I don’t think there are any ( see below) and why make the query structure more complex than it should be?
I think posting back the envelope would be strange. POST should allow you to add items to the collection, so why would the client need to place an envelope for this?
Resetting the envelope may make sense from a RESTful point of view, as it can be seen as updating the metadata associated with the collection as a whole. I think it's worth considering which metadata you will strip in the envelope. All material that, it seems to me, fits well into this envelope (for example, pagination, clusters, fax searches and similar metadata) is read-only, so the client has nothing to send back to the server. If you find that there is a lot of data in the envelope that the client can mutate, then it may be familiar to break this data into a separate resource with a list as a subcategory. Example garbage:
/animals
{ "farmName": "farm", "paging": {}, "animals": [ ... ] }
It can be divided into:
/farm/1
{ "id": 1, "farmName": "farm" }
and
/farm/1/animals
{ "paging": {}, "animals": [ ... ] }
Note. Even with this section, you can still return both combined as a single response using something like Facebook or the LinkedIn field extension syntax . For example. http://example.com/api/farm/1?field=animals.offset(0).limit(10)
In answer to your question about how the client should know what JSON payload they represent POSTING and PUTing, it should look like this: this should be reflected in the API documentation. I'm not sure if there is a better tool for this, but Swagger provides a specification that allows you to document which request bodies should look like this: JSON schema - check this page to determine your schemas and this page to reference them as a parameter of type body . Unfortunately, Swagger does not yet visualize the request organs in this fraudulent web interface, but it is open source, so you can always add something for this.
Original answer
Mark William’s comment on the discussion topic on this page - it offers a way to avoid the exploit altogether, which means that you can safely use the JSON array at the root of your answer, and then you don’t have to worry about any of the questions.
The exploit you use relies on your API using cookies to authenticate the user session - instead, just use the query string parameter and you will remove the exploit. This is probably worth doing, because using cookies for authentication in the API is not very RESTful - some of your clients may not be web browsers and may not want to deal with cookies.
Why does this fix work?
An exploit is a form of CSRF attack that assumes that an attacker can add a script tag to his own page on a sensitive resource of your API.
<script src="http://mysite.com/api/columns"></script>
The victim’s web browser will send all cookies stored in mysite.com to your server and to your servers, it will look like a legitimate request - you will check the session_id cookie (or whatever your server infrastructure calls the cookie) and see that the user is authenticated. The request will look like this:
GET http://mysite.com/api/columns Cookie: session_id=123456789;
If you change your API, you ignore Cookies and use the session_id string parameter instead, the attacker will not be able to trick the victims web browser by sending session_id to your API.
Now the actual request will look like this:
GET http:
If you use the JavaScript client to execute the above request, you can get session_id from the cookie. An attacker using JavaScript from another domain will not be able to do this, since you cannot receive cookies for other domains ( see here ).
Now we fixed the problem and ignore the session_id cookie, the script tag on the attackers website will still send a similar request using the GET string as follows:
GET http:
But your server will respond with 403 Forbidden , as the required parameter for the session_id string is missing from GET.
What if I do not authenticate users for this API?
If you do not authenticate users, your data may not be sensitive, and anyone can call a URI. CSRF should be no problem, because without authentication, even if you prevent CSRF attacks, an attacker could just call your side of the API server to get your data and use it anyway.