We have a CORS REST API. It's clean. It works. It's almost perfect. But...
I'm trying to implement an endpoint with request specific parameters. This endpoint should accept POST, PUT, LINK and DELETE requests. And I'm not sure how to implement these parameters.
An example:
A user wants to DELETE a model. There are two scenario's: one where the model is deleted and nothing else happens, and one where the model is deleted + a notification email is sent out.
Initially I implemented this parameter in a header called "X-NOTIFY-OWNER". This worked since it could be added to any of the 4 actions. But now we'd like to get rid of that header, since it's too specific to this single endpoint.
What whould be the best place to put this parameter? A query parameter sounds cleanest (since DELETE and LINK technically don't need a body), but query parameters should be used to filter content. A parameter in the request body would work too, and seems to be the prefered method; but it means sending a body with the DELETE and LINK actions...
Any thoughts on best practice in this case?
I would stick to a query string, DELETE is supposed to ignore the body and only read the URL so it makes sense to use a query string here.
You should use an URL parameter. As you stated, they should be used to filter output and an e-mail can be considered to be output.
I would recommend setting up a new endpoint for the cleanest solution.
example.com/endpoint
example.com/endpointAndNotify
You could either:
Setup the notify endpoint to extend the base endpoint and then add the notification logic to the notify action.
Abstract out the shared logic from both actions, update each action to extend the base class and then add the specific notification logic to the notify action
This way both endpoints stay clean and concise and if you define a standard for this endpoint, any other endpoints that need notification logic can use the same standard.
Related
I have a model Project which have many Orders. On the page of the project, I have a list of its orders and create/update buttons.
Now I pass project_id in GET params in url. I need watching that each url and redirect have this parameter (in the update and create views/controllers and in the list of orders view/controller).
Is there a better way, to pass parameter through views and controllers?
This doesn't really have anything to do with MVC. In a web context, each HTTP request must be self-contained. All the information your server needs to fulfil the request must be contained within the request. Either within the URL, or within the request body.*
Whenever your server generates a URL somewhere to send back to the client, you need to embed all the information necessary in that URL so a request made to that URL gives your controller all the information it needs to fulfil the request. So, yes, you'll need to pass all the information through to that place in your code. That's pretty much the same whether you use MVC or plain spaghetti PHP files.
The only alternative is for you to reduce the amount of information the controller needs to fulfil the request, e.g. because you can implicitly get one part of information from another, like the project id when given just an order id.
* (I'll forego something like session storage here, since that's stateful across all requests and generally cannot be used for transporting information specific to individual requests.)
I'm working with Laravel 5 API. I have a few methods with similar request parameters
For example to check the licence status or get the settings file you need to provide the ?serial=licence_serial_number parameter.
I need to return 400 error code, when the user didn't provide the serial parameter, and 403 error code, when the user is trying to get information about the licence of another user.
What is the best practice to organise validation and error handling of these kind of requests?
Should I make a middleware to check if the user has provided ?serial?
Or should I make a different Laravel 5 FormRequest class for every method?
Or should I validate it directly in a controller with:
if (..) {return response()->json([..], 400);}
$request->wantJson(), with a request with Header Accept=application/json Will tell Laravel to return json validation error instead of goback with errors
Middleware will probably be the best choice but you could also use the Request method.Inline validation is a bad practice as its ignore the most basic rule of programming - Dont Repeat Yourself.
In case you decide go for the request option you aren't supposed to create the authorize method for each class,instead create 1 parent witch will handle this and the other sub classes will just have the rules method.
It depends on a few things acctualy:
If your always validating the same thing for all requests: Go With a Middleware Solution.
But if some or multiple requests validate different things then I would advise on using the new FormRequest from Laravel.
It handles the validation for your request perfectly, and also allows you the define the error responses per request.
Also a middleground is an option, Let middleware validate the thing that needs to be validated always. And FormRequests to handle the variable validation.
If you have similar FormRequests, consider using inheritance to prevent code duplication like a good SOLID programmer :-)
I'm looking for a suggestion on how to solve an issue I have. I have a filter that executes a DB check on the postFilter function. The filter basically sees if an email should be generated and send out a template set up by the site admin. This function is working as expected.
The issue i have is there are some actions that i need to pass specific data to the email template that is only exposed within the action. My initial idea was to assign the needed values to a system parameter in the form of an array that could be accessed from filter function. The issue with this would be documenting each action that passes extra data.
I just wondering if there is more elegant solution... I would like to keep the system as flexible as possible for the user so if there was a way the user could setup a catch on the preFilter action that could then pass the needed information to postFilter.
Thanks all.
Since the data is generated within the action there's no avoiding the fact that the action has to cooperate somehow in order to make the data available to whatever code ends up sending the email. Therefore I can't see how it would be possible to not have to document that "action X exposes data Y".
A very simple but at the same time quite adequate solution would be to have a pair of setContextData / getContextData functions on the base controller; actions set the data and the postfilter reads it.
can i call a web service like this
and not use put and delete method?
is this a REST web service really?
....
$url = 'webservice.php';
$data = array(
'username' => 'a',
'password' => 'a',
'param1'=> 'param1',
'operation'=> 'delete',
'output'=>'xml'
);
$client = curl_init($url);
curl_setopt($client, CURLOPT_POST,1);
....
...................
//webservice.php
$operation=$_POST['operation'];
$param1=$_POST['param1'];
if ($operation=='delete')
{
$r=mysql("delete from list where id='$param1'");
}
if ($operation=='insert')
{
$r=mysql("insert into list values ('$param1')");
}
.....
One of the major ideas behind REST is to not give operational methods as part of the argument (in this case the 'operation' parameter).
Instead, each resource has its unique URL and the HTTP verbs (GET, POST, PUT or DELETE) are used on those resources.
Your approach is not RESTful.
Example:
Deleting a comment using the flickr API:
GET /services/rest/?method=flickr.photos.comments.deleteComment&comment_id=28
Note how they use a 'method' parameter to determine what operation to perform (like in your example).
The RESTful implementation would accept something like:
DELETE /comment/28
Best practise in this case would be to use POST for creating new resources, DELETE for removing them, GET for retrieving existing and PUT to update existing.
This kind of technique is sometimes called "tunneling" because it buries the true operation in the body of a generic POST operation. In my opinion it's kind of a hack and defeats the purpose of REST but sometimes it's necessary if your web host doesnt allow the required HTTP verbs.
Using standard verbs and understanding the implications they make about your service is an important aspect of REST that should not be overlooked. For example, you should be able to issue a DELETE operation repeatedly on the same resource and that should result in only the first DELETE having any effect (idempotent). With GET it should be assumed that no changes are being made on the server (safe). But hiding the operation inside of a POST obscures that.
This isn't really a RESTful service. You don't need to implement all HTTP verbs to be RESTful, but you shouldn't use POST to DELETE data.
Personally I'd implement DELETE for removing items and only use POST for inserting data.
I'm going to go against the tide here and say it is perfectly fine to create RESTful services without PUT and DELETE. The only key thing that you need to be aware of is what you are giving up in doing so.
1) Intermediary components(e.g. proxies, caches, load balancers) will not know whether you are creating/updating or deleting resources, they will only know if the operation is safe (GET) or unsafe (POST). My question is, do you know of any intermediary components that take advantage of this knowledge?
2) The programmer who is going to be accessing your service will not be able to guess how to DELETE a resource, you are going to have to include a link with a link relation that has some documentation that explains to the programmer that they will need to POST to the link's URI to do a delete. It's a bit more work for the client developer but at least you are being explicit about how to do it.
And before I get downvoted into oblivion, here is a quote from Roy Fielding who says it is ok too!
In any case, there are plenty of
RESTful services that do nothing but
GET and POST. The key is how those
methods are used, not what methods are
used. To give a specific example, what
makes a wiki more or less RESTful is
almost always determined by how it
(ab)uses GET and sessions -- whether
it uses PUT or POST for editing pages
is sugar topping in comparison.
http://code.google.com/p/implementing-rest/wiki/FAQ
Having said all of this, creating a single resource called webservice.php and passing a "operation" parameter is a nasty design smell from the perspective of REST.
The agavi framework uses the PUT request for create and POST for updating information. Usually in REST this is used the other way around (often referring to POST adding information while PUT replacing the whole data record).
If I understand it correctly, the important issue is that PUT must be idempotent, while POST does not have this requirement. Therefore, I wounder how creating a new record can be idempotent (i.e. multiple request do not lead to multiple creations of a record) in particular when usually the ORM uses an id as a primary key and the id of a new record would not be known to the client (since it is autocreated in the database), hence cannot be part of the request. How does agavi maintain the requirement of idempotence in light of this for the PUT request.
Thanks.
PUT can be used both for creation and for updating complete records. POST is usually used for partial updates and related operations as well as for creating a new type of record on the server without specifying a URL for the resource (e.g. POST to /articles/23/comments returns a 201 status and a Location: /articles/23/comments/283136 header). So in your case (with a sequence/autoincrement ID), you would use that approach.
However, HTML (and thus web forms) is different. It only knows GET and POST, not DELETE and PUT. For deletion and updating operations, it overloads the POST method.
That's why Agavi, by default, maps POST to "write" and GET to "read" - it's the most common use case, and "read" and "write" were chosen because they are relatively neutral and also in a way represent the safety aspects of GET vs POST (safety as in "GET can be called without side effects" and blah).
You can change the mapping of verbs for the AgaviWebRequest implementation in factories.xml; refer to the Agavi users mailing list or the IRC channel if you need help with that (or ask away here). A lot of people on the IRC channel are also quite experienced with URL scheme design in case you need more help with making your API pretty.
Instead of thinking of PUT as creating, think of it as "putting". You put a resource at a URI (ie send an entire resource to a URI).
PUT http://example.com/articles/1
If you repeat this (send the same entire resource to the same URI) you get the same result and you haven't changed the resource at that URI, that's what makes it idempotent.
If agavi's implementation of PUT is idempotent then it is implementing PUT correctly. Otherwise it's not.
PUT can be used to create a resource, except that if the resource already exists (or has already been created by a previous PUT) it will just update it. POST should not update resources, however, if this is simple CRUD. Note that the HTTP verbs do not have a defined mapping to certain actions necessarily, since they're useful for a lot more than just CRUD.
Also note that this question has nothing to do with REST - just proper HTTP usage. So please remove the REST tag.
I've had this problem before. This can be solved by changing the factories.xml