I'm in the process of writing a RESTful API. For the most part, everything works out great but there are a few cases when I'm not dealing with a resource that things start to break down. While there are a million ways to solve the problem I'm facing, I'm looking for some feedback as to which would be the most ideal.
For simplicity, we'll say that the API is a timer.
A user can only have 1 active timer at a time.
The API has 2 functional endpoints start and stop.
When the user starts the timer they POST some data related to the timer which creates a new timer as long as they don't already have a timer running.
Calling stop on the timer updates the timer to mark it inactive.
I currently have this setup as follows:
Start Timer:
POST /api/v1/timer
Body: [
'thing1' => 'something',
'thing2' => 'somethingelse
]
Response: 204
Stop Timer:
PUT /api/v1/timer/stop
Body:
Response: 204
Since a user can only have 1 timer active, it didn't seem to make sense to return the timer id as you would in a more traditional CRUD call.
I've read some posts that suggest using POST method on the stop call to trigger the stop instead of a PUT. I suppose that makes sense too... this just really breaks down when you're not dealing with a traditional resource.
Of course, I could also rewrite it to return a timer resource but to me that adds overhead of the client having to then track the timer id when they want to stop (or delete) the active timer.
Any input here would be greatly appreciated.
Think about how you would implement this requirement on a website.
You would be looking at some web page, specific to the current user. There would be a link labeled start. You would get that link, and it would bring up a form that gives you the ability to override the default parameters associated with starting the timer.
When you submit the form, the browser would construct a request based on the HTML form processing rules. Since this isn't a safe operation, the method would probably be a post, and the form data would be application/x-www-form-urlencoded into the message body.
Since changing the state of the timer would probably change the representation of the original page, that's likely where the form would tell you to submit the POST. A successful response to the POST request would tell the browser to invalidate it's cached representation of the original page.
When you reload that page, the "start" link would be gone, and there would instead be a "stop" link. The operation of that link would be much the same --> clicking the link takes you to a form, submitting the form back to the original page, invalidating the previous representation. When you reload the page, the timer is off and the start link is available again.
GET /DarthVaderYellowMerrigold
GET /DarthVaderYellowMerrigold/start
POST /DarthVaderYellowMerrigold
GET /DarthVaderYellowMerrigold
GET /DarthVaderYellowMerrigold/stop
POST /DarthVaderYellowMerrigold
GET /DarthVaderYellowMerrigold
There are various things you might do to clean this up (returning the new representation in response to a successful POST, for example, with the appropriate Content-Location headers, so that the client doesn't need to fetch the data), but the basic idea is sound.
Do that in a machine readable way, and you have yourself a REST API.
Doing that mostly means documenting how the machine is supposed to understand what each link is for. "To go to the start timer form, look for this link; to go to the stop timer form, look for that link".
You'll probably leave HTTP and URI alone, but it's reasonable to replace HTML with, for example, one of the hypermedia JSON types. Or to put the links into the HTML headers, rather than in the representation.
Of course, HTML has the immediate advantage that you can just walk the API "by hand" and make sure that everything works using your favorite desktop browser. Trade-offs abound.
Related
I've designed a forum on my website that operates through AJAX requests therefore the URL does not change at all. You click a button, the AJAX requests a PHP file, and the response updates the client. This works for me - however, I need to know if it's possible to redirect a user through a series of AJAX requests after a form submission.
User enters forum.php page
User clicks on topic button (AJAX request to load threads)
User clicks on thread title (AJAX request to load replies)
User clicks on reply button (AJAX request to load text editor)
User clicks on submit (AJAX request to submit form)
At this point I want to redirect the user back to that specific thread - therefore I believe they would need to be directed through a series of AJAX requests. Is this possible?
Extra: Also if you believe this forum process is not efficient please let me know your opinions.
Seems you have a few options:
continue to use Ajax for the submit, so no need to redirect. (EDIT: sounds like you are already doing this, so the problem is probably you are discarding the content you want to display, rather than just hiding it temporarily)
implement a way to load a page directly to the forum. This would be in addition to the ajax call. You would track the forum ID, include it in $_POST parameters, and have the server redirect to the appropriate URL.
Generate javascript (or approriate fields/data for your fixed javascript to use) that will cause the page, when reloaded, to automatically make the necessary AJAX calls.
Skip Ajax and just use full page loads for everything
Mixing things up, by sometimes using Ajax and sometimes using a page load isn't ideal, but it is sometimes difficult to avoid completely.
Keep in mind what happens when user hits the BACK button or history in the browser. Do you want them to leave your app when hitting back? They can end up in a weird place mixing ajax/page loads. For this reason, people favor (4)
(2) is probably a lot of work.
(1) would be ok, and BACK button will just always take the user WAY BACK to some other website. Personally, that wouldn't bother me.
(3) would be a pain and also be slow, and then you get pretty weird forward/back behavior. Avoid.
(4) might just be best.
I am using Laravel 5.2.15.
There are list of records in a webpage with Edit and Delete button with each record. I have two approaches for deleting the record
Use JQuery and send Ajax Request to server.
Place a form tag for delete button in each row.
I have following question
In case I use Approach 1, can it cause any issue when the site will be viewed from Android or iPhone? I have another option to do Server side validation using Request class.
In case of Approach 2, Will it make the page heavy? I am using Pagination, so 10 records will be displaced per page.
Please guide me if I should go with which approach or please suggest if both approaches are incorrect.
The questions you have don't really focus on the main reasons to choose one above the other. They differ mostly in how the request is sent to the server and how the page is refreshed to show the results.
Using Ajax is a very common approach and relies on using Javascript, a technology that has been available in all browsers for a very long time. Compatibility will not be a problem as most of the internet wouldn't function without it anyways (and you can even make it work using your second approach as a fallback mechanism). The request you sent is typically a HTTP DELETE request to a REST endpoint so that the server then knows to delete the record1. Upon receiving the success response from the server the page is responsible for updating itself by removing the row corresponding with the just deleted record, and possibly fetching new records to still have 10 rows on that page. No page refreshes required, but some Javascript required.
Your second approach is kind of old school in that the form you submit contains some kind of identifier such that the server knows what to do. This is a full page load and should be a HTTP POST request if you want to do it properly2. Following the Post/Redirect/Get idiom the server then sends a Redirect response so that the browser will then trigger yet another normal page load as GET request to show the user the updated list of records. You do not have to update the page manually by yourself, at the cost of having annoying page reloads (this isn't really expected anymore in the current day and age).
My advise would be to go with the first approach. It is the modern way of doing things and allows for having non-reloading pages. It does however require some additional work on the client side (in Javascript) to update the page accordingly.
As a side note, CSRF must be taken care of in both instances really. Always include a CSRF token with every 'update' action you perform on the server.
1 You have to program this yourself, of course :)
2 Browsers don't generally support anything other than GET and POST, although the HTTP specification allows for much more request methods.
It depends upon your requirements. But you should go with the 1st approch. If you will use 2nd approch the you will have to refresh the page since you can not handle the response. So basically if you delete 5 items the page needs to be refreshed 5 times and you may not send more than 1 delete request at a time. Now If you use 1st approch since It's ajax and javascript you can display appropriate message depending upon the result and no need of unnecessary page refresh.Plus as you mentioned you can do validaton using Request class. So you can handle bad or malicious request. And I am sure CSRF won't be that much of a problem since you can check whether the request is ajax or not using Request::ajax(). So 1st approch is better mostly because of that no page refresh.
Both approaches are fine ;)
But 2nd approach would be better than first one; Using this approach you can prevent CSRF attacks too;
I would suggest you to use method 1 with certain modifications.
Use get request to delete the record.
Send a CSRF token and dont forget to encrypt your id for the record
add your delete URL to href
Then when you do ajax request, use the url from href and you could send some additional parameter like is_ajax=1, but laravel already checks for the jquery header so Request::isAjax() method will let you know if the request was an ajax request or normal request.
Now all you need to do is send different response for ajax and normal request.
HOPE THIS HELPS :D
Another drawback of your second approach which haven't been mentioned is displaying validation errors. Specifically from your edit and even your delete actions.
If you have multiple forms for each set of data showing errors from validation would be a pain. But if you follow approach number 2 just by getting the reference of the row element submitted, you could easily append an alert div if ever an error from validation has occurred.
as for the delete action, somebody else might have already delete some shared data so you might also want to tell the user somebody already threw this out.
Is there a way to pass results generated within a PHP page (called into action by an ajax post request) back to the document in bits / intervals?
Here is an example...
I am making an ajax POST to a PHP document with keywords passed by the user which scans a few sites to determine if they have resources for the search. If they do the PHP file returns a link to the site, and continues to the next one, if not I will just continue on to the next one..
with an ajax (I use jQuery) I can make this request and wait for the page to load, and then show all the links together easilly, but am wondering if I can display the links one by one as they load from the PHP file so that I don't have to wait for every page to be checked.
Thank you for your input.
You can implement this by having the client send a request for the first X (5 or whatever) results, display those, and then immediately send the request for the next X records. Your client will simply continue making requests and displaying records until it gets an empty response, at which point retrieval is complete.
To make this work you either need to maintain state on the server so that you know "where" in the search to pick up searching, or the client needs to include sufficient information in each AJAX request for the server to know how to continue processing.
By the way, this seems more like a GET operation than a POST.
There might be some cases that your request takes long time because
of some problems with your client internet connection or your server
connection. So since the client doesn't want to wait he clicks on the Ajax
link again which sends the request to the server again which messes up
the following:
Rendering of our website in the browser because we are giving extra
load to the browser.
What if the second request processed correctly and you showed user
the page and then comes along the error message from your first
request(saying request timed out) which loads above on the correct
content and mess up with the user reading the correct content.
I want to stop the 1st Ajax response if the Ajax function is called twice. How do I do this?
so i want to stop the 1st Ajax response if the Ajax function is called
twice
What you actually want is to prevent a second request when a first request is in progress.
For example, You may have to change the Save button to Saving..., disable it (and add a little progress wheel) to give live feedback to the user. (Facebook does this)
The key is love feedback to the user. If the user is clueless on what is going on, they are going to think nothing is happening.
You might want to check why the operation is taking long
If this is a complex/time consuming operation, like, say a report generation or a file upload, a progress bar should do
If this is because of the client's internet connection, say it up front, like Gmail: Your have a slow Internet connection and this site may be slow. Better still, provide a fallback option, with less/no Ajax.
You say cause we are giving extra load to the browser: this is kind of fishy. You will not be giving extra load to the browser unless you are giving it tons of HTML to render. Use Ajax only for small updates on the browser. You may want to reload the page if you expect a large change.
How bout seeing as your using some form of JavaScript to begin with you have that link either hidden or disabled in a manor of speaking til the pages request has been followed through with. You could for example have the requested ajax wait for a second variable that would enable that link so a user could click it. But until that variable is received from the original AJAX request its disabled to the click, then if it is clicked it disables again and waits for the same variable to come back again.
Think of how some developers disable a submit button on a form so a user can't double submit there form.. same concept of notion here.
I have an application that supplies long list of parameters to a web page, so I have to use POST instead of GET. The problem is that when page gets displayed and user clicks the Back button, Firefox shows up a warning:
To display this page, Firefox must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.
Since application is built in such way that going Back is a quite common operation, this is really annoying to end users.
Basically, I would like to do it the way this page does:
http://www.pikanya.net/testcache/
Enter something, submit, and click Back button. No warning, it just goes back.
Googling I found out that this might be a bug in Firefox 3, but I'd like to somehow get this behavior even after they "fix" it.
I guess it could be doable with some HTTP headers, but which exactly?
See my golden rule of web programming here:
Stop data inserting into a database twice
It says: “Never ever respond with a body to a POST-request. Always do the work, and then respond with a Location: header to redirect to the updated page so that browser requests it with GET”
If browser ever asks user about re-POST, your web app is broken. User should not ever see this question.
One way round it is to redirect the POST to a page which redirects to a GET - see Post/Redirect/Get on wikipedia.
Say your POST is 4K of form data. Presumably your server does something with that data rather than just displaying it once and throwing it away, such as saving it in a database. Keep doing that, or if it's a huge search form create a temporary copy of it in a database that gets purged after a few days or on a LRU basis when a space limit is used. Now create a representation of the data which can be accessed using GET. If it's temporary, generate an ID for it and use that as the URL; if it's a permanent set of data it probably has an ID or something that can be used for the URL. At the worst case, an algorithm like tiny url uses can collapse a big URL to a much smaller one. Redirect the POST to GET the representation of the data.
As a historical note, this technique was established practice in 1995.
One way to avoid that warning/behavior is to do the POST via AJAX, then send the user to another page (or not) separately.
I have been using the Session variable to help in this situation. Here's the method I use that has been working great for me for years:
//If there's something in the POST, move it to the session and then redirect right back to where we are
if ($_POST) {
$_SESSION['POST']=$_POST;
redirect($_SERVER["REQUEST_URI"]);
}
//If there's something in the SESSION POST, move it back to the POST and clear the SESSION POST
if ($_SESSION['POST']) {
$_POST=$_SESSION['POST'];
unset($_SESSION['POST']);
}
Technically you don't even need to put it back into a variable called $_POST. But it helps me in keeping track of what data has come from where.
I have an application that supplies long list of parameters to a web page, so I have to use POST instead of GET. The problem is that when page gets displayed and user clicks the Back button, Firefox shows up a warning:
Your reasoning is wrong. If the request is without side effects, it should be GET. If it has side effects, it should be POST. The choice should not be based on the number of parameters you need to pass.
As another solution you may stop to use redirecting at all.
You may process and render the processing result at once with no POST confirmation alert. You should just manipulate the browser history object:
history.replaceState("", "", "/the/result/page")
See full or short answers