php custom error codes for ajax app - javascript

I have an ajax application which returns content of article with given id. All requests are sent to a php file, which takes article content from database and echos it.
Now, there is problem: php file will always have 200 OK status. And I want it to send some status code, which says that article doesn't exists. Something completely out of usual range (like 100 000 or similar).
My question is, is it possible to set some status like that with php?

You can set the HTTP status code with http_response_code. You can only use status codes in the 1xx, 2xx, 3xx, 4xx, or 5xx ranges. You can't make up your own status codes. See this answer for info on that: https://stackoverflow.com/a/11871377
For a status of "article doesn't exist", you can simply use 404 Not Found.
http_response_code(404);
Here is a list of HTTP status codes: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
EDIT: http_response_code only works on PHP 5.4+. If you don't have PHP 5.4 you can do:
header("HTTP/1.0 404 Not Found", TRUE, 404);
More info on this: https://stackoverflow.com/a/12018482

You could send a 404 status code back using http_response_code.
Another option would be to encode a status code and the data you want to return as a JSON response and return that to the browser.
$response = array(
'status' => 100001,
'result' => '<h1>Title...'
);
echo json_encode($response);
exit;

Generally you can mix two ways of answering in PHP. Best practice is to send correct http status code , but with correct code (like 404 for not found and 409 for wrong input (just example)) you can send text response message like if it is standard answer.
So you can mix previous answers (if you need it):
http_response_code(404);
$response = array(
'status' => 100001,
'result' => 'Document was not found on server'
);
echo json_encode($response);
exit;
But i'm not sure you need sub-statuses in that situation.
With that in your javascript you can operate by xhr response code to determine the error itself and show to user some text and substatus that came from server in response body;

Related

Understanding JavaScript responses

I am using the following PHP code to respond to a JavaScript fetch() request.
$json = json_encode(array(
'status' => 200,
'resources' => $dataObj
));
http_response_code(200);
header('Content-Type: application/json');
echo $json;
exit;
Back in my JavaScript code, after I get the response, I can do the following:
console.log(response.status);
console.log(response.resources);
console.log(JSON.stringify(response.resources));
The first line works and shows a value of 200. The other lines display undefined.
Now, if I add response.json() before my code, all three console lines show correctly.
let resp = await response.json();
console.log(resp.status);
console.log(resp.resources);
console.log(JSON.stringify(resp.resources));
My question is: Why in the first example can I correctly see the status of 200, but I need to use the json() function in order to see the data object?
When you make an http request - any http request - you will get back a status code. This is available on the response object.
You have also sent a status property as part of your response body, and until you explicitly tell your code to read the response body as json (response.json()) you wont be able to read any of your custom response.
So, basically, the status you can read is the one sent back by the server - not the one on your json.
If you're using the Fetch API you will always get an object back which you don't need to parse. It's already an object literal, specifically a https://developer.mozilla.org/en-US/docs/Web/API/Response.
This object has a property called status which returns 200 in your first case.
If you do however call the method json() on this object, it will parse the body of your response, not the whole thing. In this body you have your status from the backend not the status of the Response.
That's why let resp = await response.json() will return you your actual response data with your resources and such.
the response is actuallay a string:
"{'status':200,'resources':'sth'}"
and that string hasnt a resources property. You first need to parse it to an object literal.
To clear up some confusion:
The server sends a full response, so the upper is just the body , while a http response also consists of a header. If you do:
response.status
thats actually the headers status.

javascript redirect in ajax response

I have a modal for my login form. I submit the login form using Ajax. If username and password were invalid, I display a message to inform user about failure
But if login data was valid, I'd like to redirect the user to dashboard.php
Here is what I wrote in php file for response:
$action = $_GET['action'];
if($action=="checkLogin")
{
$result = check_login();
if($result=="failure")
{
echo "login failed";
}
else
{
echo 'success
<script>
window.location = "dashboard.php";
</script>
';
}
}
But it is not working as I expect. "failure" and "success" are shown, but redirect does not happen in case of success
Please help me were I am wrong?
Thanks in advance
Your PHP can't control what the client does from an AJAX response; It can't set headers or redirect the client. Instead, you need to return an appropriate success or failure HTTP status code and redirect based on that. A 200 status means success, a 401 means a unauthorized. Click here to learn more about HTTP status codes.
In PHP, response codes can be set in a variety of ways, depending on your version. My example below is the most bare-bones way and should work in PHP4 but Click here for more ways to set them.
if($result == "failure") {
header("HTTP/1.1 401 Unauthorized");
echo "failure";
}
else {
header("HTTP/1.1 200 OK");
echo "success";
}
You can then capture those status codes in your javascript client and redirect if the login is successful. If you were using JQuery it might look something like this:
$.ajax("example.php")
.done(function() {
// done() is called on any 200 response codes (200, 201, etc)
window.location = "dashboard.php";
})
.fail(function() {
// fail() is called on any 400 or 500 response codes (400, 401, 404, 500, etc)
alert("error");
});
It's worth noting that because of the status codes, you do not need to check the response body in your javascript for the words "success" or "failure". Browsers and other clients are already designed to gracefully handle HTTP response codes, so use them as much as possible.
If you can redirect using php you could do this:
header('location : your_php_page.php');
the problem with your code is that you're calling it from ajax. meaning the code is most probably returning text. not html or javascript. if this was coming back to an HTML page, sure it'd print the "Script" part and your js would run. but here, you'd have to do something like this:
in your ajax callback('success' or 'then'. whichever you used):
success: function(data){
if(data == "success")
window.location.redirect("path.php");
}
Try this:
else
{
header('location:your_location.php');
}
or if you are using ajax than return false or something else from here and for this put this in js:
window.location.href = "your_location";
This is what I have done to redirect page:
else{
echo "<meta charset='utf-8'/>";
//direct after five seconds
echo "<meta content='5; url=http://".$_SERVER['HTTP_HOST']."/dashboard.php"."' http-equiv='refresh'> ";
}
What I think about is you don't need 'success' as response ,
If the login valid , just redirect the page.
If fail , OK , let us know with echo "login failed";

Why php json response does not send back the data array to ajax jquery request?

I have made an ajax request to the php server where I send a data from a form request and I would to get back the same data from the server just for testing requests and responses of the same data throwing between the client and the server.
$.ajax({
method: "POST",
url: "addRaces",
dataType: "json",
data : sending_data,
success : ...
})
sending_data is an array like {field_form_name : value}
The server responds to the request with the following code :
$data = [];
foreach ($request->Input() as $key => $value) {
$data[$key] = $value;
}
return json_encode($data);
The same data should come back to the client, but nothing happen with an alert(response) or a jquery showing debug data like $('#debug').html(response);
The strange thing coming up when I try to push the server answer like
return json_encode([
'debug' => $data['name']
]);
and showing results to client like
$('#debug').html(response.debug);
it is working for a single key-value response showing the properly value field I have send from the client.
Other wise whether I send the full data as an array nothing is shown in the debug area of the client.
return json_encode($data); wont work. as it is returning the json string to the calling method which is not your jQuery at front end. Don't confuse front end (html javascript, jQuery, etc...) with back end (PHP) the two of them are running in different machines. One at client end and another at your server.
you should use echo json_encode($data); this will output the json string and your web server will send it to the front end.
Make sure you are echoing the data not returning as #bansi said, if you are echoing it already then debug using var_dump(json_encode($data)) . If json_encode() found errors it will return False instead of the expected json array.
You should debug using the developer tools instead of using code $('#debug').html(response.debug);. The Network tab of developer tools is very useful to debug HTTP requests, it will show response header and body of your requests.
In your case, just change return to echo like #bansi's answer. The return command does not print the data so you did not get anything in the response.

How can I trigger the error event in DropZone using PHP?

In dropzone.js , there is an event error, however I can not find any documentation on how to trigger this from PHP.
I have tried sending various header() responses from PHP including, 404, 500, 503, and so on yet this event has not fired.
What I am looking to do, is the server checks the mime to see if it is valid, and if it is not valid, I discard the file, and ideally -- return an error so that dropzone can respond accordingly.
From the javascript side, I have tried the following :
.on("complete", function(file,response) {
console.log(response);
}
.on("error", function(file,response) {
console.log(response);
}
.on("success", function(file,response) {
console.log(response);
}
... however, response is undefined, even if i return JSON or plain text from the php script. It doesn't appear that dropzone.js supports getting the full server response or at least it doesn't elevate it to the custom handler. The ONLY place I have seen any reference to passing a second param on events is here on SO in other questions that are not directly asking this question.
There must be a way to get the server response (as I have done in the past with other uploader javascript such as jQuery POST, and jqUpload, and so on). It seems rather silly that I can't trigger a command to signal the upload failed -- even if the file transfer completed -- as it still needs to wait on the script for a response. --- This means I am likely overlooking something, which is why I am calling for assistance as their documentation reveals absolutely nothing with regards to how a server should respond --- language irrelevant, however in my case, I am using PHP.
Thanks in advance.
<?php
header('HTTP/1.1 500 Internal Server Error');
header('Content-type: text/plain');
$msg = "Your error message here.";
exit($msg);
?>
NOTE: Do not redirect user else it won't run exit($msg)
<script type="text/javascript">
$(document).ready(function () {
Dropzone.options.dropzone = {
maxFilesize: 10,
init: function () {
this.on("uploadprogress", function (file, progress) {
console.log("File progress", progress);
});
}
};
});
</script>
That's it! It should work.
If you send any non-200 response header Dropzone will detect it as an error and fire the error(file, response) event. The error info can go in as JSON and is accessible via response.your_msg_variable
Note that just printing response won't show anything useful as it's an object, you can use console.log(JSON.stringify(responseText, null, 4));
This will pretty print the object upto 4 levels down

Struggling to communicate with the utorrent web API

I am trying to access utorrents web api, it uses a token authentication system which is detailed here
the JavaScript on my page is
<script>
$.getJSON("http://XXX.XXX.XXX.XXX/lib/token.php", function(response) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
//script.onreadystatechange = function () {
// if (this.readyState == 'complete') utorrent();
//}
//script.onload = utorrent();
script.src = 'http://XXX.XXX.XXX.XXX:8080/gui/?list=1&token=' + response.token;
head.appendChild(script);
});
</script>
simply retrieving the token from a php file and passing it along the chain, i have confirmed that the token is being passed and is not being poisonned, my PHP document is below
<?php
header('Content-type: text/json');
$token = file_get_contents('http://[username]:[password]#XXX.XXX.XXX.XXX:8080/gui/token.html');
$token = str_replace("<html><div id='token' style='display:none;'>", "", $token);
$token = str_replace("</div></html>", "", $token);
$response = array('token' => $token);
echo json_encode($response);
?>
this gives me a confirmation of the token
Object {token: "GMt3ryaJE64YpXGN75-RhSJg-4gOW8n8XfTGYk_ajpjNLNLisR3NSc8tn1EAAAAA"}
but then i receive a 400 error code when retrieving the list
GET http://XXX.XXX.XXX.XXX:8080/gui/?list=1&token=GMt3ryaJE64YpXGN75-RhSJg-4gOW8n8XfTGYk_ajpjNLNLisR3NSc8tn1EAAAAA 400 (ERROR)
Any help/thoughts/idea's would be greatly appreciated
just adding my 2 cents.
I've been doing a similar implementation in .NET MVC - I was able to get the token as you did, but the list=1 feature didn't work for me either, getting the 400 bad request code (as you have found).
The solution for me:
In the token.html response, there is a token in the div and also a GUID in the header.
To break it down:
Call token.html with uTorrent credentials
In the response content, parse the html to get the token
in the response header, there is a value with key Set-Cookie, which looks like
Set-Cookie: GUID=<guid value>
I needed to use this value (GUID=<guid value>) in all requests being sent back, as well as the token and it worked!
I'm not sure what the implementation is in PHP to do this however :)
Also quick note, I've been trying to get values through jQuery's $.getJSON and $.Ajax method without any success, because the browser (chrome) I'm using has strict guidelines on cross domain requests, and it doesn't look like uTorrent is implementing JSONP.
Hope this helps!
The 400 Error message means you are communicating with a bad request.
The MIME media type for JSON text is application/json .
use text/plain or application/json, not text/json.
application/json sometimes causes issues on Chrome, so you might want to stick with text/plain in this case.
Have you tried changing the order of the query parameters?
eg: http://localhost:8080/gui/?token=<token_uuid>&list=1
Reference: https://github.com/bittorrent/webui/wiki/TokenSystem#examples
UPDATE
I ran into a similar problem trying to create and XMPPBot for utorrent client in python.
#m.t.bennett was correct. You need to save the session information as well.
When you receive the response from token.html, capture the cookie information as well.
Usually there are 2 params: GUID and sessions. You need to put them in the header for all your subsequent requests -- List API, Getfiles API, etc.
This should fix your problem!

Categories

Resources