REST API - Endpoint syntax - get item by property - not by id - rest

I'm implementing my first REST API, and I have a question about the syntax of the URL endpoints.
I know that I should use these endpoint for get, create, update and delete:
Get list of items
Method: GET, Url: /api/items
Get item by id
Method: GET, Url: /api/items/:id
Add item (new item data in the request body)
Method: POST, Url: /api/items
Modify item (modified item data in the request body)
Method: PUT, Url: /api/items/:id
Delete item
Method: DELETE, Url: /api/items/:id
But lets say the interface of item is
interface item
{
id: string;
name: string;
}
What should be the request url for getting an item by it's name?
I can't use Method: GET, Url: /api/items/:name, because this will match the get-by-id request. So how should I syntax this endpoint?

There is no standard REST URI syntax unless you are doing OData for example. You have perfect freedom designing your own URIs, even /resource/{id} is perfectly valid.
What I like to do is end the URIs of collections with / and use queries for filtering collections. So I would do /api/{version}/items/?name={name} if they have unique names and you expect an item instead of a collection, then I would do it this way: /api/{version}/items/name:{name}. But this is my style.
From client perspective the URI syntax is totally irrelevant, because the server gives the valid URI templates to the client according to the HATEOES constraint. If you thought otherwise, then probably you are building a CRUD API instead of a REST API.

You chould use a filter on the collections endpoint like:
Method: GET, Url: /api/items?name=foo
This filter could return all items which have a foo string in them (depending on how you want to handle wildcards in the search / filter term), e.g. the response could be a collection of items:
{
"data": [
{
"id": "d079d8e9-4d24-4514-b356-78587f6c2ba9",
"name": "foo"
},
{
"id": "7f5e558c-6a7f-4ebe-8f4f-a2d029a803ed",
"name": "foo bar"
}
]
}
If you want the response to return a single resource you could also use the name as identifier and apply the scheme from above using the name, e.g.
Method: GET, Url: /api/items/:name

Related

A platform returns a POST method to an url and I want to retrieve the data to firestore

I want to retrieve the data from a third party platform that generates a POST call to an url that I can define. But I can only configure the url. I cannot configure the headers or the body of the POST action.
I want to store the JSON into a firestore collection.
The platform calls a POST action to a URL y can define, and that POST action has a JSON with the parameters I want to store.
In another post they directed me to the firestore API
https://stackoverflow.com/a/50061155/18276916
But there it is stated that the body of the POST action must have the following structure:
{
"writes": [
{
object (Write)
}
],
"labels": {
string: string,
...
}
}
The body of the POST action is defined in the third party aplication, and I cant modify it.
Is it posible to do this with Firestore, or is there another method I can use?
What would be the path of the url?:
https://firestore.googleapis.com/v1/projects/[my-project-id]/databases/(default)/documents/[my-collection-name]
Also, can I set the firestore rules to allow everyone to perform create actions so the call doesn't need to be authenticated
I found a solution that works
https://www.jeansnyman.com/posts/google-firestore-rest-api-examples/
With the following structure:
Url: https://firestore.googleapis.com/v1/projects//databases/(default)/documents/
Body:
{
fields: {
title: { stringValue: title },
category: { stringValue: category }
}
}
But here the body has its defined structure. I would need the url to accept:
{
title: title,
category: category
}

REST API Multiple PUT or DELETE in one time

Greeting everyone, I have a datatable in my html page that I populated using REST API. I can create new row and also update or delete by selecting a row and clicking the edit or delete button.
But currently I am unable to delete update or delete multiple row at once due to url error,
e.g : PUT http://127.0.0.1:8000/dashboard/content_detail/5,7,9/ 404 (Not Found)
how can I split this this into several separate url with respective id when I update or delete.
e.g :
/dashboard/content_detail/5
/dashboard/content_detail/7
/dashboard/content_detail/9
Below is my code, any help is much appreciated thank you.
idSrc: 'id',
ajax: {
create: {
type: 'POST',
url: content_path,
data: function (content_data) {
var create_data = {};
$.each(content_data.data, function (id, value) {
create_data['name'] = value['name'];
create_data['description'] = value['description'];
create_data['category'] = value['category'];
});
return create_data;
},
success: function () {
content_table.api().ajax.reload();
}
},
edit: {
type: 'PUT',
url: '/dashboard/content_detail/_id_/',
data: function (content_data) {
var updated_data = {};
$.each(content_data.data, function (id, value) {
updated_data['description'] = value['description'];
updated_data['category'] = value['category'];
updated_data['name'] = value['name'];
});
return updated_data;
},
success: function () {
content_table.api().ajax.reload();
}
},
remove: {
type: 'DELETE',
url: '/dashboard/content_detail/_id_/',
data: function (content_data) {
var deleted_data = {};
$.each(content_data.data, function (id, value) {
deleted_data['id'] = id;
});
return deleted_data;
},
success: function () {
content_table.api().ajax.reload();
}
}
},
If you're going to allow the update of a large number of items at once, then PATCH might be your friend:
Looking at the RFC 6902 (which defines the Patch standard), from the client's perspective the API could be called like
PATCH /authors/{authorId}/book
[
{ "op": "replace", "path": "/dashboard/content_detail/5", "value": "test"},
{ "op": "remove", "path": "/dashboard/content_detail", "value": [ "7", "9" ]}
]
From a design perspective you don't want several ids in your url.
I would prefer single calls for each change, thinking in resources you only manipulate one at a time.
In case this is a perfomance issue, I recommend a special url marked with action or something simliar, to make clear this ist not REST.
In HTTP it is not required for information to only exist on a single resource. It is possible to have multiple resources that represent the same underlying data.
It's therefore not out of the question to create a resource that 'represents' a set of other resources that you wish to DELETE or PUT to.
I do agree that it might not be the most desirable. I think we tend to prefer having information only exist in a single part of tree, and I think we like to avoid situations where updating a resource effects a secondary resource's state. However, if you are looking for a strictly RESTful solution to solve this problem, I think it's the right way.
Therefore a url design such as:
/dashboard/content_detail/5,7,9/
Is not necessarily non-RESTful or goes against the HTTP protocol. The fact that you're getting a 404 on that URL currently has to do with your application framework, not the protocol (HTTP) or architecture (REST) of your API.
However, for cases such as these I feel I would personally be inclined to sometimes create a separate POST endpoint that, acting outside of REST like an RPC endpoint. Specifically for these types of batch requests.

Should I include URLs or Ids of resources in REST API response?

I am designing a REST API. There's an entity Organization which may have a parent organization and multiple child organizations.
Let's say a user does request GET /organizations/1234.
What should I respond with?
I can use URLs to these other organizations.
{
"data": {
"name": "Microsoft",
"parent_organization": "http://api.myapi.asdfghj/organizations/1220",
"child_organizations": [
"http://api.myapi.asdfghj/organizations/1236",
"http://api.myapi.asdfghj/organizations/1214"
]
}
}
or I can use their ids
{
"data": {
"name": "Microsoft",
"parent_organization": 1220,
"child_organizations": [
1236,
1214
]
}
}
Which one is better?
If it's the one with full URLs, how do I do document that in swagger? Do I just set that as a string, something like the following?
definitions:
Organization:
type: object
properties:
data:
type: object
properties:
name:
type: string
parent_organization:
type: string
format: url
child_organizations:
type: array
items:
type: string
format: url
What about POST /organizations for creating a new user? Should the user specify parent and children as urls too?
I suggest you use urls rather than some ids. The advantage of having actual urls is that you can change them dynamically without worrying about the clients who depend on some base urls and then have to compute the actual urls from ids, etc.
For documentation purpose you can treat urls as strings and explain them like other params.

Meteor: Difference between request.query and request.body in restFul API

while using restFul Api in meteor, we return two request methods request.body and request.query for get and post methods:
Utility = {
getRequestContents: function(request) {
switch (request.method) {
case "GET":
return request.query;
case "POST":
return request.body;
}
},
But I am not getting the difference between the two.
The terminology comes from HTTP. HTTP GET requests are made to get or query something, that is why they don't have a "body", but a "query" string. POST has a body (the thing that should be POSTed), but it does not (usually) have a query.
Normally the two have different purposes and it is actually a questionable idea to mix them into a generic "content" term.

Non-standard REST API in Backbone js

I am building Backbone.js models backed by a legacy REST API. When I create a new resource on the server, rather than return the JSON of the newly created resource, it returns plain text of the id of the newly created resource, along with a relative URL in the Location header where the resource can be gotten.
For example, I POST:
{ "firstName": "Joe", "lastName": "Blow" }
to http://fakeserver.com/people and (on success) the body of the plain/text response might be: "1234". The status of the response is 201 and the Location header would be http://fakeserver.com/people/1234. If I GET from that Location URL, it will have
{ "id": 1234, "firstName": "Joe", "lastName": "Blow" }
How would I override the sync function on my model to accommodate this convention instead of the default Backbone.js conventions?
To clarify, there is no Backbone.js version of this yet - I am trying to create a new one. The old jQuery-only way of doing it was:
$.ajax({
type: 'POST',
url: submitURL,
data: $.toJSON(person),
success: function(data, status, request) {
showSuccessMessage();
closeDialog();
},
dataType: 'json',
contentType: 'application/json'
});
The details of the showSuccessMessage and closeDialog are unimportant - just to demonstrate that basically we are just ignoring the content of the response and throwing the original object away.
Handle the simple text response with parse:
http://backbonejs.org/#Model-parse
parse : function(response, options){
console.log(response, options);
var data = this.toJSON(): //current model to hash
data.id = response; <- assuming that response is a simple text plain id
return data;
}
You could also use sync to overwrite something in the ajax call(that is not supported in the options hash.
http://backbonejs.org/#Model-sync