new_story GET /story/new(.:format) {:action=>"new", :controller=>"stories"}
edit_story GET /story/edit(.:format) {:action=>"edit", :controller=>"stories"}
story GET /story(.:format) {:action=>"show", :controller=>"stories"}
PUT /story(.:format) {:action=>"update", :controller=>"stories"}
DELETE /story(.:format) {:action=>"destroy", :controller=>"stories"}
POST /story(.:format) {:action=>"create", :controller=>"stories"}
In web development I have done with other technologies, I only ever used GET and POST methods, but with RESTful routes in Rails, by default the PUT and DELETE methods are used for the update and destroy actions. What's the advantage or need for using PUT and DELETE? I assume these methods are just another way of doing POST - but why not just stick with POST?
The advantage is mostly semantic, and can also simplify URLs to an extent. The different HTTP methods map to different actions:
POST => create a new object
DELETE => delete an object
PUT => modify an object
GET => view an object
Then, in theory, you can use the same URL, but interact with it using different methods; the method used to access the resource defines the actual type of operation.
In practice, though, most browsers only support HTTP GET and POST. Rails uses some "trickery" in HTML forms to act as though a PUT or DELETE request was sent, even though Rails is still using GET or POST for these methods. (This explains why you might not have used DELETE or PUT on other platforms.)
I just wanted to add something to the accepted answer because his definition of the http verbs are incorrect. They all have a spec which "should" be followed and you can create/update/delete with multiple http verbs based on the specs.
I am going to highlight some of the important bits in the RFC 2616 by W3
I'm going to start with PUT because in my opinion it has the most confusion surrounding it.
PUT is used for both create/update PUT updates by completely replacing the resource on the server with the resource sent in the request
For example
You make this call to my api
PUT /api/person
{
Name: John,
email: jdoe#hra.com
}
my Server has this resource living on the server
{
Name: Jane,
email: jdoe#hra.com
}
Now my existing resource is completely replaced by what you sent over and this is what I have on my server.
{
Name: John,
email: jdoe#hra.com
}
So if you PUT and only send an email in the body
PUT /api/person
{
email: jdoe#hra.com
}
My Server will completely replace the entity
{
Name: Jane,
email: jdoe#hra.com
}
With
{
email: jdoe#hra.com
}
And Name will be gone. Partial updates are for PATCH but I use POST for that anyway.
One of the main reasons why we create/update with put is because it is idempotent.
It's just a fancy term and the basic definition of it is multiple identical requests are the same for a single request.
Example
Suppose I PUT a file to api/file if the origin server does not find that file it will create one. If it does find a file it will completely replace the old file with the one I sent over. This ensures that one file is ever created and updated. If no file exists and you call PUT 5 times, the first time it creates a file then the other 4 times it replaces the file with what you send over. If you call a POST 5 times to create it will create 5 files.
You PUT to that exact URI. If you don't you have to send a 301 (Moved Permanently) to the user and allow then make a choice whether or not to redirect the request. Most times the server you PUT to usually hosts the resource and takes care of updating it
Those are the major points in when to use PUT
As far as POST is concerned
You can also create/update and then some...
As I mentioned above there are a few key differences.
Post is more General. In what ways? some other examples include a gateway to other protocols, it could take the response and send it to some data handler out in the middle of yonder, or it can extend some sort of functionality.
Post doesn't have the restriction of "To the exact URI or notifiy" for examplePOST can append a resource to an existing collection and decide where it's stored.
Now what about Delete Why don't I just POST?
When you DELETE, the server SHOULD NOT respond with success unless you delete the resource or move it to an inaccessible location at the time the response is sent.
Why is that important? What if you call DELETE but the resource has to go through "APPROVAL" before being deleted? If the delete can be rejected you can't send a successful error code and if you do follow the basic specs on this it's confusing to the caller. Just an example I'm sure you can think of many others.
I just highlighted some of the major points on when to use the common Http verbs
Here's the "methods" section of the HTTP 1.1 spec; it defines lots of methods, and they all have different benefits and tradeoffs. POST is the most flexible, but the tradeoffs are numerous: it's not cacheable (so the rest of the internet can't help you scale), it isn't safe or idempotent so the client can't just resend it gets an error, and it is no longer clear exactly what you're trying to accomplish (because it's so flexible). I'm sure there are others but that ought to be sufficient. Given all that, if the HTTP spec defines a method that does exactly what you want your request to do, there's no reason to send a POST instead.
The reason POST is so common is that, historically at least, web browsers only supported GET and POST. Since GET is defined to be safe and idempotent (even though many applications don't adhere to that), the only safe way to modify data was to send a POST. With the rise of AJAX and non-browser clients, that is no longer true.
BTW, the mapping #mipadi gave is the standard mapping, but it isn't the only valid one. Amazon S3, for instance, uses PUT to create resources. The only reason to use POST is if the client doesn't have sufficient knowledge to create the resource, e.g., you back your resources with a relational database and use artificial surrogate keys.
That'd be kind of like asking why "delete" a file when you could just set its contents to zero bytes and the file system would just treat that as a delete. HTTP has supported verbs other than GET/POST forever but the way SOAP evolved kinda twisted the original meaning of those verbs. REST is a simpler, back to basics approach that uses the verbs as they were intended instead of inventing some new verb concept inside of the payload.
Related
I want to add a new update(new_update) action in my user model of rails which will update a single column in the model. which rest api method I should use in routes file. Should I use put or patch or both.
resources: users do
member do
put 'new_update'
patch 'new_update'
end
If you want to match 100% with the HTTP verb definition.
PUT is supposed to overwrite your targeted resource entirely with the content in the request(all field non present in the request should be set to removed/nullified).
PATCH is supposed to only modify the fields sent in the request.
That being said, most of the time people don't make the difference and use either of them (a lot of people don't even know that there is a PATCH verb) is use PUT with the same behavior as PATCH (since the use case for PUT is quite rare on imo).
In Michael Hartel's Rails Tutorial he suggests creating the following route in oder to logout users:
delete 'logout' => 'sessions#destroy'
This seems to add some unnecessary legwork throughout the application, e.g., requiring links to include method: "delete". The following also works perfectly:
get 'logout' => 'sessions#destroy'
Why is the convention to use the "delete" method and not simply "get"? Is there some hidden advantage?
There are a number of reasons, two of the most vital:
Prevents inclusion of stray "destroy" links (using DELETE in a destroy link means you have to explicitly define it)
Forms part of the "resourceful" structure of HTTP (not as important, but if you want to create "real" web apps, it is vital for using the correct URL structure)
Links
The most important reason - for many - is the inclusion of stray "destroy" links in your views.
To destroy an object (which is what the DELETE method is meant to denote) is a serious endeavour -- you need to make sure the links you include are legitimate & cannot be confused.
Explicitly declaring method: :delete adds an immediate level of authorization to the links, enough to give you assurance the link is there for a reason.
The number of times I have seen people neglecting the method switch of their links is ridiculous -- imagine if you had the ability to destroy some data with such haphazard structure. You'd have so many mistakes in your code...
-
Resources
The second reason is more important - it retains the resourceful nature of HTTP:
HTTP resources are identified and located on the network by uniform resource locators (URLs), using the uniform resource identifier (URI) schemes http and https. URIs and hyperlinks in Hypertext Markup Language (HTML) documents form inter-linked hypertext documents.
Simply, the real structure of HTTP (the protocol which powers the "web") is such that you're meant to load resources through it.
This video explains it quite well:
These resources are meant to be located through specific urls, and if you think about it properly, only have a certain number of permutations which would allow the resource to be managed.
Indeed, when it comes to Rails, many engage with the resourceful nature of the web for the first time, hence questions like this. I didn't know about it until working with Rails... which is why it's so important to understand why this type of setup works so well:
The above shows what happens when using the rails resources helper (which I'd strongly recommend you use):
#config/routes.rb
resources :sessions, path: "", path_names: { destroy: "logout" }
This will create a set of "resourceful" links (as above). These links basically denote how you should handle the resources on your app, of course placing the DELETE method with the destroy action.
You don't have to use DELETE but it certainly makes your application more versatile!
Get is different in DELETE Request.
GET - Requests data from a specified resource
DELETE Deletes the specified resource
See HTTP REQUEST
delete 'logout' => 'sessions#destroy'
The main target is to make meaningful/semantic http requests.
since it corresponds to deleting session object via destroy action; RESTful recommends to use semantic HTTP verb delete rather than get. Moreover, Rails maps delete verb to destroy action by default.
Since you are not getting anything after you delete session rather you are redirected to somewhere else; so it is recommended to make AJAX calls with delete method.
For more info see this
https://parse.com/docs/rest/guide
I am using Ruby on Rails 4.1.1 and I am thinking to accept parameters (through URL query strings) that are passed directly to the url_for method, this way:
# URL in the browser
http://www.myapp.com?redirect_to[controller]=users&redirect_to[action]=show&redirect_to[id]=1
# Controller
...
redirect_to url_for(params[:redirect_to].merge(:only_path => true))
Adopting the above approach users can be redirected after performing an action. However, I think people can enter arbitraryparams that can lead to security issues...
Is it safe to accept URL parameters for populating the url_for method? What are pitfalls? What can happen in the worst case?
By logging params during requests to my application I noted Rails adds always :controller and action parameters. Maybe that confirms url_for can be used the above way since it is protected internally and works as-like Rails is intended to.
This it is safe internally as Ruby On Rails will only be issuing a HTTP redirect response.
As you are using only_path this will protect you from an Open redirect vulnerability. This is where an email is sent by an attacker containing a link in the following format (say your site is example.com).
https://example.com?foo=bar&bar=foo&redirect=http://evil.com
As the user checks the URL and sees it is on the example.com domain they beleive it is safe so click the link. However, if there's an open redirect then the user ends up on evil.com which could ask for their example.com password without the user noticing.
Redirecting to a relative path only on your site fixes any vulnerability.
In your case you are giving users control of your controller, action and parameters. As long as your GET methods are safe (i.e. no side-effects), an attacker could not use this by creating a crafted link that the user opens.
In summary, from the information provided I don't see any risk from phishing URLs to your application.
Rails redirect_to sets the HTTP status code to 302 Found which tells the browser to GET the new path as you defined it by url_for. GET is a considered a safe method in contrast to
... methods such as POST, PUT, DELETE and PATCH [which] are intended for
actions that may cause side effects either on the server, or external
side effects ...
The only problem would have been if someone could gain access to methods such as create and destroy. Since these methods use HTTP methods other than GET (respectively POST and DELETE) it should be no problem.
Another danger here is if you go beyond CRUD methods of REST and have a custom method which responses to GET and changes the database state:
routes.rb
resources something do
member do
get :my_action
end
end
SomethingController
def my_action
# delte some records
end
For future ref:
Rails has a number of security measurements which may also interest you.
It's not exactly an answer, just wanted to point out that you shouldn't use something like
url_for(params)
because one could pass host and port as params and thus the url could lead to another site and it can get worse if it gets cached or something.
Don't know if it threatens anything, but hey, it's worth pointing out
In my Rails application I have an url routed to an action in charged of showing or creating (if not existing) e resource. What is the appropriate http verb to use for this kind of request?
To be more precise, in my method I don't directly access the resource but I use a library which has that behavior: first search and then create the resource if not exiting. My method, in the end, always provide the resource returned by the library either a brand new one or an old one. Hence I cannot split into two requests.
According to this and considering my method always returns the same resource (idempotent) it seems that PUT should be the right one. I just wonder whether PUT can be used in case where e resource is actually just retrieved (get) and anything is not even updated
tnx
POST for creating, GET for showing is automatically used by rails. But I hope you can do all sorts of things with custom programming as data will be available to you in form of params[]
According to Ruby on Rails guides, you should use GET and POST verbs. More information here: http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
You use GET to retrieve.
If resource found return 200 with resource.
If resource not found let it return 404 and check the error code and use POST and create the resource.
If you donot need any parameter while creating resource then you should use GET request Else if you need params while creating resource , then you should make separate action for creating(Post request with params) and showing(GET request) resource.
I'm doing a rewrite of an old Rails application and I thought I should do it in a RESTful manner, as a learning experience if nothing else.
I've reached some actions that toggles a boolean value, for example if an article is published or not.
Before I had a couple of actions: toggle_published, publish and unpublish.
They were very easy to use: i just made a link to them in the article-list.
How would you do the same thing in a RESTful manner?
Should I use the update-action, and build a mini-form to replace each link that I used before? I don't particulary like that idea.
Just a notice:
A toggle method is not RESTful, because the HTTP PUT verb is supposed to be idempotent (see a.o. http://en.wikipedia.org/wiki/Idempotence#Examples). This means that no matter how often you execute a method, it should always give the same result. A toggle method does not adhere to this principle, as it does not give the same result if you execute it once comparing to executing it twice.
If you want to make it RESTful, you should create two methods: one for setting and one for unsetting.
Making an application RESTful does not only mean that you should use the correct HTTP verb.
I'd probably solve it with PUT/DELETE or POST/DELETE on a nested "toggle resource". Perhaps not 100% completely restful but certainly easy enough to understand.
PUT or POST /articles/:id/published # Toggle published ON
DELETE /articles/:id/published # Toggle published OFF
GET /articles/:id/published # Get state RESTfully via status 200 (ON) or 404 (OFF)
Might seem a bit odd, but it is technically RESTful.
Update: A (perhaps) more natural approach might also just be:
PUT or POST /articles/:id/published Data: { state: true/false } # Toggle published ON
You could also use the PATCH verb with the actual article which I assume has a published property:
PATCH /articles/:id { published: true/false }
Because all the cool REST kids are using PATCH nowadays.
It sounds like you have two use cases:
set published state
toggle published state
You should be able to add a member route for the toggle action for:
/articles/<id>/toggle_published - calls Article.toggle(:published)
And use Article update on :published attribute via the standard REST resource route.
map.resources :articles, :member => :toggle
I like #Van der Hoorn answer
so in real life we are using in login & logout scenario
use post or put or patch
/users/login -> with some payload data
/users/logout
In Above Eg login & logout is almost acting like setting boolean Flag , Easy to read and set in db
Eg : so its no harm to use same idea in toggle context
use post or put or patch
/book/3/publish
/book/4/unpublish
Note . :
1 : use this approach if there is only 1 field to be toggled , else if there are multiple fields then general /book/4 a patch request with payload data will do
2 : use this approach if there is any security layer is implemented so it will be like
Eg :
Editor -> can access urls like `/books/:id` & `/books/:id/publish`
Senior Editor -> can access urls like `/books/:id` & `/books/:id/unpublish`