In a RESTful application, how do we differentiate between an "action" and an HTTP verb (GET, POST, PUT, DELETE)? - api

In a RESTful application, how do we differentiate between an "action" and an HTTP verb (GET, POST, PUT, DELETE)?
For example, as I understand it, a GET request to the resource /products should return a list of all products. A POST request to /products should create a new product. How, then, does the user request the original form which is used to create the product? My initial response would have been a GET request to the same URI, but as mentioned above, that should return a list of all products - not a blank form for creating a product.
In most frameworks I've researched, this problem is solved by making the "action" part of the URI. For example, a POST request to /products/create would create a new product, whereas a GET request to /products/create would give the blank form for creating a product. To get a list of all products would be a GET request to either /products or /products/get, /products/read, etc. depending on the framework in question. This approach resolves the ambiguity above, but it conflicts with what I've read about traditional REST design.

IMHO, the best option is to make the request method a part of controller's action.
Lets say you are accessing http://who.cares/product/42 or http://who.cares/product/42/specification . This query to webserver would translate as Product controller. The actions name should be created by combining request method and command:
DELETE "http://who.cares/product/42"
controller: "Product",
action: "deleteProduct()"
GET "http://who.cares/product/42/details"
controller: "Product",
action: "getDetails()"
POST "http://who.cares/product/42/review"
controller: "Product",
action: "postReview()"
GET "http://who.cares/products/
controller: "Products",
action: "getProducts()"
POST "http://who.cares/products/
controller: "Products",
action: "postProducts()"

here is example like it Rails does
REST request path | action name | Description
---------------------|-------------------|-------------
GET /profile/new | new | Render a form for creating the profile
POST /profile | create | Create a the profile from the received data
GET /profile | show | Render a the profile
GET /profile/edit | edit | Render a form for editing the profile
PUT /profile | update | Update the profile based on the received data
DELETE /profile | destroy | Destroy the profile
I don't see any conflict , Idea is that
urls are human readable and you can introduce new URIs to show different representations of the same resource. (like profile/1/edit and profile/1)
/profile/new - address of profile that is empty (like profile/1, profile/2 .. etc in show method)
But if you want you can suggest that profile/1/edit is some kind of different - nested resource of profile/1/ resource, but I like to thing that it's just other representation of profile/1/ resource =)
Also is good idea to use plural and singular URI when you working with many resources or with one, example
/profile/1.html - gives you 1 resource
/profiles.html - gives you list of profiles

Related

Acumatica API. Fetch products

What endpoints are used to fetch from Acumatica product data. Theoretically it should be /entity/Default/18.200.001/StockItem, however there no info about assigned categories, attributes, complex product information
The Default endpoint provides the ability to get the following information from the Stock Items page
The main problem with this page is that Acumatica doesn't allow to request more than one array type detail at a time and as you can see on the screenshot almost all details are arrays. So you will have to request each one separately.
For example, you can get items with their Categories by sending the following GET request:
entity/Default/18.200.001/StockItem?$expand=Categories
but at the same time, it is a little tricky to get Attributes, because you will need to send a PUT request with InventoryID for getting Attributes of the Item:
Request: entity/Default/18.200.001/StockItem?$expand=Attributes
Body:
{
"InventoryID" : {
"value" : "AACOMPUT01"
}
}
If you need to be able to get other information from this page you will need to extend endpoint, entity and add additional Views and Fields.

Laravel Route apiResource (difference between apiResource and resource in route)

I'm using apiResource in Route which is using (index, create, show, update, destroy) methods in exampleController. When I would like to use show method the route wont work. what shall I do? I think it is because of {fruits} but I do not how solve it?
Route::apiResource('/fruit/{fruits}/apples', 'exampleController');
My route in browser is:
localhost:8000/api/fruits/testFruitSlug/apples/testAppleSlug
difference between apiResource and resource in route: Route::apiResource() only creates routes for index, store, show, update and destroy while Route::resource() also adds a create and edit route which don't make sense in an API context.
Already peoples added answers, I am just adding the route differences as visually :
Normal Resource controller
Route::resource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
Api Resource controller
Route::apiResource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
POST /users store users.store
GET /users/{user} show users.show
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
To quickly generate an API resource controller that does not include the create or edit methods, use the --api switch when executing the make:controller command:
php artisan make:controller API/PhotoController --api
Try using the command line to generate your controller. It will save you stress. You can then do this in your route
Route::apiResource('photos', 'PhotoController');
I solved my question in below way:
public function show(Fruits $fruits, Apples $apples){
}
I found that I should give all variables in my function however I did not use all of them.

laravel 4 pattern filter using a wildcard

I started using Laravel 3 last week, and then found the new 4 release and I'm trying to convert now.
I have a dozen+ routes that I want to deliver to a specific controller method. i.e., "/api/v1/owners/3/dogs/1 or /api/v1/owners/3" to run "myresourcecontroller#processRequest"
In Laravel 3 I was able to use this: (note * wildcard)
Route::any('api/v1/owners*', 'owners#processRequest'); // Process tags resource endpoints
I found this example from the documentation but it gives me an error. I get a NotFoundHttpException.
//[Pattern Based Filters](http://laravel.com/docs/routing#route-filters)
Route::filter('admin', function()
{
//
});
Route::when('admin/*', 'admin');
Not sure what I'm doing wrong? Is there another way to do this?
I don't want to use the Laravel 4 restful controllers, cause they don't seem to conform to complete restful design. i.e., no verbs in the url.
I have all of my processing written, I just need to be able to route to it.
I need to be able to create new records by POST /api/v1/owners or /api/v1/owners/3/dogs
I cannot use /api/v1/owners/create.
I'm trying to avoid having to write a route for every endpoint, i.e.,
Route::any('api/v1/owners/{owner_id}', 'owners#processRequest');
Route::any('api/v1/owners/{owner_id}/dogs/{dog_id}', 'owners#processRequest');
Thank you for any help
You should make use of resourceful controllers as they're a great asset when building an API. The endpoints you described can be achieved using resource controllers and nested resource controllers.
Route::resource('owners', 'OwnersController');
Route::resource('owners.dogs', 'OwnersDogsController');
Would allow you to create an owner with POST localhost/owners and create a dog on an owner with POST localhost/owners/3/dogs.
You can then wrap these routes in a route group to get the api/v1 prefix.
Route::group(['prefix' => 'api/v1'], function()
{
Route::resource('owners', 'OwnersController');
Route::resource('owners.dogs', 'OwnersDogsController');
});
Haven't used Laravel myself, but try any('api/v1/owners/*', (note slash before asterisk) as in the example.

How about using URI path variables for an HTTP POST?

I've searched a lot but I couldn't find the proper answer to my question regarding my conditions.
I'm building a REST API, and the case, which seems a border line case to me, is the following:
-I'm dealing with two entities, Users and Roles. An User can have multiple roles assigned.
-To assign a Role to a User, the Role must be already in the DataBase.
-To assign a Role to a User, the only thing needed is the 'code' of the role, that is a short string.
-The uri path template used now is:
--Users: localhost:8080/api/users
--Given User: localhost:8080/api/users/{userId}
--Roles of a given User: localhost:8080/api/users/{userId}/roles
Now, to 'link' a given User with a given Role, two options come to my mind.
-The first is the one that sounds as best practice in any scenario, sending the post data in the body, perhaps as a JSON.
-The other one, sending it through the uri and with an empty body. For example, to link User with id U001 with role R001, one would have to post to the following uri sending no data in the body: localhost:8080/api/users/U001/roles/R001
The thing is that I don't mind using the first option, and it seems to be the best and most correct one, but in this particular case, I'm not sure wether it is better to send an almost empty body (because it only holds the role id, a very short string) posting it to 'localhost:8080/api/users/U001/roles' or skipping the body and just sending the role id through the uri as a path parameter like localhost:8080/api/users/U001/roles/R001
Thank you all in advance for your help.
There is nothing wrong with putting role in the URI. Your intuition was on the right track. I'd do it this way.
PUT: locahost:8080/api/users/{userid}/role/{roleId}
And here's why.
FIRST: The PUT verb is Idempotent. In other words (taken straight from the spec)
... the side-effects of N > 0 identical requests is the same as for a single request.
Which is what I'd assume you want in this regard. You don't want multiple records in your state storage for each instance of user & role. A user should feel at ease making the same PUT request without adversely effecting (adding duplicate records) the system.
When doing the same thing with a POST I'd expect to have a new record created for every request.
SECOND: The PUT verb is supposed to identify a specific resource. (taken straight from the spec)
... PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires that the request be applied to a different URI,
it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.
What if role R102 becomes obsolete and R104 is preferred? Return a 301 (Moved Permanently) with a HEADER (Location : localhost:8080/api/users/{userid}/role/R104).
FINALLY: When everything works well. Return a 201 (Created) when created and a 200 (No Content) on every subsequent request to the same URI. If they provide a Role that is not in the system return a 501 (Not Implemented).
Hmm - in this case - a POST with a 302 may be a bit messy.
Why not a very simple 'PUT'/'DELETE' with indeed the URIs suggested ?
With simple; 20X meaning succeeded, possibly some 30X to indicate it was already there - and anything else a fail ?

Multiple Resource Routing In Rails

I have two unrelated models, say Person and Building. When the app receives a url like www.mysite.com/JohnDoe/EmpireState I would like to show properties of the Person with the name johnDoe, and the same for the building with the name EmpireState.
I'm confused as to the routing part specifically. I'm unsure if I need to create a pages controller that can return the objects from the database. How should I go about doing this?
Am hoping for something like below?
match ':user_name/:building_name', :controller => pages
If those two are not related, you shouldn't do it that way. If they ARE related, we call that nested resources.
Example:
resources :projecs do
resources :tasks
end
Sample URL: "/projects/12/tasks/1281"
Edit:
If they are NOT related (taken from my comment):
In your BuildingsController you can fetch the parent informations too. If you use the match route in your question, you'll have params[:user_name] AND params[:building_name] available and can fetch anything you want with them...
Building.find_by_name(params[:building_name]) # return all Buildings based on URL param