GeekJock
GeekJock

Reputation: 11316

GET vs. POST Best Practices

For my web application (PHP/MYSQL), I show a list of items and a link on each row to delete the item. Right now, the link is

<a href='item.php?id=3&action=delete'>Delete Item</a>

If I wanted to use POST instead... how would I do it (this is a dynamically generated list)? Can I send POST data without the use of a form?

Or, for every item, would I have to do:

<form action='item.php?id={$item_id}' method='POST'>
    <input type='hidden' name='action' value='delete'>
    <input type='submit' value='delete item'>
</form>

and style the submit button to look like the original link?

I am not familiar with php CURL or REST, would they help address this issue?

Upvotes: 15

Views: 18384

Answers (10)

cherouvim
cherouvim

Reputation: 31903

Please use POST for anything that modifies persistent state in the database. You don't want crawlers visiting your delete links!
Have a read at Architecture of the World Wide Web, Volume One and URIs, Addressability, and the use of HTTP GET and POST by W3C.

Edit: Sometimes though you need to use GET. For example membership activation URLs which are sent in emails are GET and need to somehow modify the database.

Upvotes: 20

you can also use get but you would need to check session values to ensure that it's the owner of the post who's attempting to delete. get is not "universally unsafe". it totally depends on how you use it.

Upvotes: 0

pbreitenbach
pbreitenbach

Reputation: 11291

You should not use an href to delete an item.

I would suggest doing this the old fashioned way and implementing a form-post for each row/item.

For example:

<tr><td>Item 1</td><td><form action=/delete method=post><input type=hidden name=id value=1><input type=submit value=Delete></form></tr>
<tr><td>Item 2</td><td><form action=/delete method=post><input type=hidden name=id value=2><input type=submit value=Delete></form></tr>
<tr><td>Item 5</td><td><form action=/delete method=post><input type=hidden name=id value=5><input type=submit value=Delete></form></tr>

Two other options: 1) using one with for each item 2) Ajax (but you will need to be proficient in Ajax)

Upvotes: 0

scotts
scotts

Reputation: 4097

POST is not a protection from all malicious behavior as some people have implied. Malicious users can still create links (that contain javascript to do the POST) and cause the same cross-site scripting problems as with GET. (<a href="javascript:function () {...}"/>)

That said, all the other reasons for using POST over GET apply (crawlers and the like).

Upvotes: 3

JasonTrue
JasonTrue

Reputation: 19609

You don't want to use Get because of the REST principle of not allowing Gets to change the state of the system. Unless you like search engines to delete all your content.

You won't need a form for each item; you can use one method=post form around the list with a delete_{id} input type=submit. Or, more cleverly, <input type=submit name="delete_item" value="{id}">. Names are allowed on submit buttons.

Per your question in the comments, <input type=submit name="action_{id}" value="Delete"> might work better, though it suffers from some issues that would work badly for localized sites. You can always revert to a HTML Button for a little more control over the presentation. It acts like a submit button by default.

The fact that you may get extra, unwanted information in the submission is mitigated by the average-case of sending back a much larger page than necessary with your proposed form-per-item solution, when you're just viewing the list. You can always use javascript to substitute the behavior of the plain-old-html form with a smarter version for javascript-capable clients.

If you're going to link to a "Get" for deletion, you should return a confirmation page with that Get that actually does a post upon confirmation.

Upvotes: 3

Ilya Birman
Ilya Birman

Reputation: 10072

It’s still better to do it with GET.

If your problem is that you don’t like the ugly URL of your link, you should be able to fix that with mod_rewrite (if you use Apache web server).

Edit: There is no reason whatsoever to use POST here. No. Reason.

People around here write about safe and unsafe as if chosing method can influence safety in any way. Of course you should authenticate your user no matter what method you choose. If you don’t, then your software is already broken. If you use javascript to emulate sending a form when you don’t have a form, and don’t need it, don’t need any javascript at all, then your software is already broken.

Actually, about 90% of web software is broken, because people have no idea about what they are doing.

Ignore this comments’ being heavily minused by some strange people. Avoid javascript (no need), avoid POST (no reason), authenticate your user (safety), make the href beautiful with mod_rewrite or some other way (being nice).

Upvotes: -12

Chris Winters
Chris Winters

Reputation: 1001

Here's a good example of why not to use GET to change server state:

http://www.infoworld.com/article/08/06/16/25FE-stupid-users-part-3-admins_5.html

The key portion is:

"It logged into the administrative area and followed the 'delete' link for every entry," the admin says.

If the delete had been coded as a POST this never would have happened. (OTOH we'd be robbed of a funny sysadmin story.)

Upvotes: 3

Will Harris
Will Harris

Reputation: 21695

As others have said, it's a really bad idea to use GET for destructive operations like delete, especially on Internet-facing web sites (or corporations with a Google Mini appliance) where web crawlers could accidentally delete all your data.

If you don't want to use a form, use an XMLHttpRequest to send the POST to your server. You could even set the method to DELETE if your server supports that.

If you can't use JavaScript and XHR (your users live in 1999), and you don't want to use a form in your list, use a link to a separate page where you can show the form and a probably a 'Are you sure?' message.

The best thing to do is probably a combination of the two options above: Render a link to a separate page with a form, but use JavaScript to rewrite the link as an XHR call. That way users from 1999 or 2009 can both have an optimal experience.

Upvotes: 0

Chris AtLee
Chris AtLee

Reputation: 8066

In general it's not a good idea to have a GET request that modifies the system state somehow, like deleting an item.

You could have your form look like this:

<form action='item.php' method='POST' id='form'>
    <input type='hidden' name='action' value='delete' />
    <input type='hidden' name='id' value='{item_id}' />
    <a href="" onclick="document.getElementById('form').submit(); return false;">Delete item</a>
</form>

Upvotes: 18

Brian Campbell
Brian Campbell

Reputation: 332776

You should never change anything in your database (other than logging information or other ephemeral data) from a GET request. The issue is that there is various web spidering software, web accelerators, anti-virus programs, and the like, that will perform a GET request on every URL they find; you would not want them to delete items automatically when they do so. GET is also vulnerable to cross-site request forgery; if an attacker makes one of your users click on a link that performs a bad action (for instance, creating a tinyurl that redirects to a delete URL), then they can trick the user into using their permissions to delete something without realizing it.

Yes, you will need a form that you submit to create a POST request. The other option is to use JavaScript and XMLHttpRequest, but that wont work for users who have JavaScript disabled.

You should also ensure that once you have accepted the data from the POST request, instead of returning a new page in response to that request, you should redirect the user to a page accessed by a GET request. This way, they will not accidentally re-send the POST request if they hit reload, or hit their back button later in their browsing session.

Upvotes: 8

Related Questions