Restlet using Get and Post Methods - restlet

Hiiii,
I am developing a small app using Restlet 2.0 API..
I want just to know how to create a URI which accepts more than one parameter for insert query.
Ex:
router.attach("/{patient}/insertpatient", insertpatient);
I want to insert all the info about the patient using POST.
Or Search by ID and address for instance using GET.
thanks,

For the "insert patient" operation, I'd suggest something like a POST to /patients (if the server generates the patient ID) or a PUT to /patients/{patient-id} (if the client generates the patient ID). Either way, the body of the message would contain all of the input data needed to create a new patient entity. Two simple options for serializing the data would be as a URL-encoded form or as JSON.
Lookup by by ID could be a simple as a GET on /patients/{patient-id}. Lookup by address could also be a GET, possibly using a URL-encoded query parameter. For example, you could fetch the patient at address "123 Main Street, apt 4, Anytown, USA, 98765" with a GET on /patients?addr=%20Main%20Street%2C%20apt%204%2C%20Anytown%2C%20USA%2C%2098765

Related

api platform - Create post requests with nested resources

I'm new to symfony and the api platform and I want to develop an api with specific routes.
I'm looking to do is create a post query with nested resources to add relationships between tables.
example: I have 3 tables (users, periods, articles). I need to create a post request to add a new post with the following structure:
URL: api/:userid/:period/item
:userID = user ID
:period = Period name
name = element name
This request must create a new article in my "articles" table by adding the identifier, the name of the period and the name of the article entered as a parameter.
So my question is how do I pass multiple parameters in my path and save them in the database using the api platform?
Thanks in advance !
You can use custom routes with API platform, which allow you to create a route that correspond to a custom query => but you need to have these data before setting them in your Api platform path.
First of all, I would use the query builder to create the query you need get the data you need, then you can use your method directly in your entity (more here https://api-platform.com/docs/core/controllers/).
You can set the route you want inside of the path of the route and set the different arguments you need like this:
'path' => '/books/{id}/publication'
here id is your argument coming from your repository function.

API convention for parent -> child element calls

We are trying to figure out if there is a generally accepted way of providing an API parent -> child resource. Say we have a Person entity and each Person has 0 or more addresses represented by the Address entity.
In terms of basic API we'd have:
POST: /api/v1/person
GET: /api/v1/person/{id}
PUT: /api/v1/person/{id}
DELETE: /api/v1/person/{id}
Then we have 2 ways to retrieve the addresses for a person:
/api/v1/person/{id}/addresses
/api/v1/addresses/{personId}
We feel it's more natural to pick the former option /person/{id}/addresses for GET but at the same time if we wanna retrieve an address by its id it should be /api/v1/address/{id}.
The question is, is there a convention in dealing with POST, PUT and DELETE calls? To me it makes sense that these should be called to the address service at /api/v1/address OR /api/v1/address/{id} but at the same time I can see why someone would POST to `/api/v1/person/{id}/address' instead of passing the person id in the request body.
So yeah, can you guys point us in the right direction here - is there a written or unwritten rule in API design when it comes to parent -> child relations?
Thanks in advance!
Can an address exist without a person? If the answer is yes, then an address should be a resources of its own.
/api/v1/addresses: the collection of all addresses
/api/v1/addresses/{addressId}: a single address
/api/v1/addresses?person={personId}: all addresses for a person
I'd not use /api/v1/addresses/{personId} because it is not immediately obvious that personId is the ID of a person, not of an addresse.
But at the same time, /api/v1/person/{id}/addresses should be available to navigate from a person to all his addresses.
If an address can not exist without a person, only use /api/v1/person/{id}/addresses.

Designing a rest url - filter with multiple params over entities (not last entity)

Let's say I have the following entities in my libraries app - Library Room, shelf, Book.
Where Room has N shelves, and shelves have N Books.
Now the following url brings me a list of books whose
library is 3, room no. is 5 and shelf no. is 43.
.../library/3/room/5/shelf/43/books
Assuming shelf 43 is unique per room only
(There is shelf 43 also in other rooms)
and Rooms are not unique (There's a few room no. 5 ) in the library.
Here is my questions:
I want to filter with more fields on the entities, here is what i want to do
(representation not in rest):
.../library/id=3&type=3/room/decade=21&topic=horror/shelf/location=east&/books
This is not rest.
How do I represent it in rest?
Notes:
I don't want to do this way
.../books&param1=X&param2=X&param3=X&param4=X
because not all params are related to books.
Couple of things that you need to look into while designing your apis.
1) are type, decade, topic etc required fields? if so, I will probably make them a part of the path itself, such as:
../libraries/{libraryId}/type/{typeId}/rooms/{roomId}/decades/{decadeId}/topics/{topicName}/shelves/{shelfId}/locations/{shelfLocation}/books
Here I am assuming that each library can have rooms which have unique room ids per library, each room can have shelves which has unique ids/locations per room (and so on and so forth). Yes, the url is pretty long, but that's kind of expected
2) if these fields are not required, you could use a different approach which is a bit less verbose but a bit more confusing for client developers who have never used such approach here. Here's a straight up example Restful Java with JAX-RS by Bill Burke
#Path("{first}-{last}")
#GET
#Produces("application/xml")
public StreamingOutput getCustomer(#PathParam("first") String firstName,
#PathParam("last") String lastName) {
...
}
Here, we have the URI path parameters {first} and {last}. If our HTTP request is
GET /customers/bill-burke, bill will be injected into the firstName parameter and
burke will be injected into the lastName parameter.
If we follow this somewhat academic approach (I have not seen this implemented on many platforms. Most platforms normally go with approach # 1, a more verbose but clear approach), your URL would look somewhat like this:
../libraries/{libraryId}-{typeId}/rooms/{roomId}-{decadeId}-{topicName}/shelves/{shelfId}-{shelfLocation}/books
This way, if the client developer doesn't pass in the non-required fields, you can handle it at the business logic level and assign these variables a default value, for example:
../libraries/3-/rooms/2-1-horror/shelves/1-/books
With this url, libraryId = 3, typeId = null (thus can be defaulted to it's default value) and so on and so forth. Remember that if libraryId is required field, then you might want to actually make it a part of the pathparam itself
Hope this helps!

Should we always validate resource id in url and body in HTTP PUT request?

Suppose I am updating a employee record
url - /api/employees/10
body -
{
id : 10,
name : xyz
}
Should I validate for the employee id in url is same as in response? Because one employee can hit the url himself but update the data of another employee by sending another value in the PUT body.
If you have to validate, it's likely that you want to use POST. A POST is not idempotent and you are supposed to manage the change.
PUT is idempotent, and it just creates a resource. It implies that you don't actually care what id 10 is and whether it is a new id or an existing id. You just replace id 10 with the resource you supply. You only use PUT when you know what the uri should be.
Yes, if the representation of the object in the body contains its own key, you should validate that it matches the key from the URL. It's an error for the client to try to PUT an object at /api/employees/10 that isn't a valid value for employee #10's record, so you should check for that and report it as an error just as you would check that the object has correct syntax.
I believe that the best error code to return in this case is 422 Unprocessable Entity, but I might be wrong about that.
Another thing you can do instead is don't include the key at all in the body. However I find that keeping the key in makes sense for consistency with the way the same type of object is represented in other parts of the API (possibly embedded inside other objects). This is especially true when using XML (although it looks like you are using JSON here).

RESTful API - How do I return different results for the same resource?

Question
How do I return different results for the same resource?
Details
I have been searching for some time now about the proper way to build a RESTful API. Tons of great information out there. Now I am actually trying to apply this to my website and have run into a few snags. I found a few suggestions that said to base the resources on your database as a starting point, considering your database should be structured decently. Here is my scenario:
My Site:
Here is a little information about my website and the purpose of the API
We are creating a site that allows people to play games. The API is supposed to allow other developers to build their own games and use our backend to collect user information and store it.
Scenario 1:
We have a players database that stores all player data. A developer needs to select this data based on either a user_id (person who owns the player data) or a game_id (the game that collected the data).
Resource
http://site.com/api/players
Issue:
If the developer calls my resource using GET they will receive a list of players. Since there are multiple developers using this system they must specify some ID by which to select all the players. This is where I find a problem. I want the developer to be able to specify two kinds of ID's. They can select all players by user_id or by game_id.
How do you handle this?
Do I need two separate resources?
Lets say you have a controller name 'Players', then you'll have 2 methods:
function user_get(){
//get id from request and do something
}
function game_get(){
//get id from request and do something
}
now the url will look like: http://site.com/api/players/user/333, http://site.com/api/players/game/333
player is the controller.
user/game are the action
If you use phil sturgeon's framework, you'll do that but the url will look like:
http://site.com/api/players/user/id/333, http://site.com/api/players/game/id/333
and then you get the id using : $this->get('id');
You can limit the results by specifying querystring parameters, i.e:
http://site.com/api/players?id=123
http://site.com/api/players?name=Paolo
use phil's REST Server library: https://github.com/philsturgeon/codeigniter-restserver
I use this library in a product environment using oauth, and api key generation. You would create a api controller, and define methods for each of the requests you want. In my case i created an entirely seperate codeigniter instance and just wrote my models as i needed them.
You can also use this REST library to insert data, its all in his documentation..
Here is a video Phil threw together on the basics back in 2011..
http://philsturgeon.co.uk/blog/2011/03/video-set-up-a-rest-api-with-codeigniter
It should go noted, that RESTful URLs mean using plural/singular wording e.g; player = singular, players = all or more than one, games|game etc..
this will allow you to do things like this in your controller
//users method_get is the http req type.. you could use post, or put as well.
public function players_get(){
//query db for players, pass back data
}
Your API Request URL would be something like:
http://api.example.com/players/format/[csv|json|xml|html|php]
this would return a json object of all the users based on your query in your model.
OR
public function player_get($id = false, $game = false){
//if $game_id isset, search by game_id
//query db for a specific player, pass back data
}
Your API Request URL would be something like:
http://api.example.com/player/game/1/format/[csv|json|xml|html|php]
OR
public function playerGames_get($id){
//query db for a specific players games based on $userid
}
Your API Request URL would be something like:
http://api.example.com/playerGames/1/format/[csv|json|xml|html|php]