how to determine failure in ajax request - php

I'm working with Mootools to develop a simple ajax-y page that does some manipulation with db records using PHP as the backend.
I'm submitting the ajax request to a PHP page that calls a function and returns TRUE or FALSE if the record was able to be updated/deleted or not.
However, it seems like the mootools onSuccess event is fired anytime the server returns a 200 status, regardless of the value returned (eg. FALSE is still assumed to be a success).
How do I use onSuccess in a meaningful way, short of returning a 40x error code or something?

All answers given by #dombenoit and #Marc are technically correct.
However, I totally differ from #Marc's vision: to me, using HTTP status codes is both efficient and common for webservices. I use them all the times and much favor them over outputting text, mainly for the following reasons:
they give a free standard for handling incorrect values, instead of making you output text and parsing it clientside, meaning semantical repetition;
they make all tools understand something went wrong, as the question itself outlines;
they feel right in a REST architecture.
To support this vision, here's a question: what's the goal of your call? Is it to update or delete a record? Then if this goal is not reached, something went wrong. It failed, and the application should know it at application-level, not through first saying 200/OK and then precising in the textual response it did not! To me, it feels like using "undefined" instead of undefined.
So, here, I would make PHP send an HTTP error status code, that is one in the 4xx-5xx ranges.
Then, the good question is: which code to use? This is a design decision that totally depends on your application and the degree of specificity you want to get to.
If the goal of the call is to update / delete, and the fact that it does not happen is extremely unlikely and is an unexpected, serious error (for example: the DB is inconsistent because there's no way the call could reference an entity that does not exist), then you should use 500 / Internal Server Error.
If it could be possible that the targeted entity does not exist at the time of the call without it being a critical error (example: your app provides several ways to delete an item, so another one could have been used instead of this call), then I'd advise 410 / Gone: you get a clear, expressive error handling, for free! And you can still use 500 for actual errors (DB connexion exceptions…).
Then, you could get even more specific about update errors only, for example with 409 / Conflict if that's the kind of errors you're trying to foresee with updates…
I always give a look at the HTTP status codes reference when I'm designing a webapp.
Just for the sake of completion, that's how you send headers in PHP (without framework at least — check for specificities):
header("HTTP/1.0 404 Not Found");
UPDATE: since it seems you decided to go with the answer that suggested to use JSON to encode success or failure, I have to add the following points about resilience.
Not relying on status codes and only on application-level data makes your code very fragile. Indeed, there are situations where you get actually unexpected errors. Not the application-level “exception” that you raised yourself, but something wrong on a lower level (server unavailable, bad config that makes the server crash, changed routing system…). These will all show through HTTP status codes (or through timeout), but not through a JSON-encoded answer, since your application will have already crashed before being able to output anything.
Like #Dimitar put it, from a programming point of view, this is somehow “naive”: you trust not only your code (you shouldn't), but also the environment (server) and the network. That's a very, very optimistic vision.
Using status codes as the standard way to handle expected exceptional situations give you a free handling of those unexpected situations: you've already registered other handlers than onSuccess, and supposedly good ones (retrying once, notifying the user, offering backup possibilities…).

Personaly, I feel that using the HTTP status codes to indicate the success/failure of whatever was supposed to happen on the server is incorrect. Everything about the HTTP call itself worked perfectly - the fact that the server was unable to complete the request doesn't mean the HTTP request failed.
It's like driving to the store to buy something, only to find it's out of stock. Returning an HTTP 404, to me, would imply that the store itself was gone. Yet, you've successfully driven to the store, walked inside, walked back out, drove home.
So, use a JSON data structure to indicate the results of the requested transaction, which you can check for in your client-side code:
$results = array()
$results['success'] = false;
$results['failure_code'] = XXX; // some code meaningful to your app
$results['failure_message'] = 'Something dun gone blowed up, pa!';
echo json_encode($results);
Then in your Moo code:
if (!results['success']) {
alert("AJAX call failed: " + results['failure_message']);
}
If the call worked, then you'd have
$results = array();
$results['success'] = true;
$results['data'] = ....;

You have a couple options, two of which you mentionned in your question. You can use onSuccess and execute some code based on a true/false response, like so :
onSuccess: function(responseText, xml){
if(responseText == "false"){
// do something...
}
}
Or you could raise errors in your PHP code, returning an actual valid error code thus firing the onFailure event.
Or as mentionned by Marc previously, you could use a JSON response format, in which case you would use MooTools' Request.JSON.
onSuccess: function(responseJSON, responseText){
// do something...
}

Related

What is the CF OnRequest scope called in other languages?

I've been fortunate enough to be a CF dev for pretty much my entire IT career without having to take on using another development language so I have a knowledge hole I'd like to ask others to help me with.
I've built an API and I want to describe to others how to invoke it. It needs to be invoked first thing during a request before any generated content is sent back to the user. One of the possible outcomes of the API call is that the incoming user request could be aborted so that there's no error message but also no generated content. Just a blank screen. Sending back the blank screen with no generated page code is critical.
I can tell someone using CF that it needs to be called at the beginning of the Request scope or OnRequest scope but I'm at a loss as to how to get across the same arrangement for someone using other languages/frameworks like PHP, ASP.NET, Node.js, Wordpress, etc.
So, for example, for a CF based site I'd say something like: "The synchronous API call needs to be made early in the Request or OnRequest scope and BEFORE any generated page content is returned to the user". What I'm looking for is how to describe that same thing but for users of those other languages/frameworks.
Odd question but Google has been zero help (or perhaps I just don't know how to search for something like this). Any advice/guidance would be most appreciated.
Thanks in advance!
Is not the answer to your question simply to tell them "It needs to be invoked first thing during a request before any generated content is sent back to the user" (I copy and pasted that from your question).
That's it. That is absolutely clear.
That's all you need to do.
Don't worry about how they need to do that in their language of choice, esp given the very nature of your question, you won't know how. It's their job to write the code to consume your API. Not yours.
At most you could give them some usage pseudo-code along the lines of:
// at the beginning of the response handler
apiResult = apiObj.makeRequest(args, here)
if (apiResult.youCanComeIn == false) {
// handle it with a 403 or something appropriate
// stop
}
// they're allowed in, so rest of processing here
Obviously, any API request must return a specific response. And probably you need to pass the expected value and the value of a certain error at the level of your API. Further, any developer will understand what information to issue when receiving some error from the API response.
You probably mean something like: "request processing is required on the server side, in case of an error, generate an empty page on the client side", etc.
It's hard to recommend anything. Maybe server-side rendering, SSR

How to return error code from restful service when expecting JSON

I am attempting to create a restful PHP web service which typically returns pure JSON data. if something goes wrong on the web server side, lets say a bad SQL query, what is the correct restful way to let the user know something went wrong?
Catch the exception on your server side code.
Log it.
Then pick one of the following HTTP Status code appropriate for the situation (REST basically returns http status codes). Error 500 seems good :)
http://www.restapitutorial.com/httpstatuscodes.html
Return that as JSON or XML, dependent upon your imeplentation to the client, along with either a nice error message or the raw error message (dependent upon whether you'd like the client to know)
FYI, preferably return a nice error message, instead of giving clients a peek into your back end data structures :)

ZendAMF - function calls in quick succession fail

I'm implementing AMF service methods for an flash front-end. Normally things work fine, but we've found that if two methods are called one right after the other, the second call returns null to the flash front-end even though the method actually completes successfully on the PHP end (to verify this, I dump the return data to a file right before I return it).
Has anyone had this behavior before? Is it some setting with ZendAMF?
Maybe wait a confirmation that the first method was finished before call the second ?
I use ZendAMF too. I have noticed that if one call fails, it will trigger a failure message for any other batched calls (Async tokens can be used to get around this).
I would try sending each call one at a time and finding out which one is failing if there is one. Personally, I use a software called Charles which is and HTTPProxy that allows me to see the contents and error messages of any AMF calls I perform. You could also use wireshark, either way you would be able to see the exact request sent, and any error messages that are being thrown by your backend.
Are you using any transactions in your code (like Doctrine ), sometimes the code will pass test and write out correctly, but choke when the transaction gets closed and end up throwing an error.
It actually turns out the flash side was using the same connection for two function calls. Making separate connections for each call has solved the problem.

Error messages stored in SESSION

Is it a good practice to store error messages in SESSION? For example after a redirect. Passing in through url isnt a solution for me...
I am wondering if it is a good solution... because..
Would a concurent submit of user cause problem? (A long time-taking post, while ajax content is obtained from another tab) that may mess up the session! Or that is impossible to happen?
If user makes a request and it fails for some reason to display the page then the message may be shown at an irrelevant page!
So? Any alternatives??
For example when using POST/redirected/get pattern
When storing error messages in the session, you must take care, that two request dont overwrite the other ones message, before it is displayed. And you must take care, that a page, that should display a message, only displays its own message.
You should show errors, when they occur and not redirect before. Also there is no reason to redirect in such a situation.
Is it a good practice to store error messages in SESSION? For example after a redirect.
Not in general. Session data should be data that matters for a significant period, errors are generally a result of a single request and the details don't need to persist.
Storing that sort of data in a session is just an invitation to race conditions.
why dont you assign them an specific id like error_id=2 and send them through url?
or is this also not possible in you case?
you could also send an error id through session...
It is not uncommon to store error messages in session, especially in cases where there can be multiple redirects. Zend framework has something like flash messenger which kind of does that.
Anything that is in session would stay in session until you destroy it or session times out. The best practice is store the error messages in session, then when the page is loaded where the error message needs to be displayed, your code would get the messages from the session and display them if they exist. After the error messages are displayed you would need to delete them from the session, otherwise each time the user goes to this page they would see the same error messages popping up again and again.
The best approach is to display and delete.
I believe you should not run into any problem ever if you use this approach. The reason is that if an incorrect form is submitted it would always have errors in it and it will always try to store those error messages in session and display them accordingly does not matter how many times they have added/deleted in session. I hope this all makes sense.
Also when you store session error messages you need to store them smartly so that the backend knows that these error messages are stored for which form.
Focus on the user! All your development efforts want to provide the best UX possible.
The first question is, why do you need messages at all?
In case of a successful request, you want the user to know that his request was successfully executed.
In case of an erroneous request, you can distinguish: if the request may be altered by the user to turn into a successful request, then show a helpful error message (e.g. a simple form submission). If the request may not be altered by the user, be as informative as possible why the request failed (e.g. "Couldn't execute as service XY is not available. Please contact support etc.").
Easy: Erroneous request that may be altered:
In case of an erroneous request where the user may alter the request, don't save it in the session and directly render the page where the user may correct his request.
Difficult: Successful request or erroneous request that may not be altered:
Here you may generally want the user to not be able to execute the exact same request again after hitting F5 or taking similar actions, hence you redirect the user. In this case I personally favor the solution with a flash messages component (see Symfony Docs or Zend Docs for an example). In general, this technique does not lead to race conditions if your applications meets these assumptions:
Your HTTP requests fired from the browser are executed fast. A user does not have a real chance of firing a second request in the meantime.
Your AJAX calls either do not influence the flash messages - or, if you return structured data (XML, JSON) you may include a special section for flash messages, that are then being rendered by Javascript.
Now, to minimize error rates you can do the following:
Store the timestamp when you added the flash message. Don't display old messages (e.g. > 1 minute). A mobile user may loose connection and then retry. What state does he expect the application to be in?
Don't ever let the HTTP requests between your user and your server take long. If you need to perform long computations, try offloading things to a background worker and show the status of processing to the user.
Summing up: If you have general good practices concerning your HTTP communication in place, then the user is unlikely able to mess up flash messages. Weigh the pros and cons and focus on the user, not the complexity of your implementation, as there are methods to cope with that.
Generally speaking:
Try to put as much on the client-side (javascript and cookies) and try to store as less as possible on the server-side.
This includes the SESSION variable, which in the best scenario should contain only user id.
If the message is after redirect, you could add a request variable that could index the message and to show it that way.
Instead of storing in a session, you could pass an error code in the URL that you would then use to look up the error. I've user bare-bones exception classes for this kinda thing:
class MyException extends Exception
{
const USER_NOT_FOUND = 'The requested user was not found';
// ...
}
Then your redirected url would be something like /controller/action/error/USER_NOT_FOUND and you'd use that to look up the message:
echo constant('MyException::' . $error);
You don't need to use an Exception class for this, but it allows you to keep things really tidy
if ($errorState) {
throw new MyException(
MyException::USER_NOT_FOUND
);
}

Best practices to deal with absent/wrongly typed GET variables?

What do you do when you detect your get request is broken or is passing wrong types of data? Say you have a forum-page.php?forum=3 that lists all the topics related to forum 3.
What would be a good way to deal with the absence of the "forum" variable? What about if instead of being an integer, you would get a string? How would you respond to such a wrong request?
Spit out an error telling why you refused the request
If forum-page.php is called without the "forum" variable simply redirect to a default page, something like forum-page.php?forum=1. The same thing for a wrongly typed forum variable.
Redirect to some other page. Something like the forum/board index?
Other options?
Would really love to read your opinions about this.
I typically return a 400 (Bad Request) with a status description explaining why (eg. "forum parameter is required"). Not sure if PHP allows this (ASP.NET does), but then you could then map a 400 to a custom page that displays the error in a way that makes sense for your application.
It depends quite a bit on each page and their GET requests. Most pages like the one you used as an example can fail gracefully, but others which have required variables missing may need to throw a 400 (Bad Request) or a 404 (Page Not Found). 404 is actually quite necessary because there may be a bad link being spidered by a search engine or being passed around through the internets, so you'd want to stop this behavior.
My view is to try the following:
For wrong/missing required variables, throw a 400 or a 404 (depending on your app). However, for a 400, I would fail gracefully to the default page (forum-page.php) and show the error in a error box at the top of the page.
For wrong non-essential variables that may be mistyped, fail gracefully to the default page.
For wrong non-essential variables that are completely the wrong format or object type, throw 404's since they may be attempts at subverting the security of your app.
Ultimately, the really important thing to never do is to try to "guess" the wrong/missing variables and fill it for the user (in most cases). I've come across many webapps where this behavior was misused by hackers to trick the webapp to simulate a vulnerability.

Categories