How to call DELETE request method in Yesod? - rest

In the book on routing ( http://www.yesodweb.com/book/routing-and-handlers ) there's a paragraph:
A separate handler for each request method will be the same, plus a
list of request methods. The request methods must be ALL CAPITAL
LETTERS. For example, /person/#String PersonR GET POST DELETE. In this
case, you would need to define the three handler functions getPersonR,
postPersonR and deletePersonR.
Performing something like
curl -X DELETE localhost:3000/person/1
works, so the server is capable of handling these requests.
Several examples (like https://github.com/snoyberg/haskellers/blob/master/routes and http://pbrisbin.com/posts/posts_database ) use GET or POST requests (in stead of DELETE) to handle this.
Is there a straight-forward way to call the DELETE request from Yesod-code? So that the route handler deletePersonR gets called?

Unlike the GET and POST methods, which can be accessed using plain links or forms on a page, DELETE methods require using JavaScript, and are not supported by all browsers. This is why POST is often used instead. To invoke a DELETE method from JavaScript, the easiest way is to use a JavaScript framework such as jQuery:
$.ajax({
url: "/person/1",
type: "DELETE",
success: function(html){
alert("Ok, deleted");
}
});

Related

Restangular - how to cancel/implement my own request

I found a few examples of using fullRequestInterceptor and httpConfig.timeout to allow canceling requests in restangular.
example 1 | example 2
this is how I'm adding the interceptor:
app.run(function (Restangular, $q) {
Restangular.addFullRequestInterceptor(function (element, operation, what, url, headers, params, httpConfig) {
I managed to abort the request by putting a resolved promise in timeout (results in an error being logged and the request goes out but is canceled), which is not what I want.
What I'm trying to do - I want to make the AJAX request myself with my own requests and pass the result back to whatever component that used Restangular. Is this possible?
I've been looking a restangular way to solve it, but I should have been looking for an angular way :)
Overriding dependency at runtime in AngularJS
Looks like you can extend $http before it ever gets to Restangular. I haven't tried it yet, but it looks like it would fit my needs 100%.
I'm using requestInterceptor a lot, but only to change parameters and headers of my request.
Basically addFullRequestInterceptor is helping you making change on your request before sending it. So why not changing the url you want to call ?
There is the httpConfig object that you can modify and return, and if it's close to the config of $http (and I bet it is) you can change the url and even method, and so change the original request to another one, entirely knew.
After that you don't need timeout only returning an httpConfig customise to your need.
RestangularConfigurer.addFullRequestInterceptor(function (element, operation, route, url, headers, params, httpConfig) {
httpConfig.url = "http://google.com";
httpConfig.method = "GET";
httpConfig.params = "";
return {
httpConfig: httpConfig
};
});
It will be pass on and your service or controller won't know that something change, that's the principle of interceptor, it allow you to change stuff and returning to be use by the next process a bit like a middleware. And so it will be transparent to the one making the call but the call will be made to what you want.

RESTful API and calling remote methods (RPC)

So i'm doing a bit of research on RESTful APIs and i'm trying to get some clarification on how to call methods on resources (essentially RPC).
So if I wanted to call a method (cancel) on a resource (an order), from what I can see so far I can do it one of two ways:
POST /api/1/orders/123/cancel { }
or
POST /api/1/orders/123 { 'action' : 'cancel' }
Hopefully that makes sense?
Personally I like the former more, you can just type out the url and call the method, the later requires a little extra work with POST params. Any params required by the method would go inside the POST?
I guess a 3rd is by doing:
PATCH /api/1/orders/123 { 'state' : 'cancelled' }
But I'm trying to keep an order's (object's) fields and methods separate.
The best option is number four, PATCH the order setting the status field of the resource to 'cancel'
PATCH /api/1/orders/123 { 'status' : 'cancel' }
or maybe
PUT /api/1/orders/123/status cancel
The latter has the advantage of being very easy to link to and use with a html form.

CakePHP: Distinguish between regular http and REST calls

I want the same Controller routines to serve both regular web-based page loads as well as REST calls. I have REST handling set-up in my routes.php:
// Setup REST Handling
Router::mapResources( '<ControllerName>' );
Router::parseExtensions();
Let's take for example, the add() method - how do I distinguish inside this method how the call is being made?
To elaborate on the issue:
public function add() {
$status = array();
if( $this->request->is( 'post' ) ) {
// Read POST body
$entityBody = file_get_contents( 'php://input' );
}
}
As you can see in the above code, I'm detecting POST requests and will deal with the request accordingly. What I need to figure is whether the post data is coming from a REST call of from a web-form. If the data comes from a web-form, it'll be in the request->data array whereas for a REST call, it'll be in XML form.
I'll deal with the data accordingly and dish out an appropriate response.
Thanks.
Use the CakeRequest object, see the documentation, works the same as with post.
$this->request->is('put');
is('get') Check to see if the current request is a GET.
is('put') Check to see if the current request is a PUT.
is('post') Check to see if the current request is a POST.
is('delete') Check to see if the current request is a DELETE.

How to implement a POST-REDIRECT-GET in Play Framework

Let's say I have two controller methods: Users.preInsert and Users.insert. The preInsert method is the one used to display the user entry form (GET), while the insert method is responsible for the actual insertion (POST) or calling the 'insert' service.
This is how the routes looks like:
GET /users/add controllers.Users.preInsert(...)
POST /users/add controllers.Users.insert(...)
So how do I redirect a request (POST to GET) without losing the parameters like error messages returned from the insert service and the values inputed by the client so that they can be accessed and displayed in the entry form. The parameters may involve some complex objects. I have implemented it using the Caching API but I would like to know if there are any better ways of doing it.
That's the exact purpose of the Form objects (http://www.playframework.com/documentation/2.1.1/ScalaForms).
And I think there is a an error in your routes, it could look like:
GET /users/add controllers.Users.preInsert(...)
POST /users/add controllers.Users.insert(...)
You should definitively take a look at the form sample.
You don't need to redirect it back to the preInsert action, instead at the beginning of the insert check if form has errors and it it has display your view containing form (the same which you used in preInsert). It's described in the doc mentioned by nico_ekito in section Handling binding failure

GET and POST request in one action. Playframework. Scala

Action create shows form:
def create = Action {
Ok(html.post.create(postForm))
}
How can i modify this action so that for GET request it would give out form and for the POST request it would process user input data, as if it were a separate action:
def newPost = Action { implicit request =>
postForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Posts.all(), errors)),
label => {
Posts.create(label)
Redirect(routes.Application.posts)
}
)
}
Wthat i mean is i want to combine this two actions.
UPDATE1: I want a single Action that serves GET and POST requests
It is recommended not to merge both actions, but modify routes to get the behavior you are expecting. For instance:
GET /create controllers.Posts.create
POST /create controllers.Posts.newPost
In case you have several kind of resources (post and comments, for instance), just add
a prefix to the path to disambiguate:
GET /post/create controllers.Posts.create
POST /post/create controllers.Posts.newPost
GET /comment/create controllers.Comments.create
POST /comment/create controllers.Comments.newComment
I tried once to accomplish similar thing, but I realized that I wasn't using framework like it was meant to be used. Use separate GET and POST methods like #paradigmatic showed and in cases like you specified "If we take adding comments to another action, we wouldn't be able to get infomation on post and comments in case an error occured (avoding copy-paste code)." - just render the page at the end of controller method with the view you like? and for errors etc. you can always use flash scope too? http://www.playframework.org/documentation/2.0.2/ScalaSessionFlash you could also render this form page with two or more beans and send them to controller side to catch related error messages and data.?