I need $http POST Status code 400, but getting 200 - javascript

I have this code
var body="ok";
var suc=0; var failed=0;
$http({
url: API.toUrl('api/xxxx/xxxx'),
method: 'POST',
data: body
}).then(function(response) {
if(response.status==200){
suc=suc+1;
}
if(response.status==400){
failed=failed+1;
}
});
My problem in this is that I can't obtain the 400 Status Code, I am only getting 200 but not 400. How can I get 400 status code in my response parameter.
I am working in Angular, any idea for obtain the 400?
Thanks

400 status code will come as an error, then accept two functions as parameters first one for OK response and second one for errors so you have to catch 400 on error function.
So if you want to catch it you should do it like this:
var body = "ok";
var suc = 0;
var failed = 0;
$http({
url: API.toUrl('api/xxxx/xxxx'),
method: 'POST',
data: body
}).then(
function(response) {
if (response.status == 200) {
suc = suc + 1;
}
},
function(error) {
//Catch 400 here
}
);

You need to use another function for errors (400):
var body="ok";
var suc=0; var failed=0;
$http({
url: API.toUrl('api/xxxx/xxxx'),
method: 'POST',
data: body
}).then(function(response) {
alert response.status ;
},function error(response) {
alert response.status ;
});

If you are using PHP server to write your api's/services then use below lines to manually send 400 to your $http request
<?php
// Get the current response code and set a new one
var_dump(http_response_code(400));
// Get the new response code
var_dump(http_response_code());
?>
[UPDATE]
You can see more examples here to check how to send response codes:
PHP: How to send HTTP response code?

From the Docs:
A response status code between 200 and 299 is considered a success status and will result in the success callback being called. Any response status code outside of that range is considered an error status and will result in the error callback being called.
-- AngularJS $http Service API Reference
var body="ok";
var suc=0; var failed=0;
$http.post(url, data).then(function onSuccess(response) {
if(response.status==200){
suc=suc+1;
};
//return to chain response
return response;
}).catch(function onReject(errorResponse) {
if(errorResponse.status==400){
failed=failed+1;
}
//throw to chain rejection
throw errorResponse;
});
If chaining from the httpPromise, be sure to use a throw statement in the onReject handler to avoid converting the rejection to a success.

Related

NodeJS - how to tell the nodeJS server to send not as chunked transfer? so that Ajax can receive it

I have a data coming to NodeJS and then it needs to be served to Ajax query. but because the NodeJS is transfering it as chunked data, none of the general Javascript/JQuery ajax methods are able to capture the packet.
How can i get the values
nodeJS:
http.createServer(options, (req, res) => {
msg = c++_to_javascript();
res.writeHead(200);
res.end(msg);
}).listen(89);
Javascript/JQuery:
received the data as transfer encoded: chunked as a result no methods are able to decode the received packets in JS.
How could i solve it from NodeJS or in JS?
TRY 1: FAILED
$.stream(javascript_to_c++,{
open:function(){
console.log("opened");
},
message:function(event){
console.log(event.data);
buf1 = buf1 + event.data;
},
error:function(){
console.log("error");
},
close:function(){
console.log("closed");
}
});
TRY2 : FAILED
var test = $.ajax({
type: "GET",
url: javascript_to_c++,
async: false,
success:function(m) {
buf1 = buf1 + m;
}
}).responseText;
console.log(test);
TRY 3: FAILED
// Define a method to parse the partial response chunk by chunk
var last_index = 0;
function parse(xhr) {
var curr_index = xhr.responseText.length;
if (last_index == curr_index) return; // No new data
var s = xhr.responseText.substring(last_index, curr_index);
last_index = curr_index;
console.log(s);
}
function test() {
var xhr = new XMLHttpRequest();
var url = javascript_to_c++;
xhr.open("GET", url, true);
xhr.send();
// Check for new content every 5 seconds
var interval = setInterval(parse, 5000);
// Abort after 25 seconds
setTimeout(function(){
clearInterval(interval);
parse(xhr);
xhr.abort();
}, 25000);
}
test();
You just have to properly wait for the response to come back. I'm not too familiar with the other ajax methods you're using but let's look at this for example:
var test = $.ajax({
type: "GET",
url: javascript_to_c++,
async: false,
success:function(m) {
buf1 = buf1 + m;
}
}).responseText;
console.log(test);
Are you expecting test to be the response? $.ajax returns a Promise representing the asynchronous request. It's not until the success callback is called or the promise is resolved when you'll get the response text. Try this instead:
var test = $.ajax({
type: "GET",
url: javascript_to_c++, // I'm assuming this is a valid URL?
success:function(content) {
console.log(content); // This is your actual full response.
}
});
As far as having the node process specify the content type, try the content-type header:
res.set('content-type', 'text/plain');
res.end(msg);
Update:
As already pointed out, it's highly doubtful that the Transfer-Encoding thing is actually a problem. It you do want to disable it, do:
res.set('transfer-encoding', '');
...but really, it shouldn't be necessary.
Another Update:
Not using Express? You'll just need to slightly modify this:
res.writeHead(200, {
'content-type': 'text/plain',
'transfer-encoding': '' // not recommended...
});
res.end(msg);

.done not fired on ajax call

I have a function that makes a ajax call. The .done doesn't seems to be firing. I checked for the error on my console. It says
function getIncidentInfo() {
$.ajax({
type: "GET",
url: "../../page_components/statsboard/stats.php",
data: $(this).serialize(),
dataType: "json",
}).done(function(response) {
incidentAr = response;
for (var i in incidentAr) {
var zaNorth = parseInt(incidentAr[i].zaNorth);
......
}
}).fail(function(xhr, status, error) {
console.log("Status: " + status + " Error: " + error);
console.log(xhr);
});
}
I asked my friend to try the same piece of code and it works.
The script in stats.php is throwing an XDebug error and is returning HTML describing the error instead of the JSON you are expecting. Loading the stats.php page in a browser, or check your PHP logs to find out what the error is.
Check .always(response) instead of .done(response). Some services return non 200 codes with a response body to describe the error.
Check response.responseJSON, response.responseText, and response.responseXML. You may have to state response.responseJSON = eval(respaonse.responseText).
However, I see that the responseText is of HTML type, so my guess (and I say this because you're getting a 200 status and not a 404 or 500) is that you are getting a more generic server error that is rendering a response from a route you did not intend to query.

Why does validation not fail on client side but fails on server side?

Right now, I have a form with several fields and on submit, I want to check if the username is taken or not. If taken, do nothing (show validation error), if not taken, successfully proceed onto the next form.
Here's what I have done so far:
View:
var RequestCreateAccount_Submit = function () {
var res = false;
ValidationAttribute.BlankValue(true);
var form = $('form#RequestCreateAccount');
$.validator.unobtrusive.parse(form);
var res = form.valid();
var data = form.serialize();
if (res) {
$.ajax({
url: Url.getFullUrl('Account/RequestCreateAccount_Submit'),
type: 'Post',
data: data,
cache:false,
success: function (data) {
//Next Dialog
},
error: AjaxLog.HandleAjaxCallFail
});
}
return res;
}
Controller:
[AllowAnonymous]
[HttpPost]
public ActionResult RequestCreateAccount_Submit(UserAccount userAccount)
{
//Check if username is unique
if (!WebSecurity.UserExists(userAccount.UserName))
{
UserSession.AddValue(StateName.CreateOrEditAccount, "CurrentUserAccount", userAccount);
JsonResult res = Json(new { Success = true, data = "", Message = "" });
return res;
}
JsonResult jres = Json(new { Success = false, data = "", Message = "Username is already registered"});
return jres;
}
I tested it with a known username and it did hit the success=false (outside of the if statement) line and it did not go inside the if statment. So I know the validation on the server side works.
However, I am wondering why on the client side, it still success = true and the next dialog appeared. It did not fail on validation. What am I doing wrong on the client side?
The reason is that your controller does actually successfully return a result. It is just that the successful result indicates an error. While logically similar at this point, they are very different. Error is going to be reserved for actual exceptions thrown or 404 no route present type of scenarios.
You should check for the response status inside of your success callback function
dotNetFiddle Demo
$.ajax({
url: Url.getFullUrl('Account/RequestCreateAccount_Submit'),
type: 'Post',
data: data,
cache:false,
success: function (data) {
if(data.Success === false){
AjaxLog.HandleAjaxCallFail();
// this may not make as much sense though
// as the request didn't actually fail, just the action did
//TODO: code for name fail
return;//do not process next dialog
}
//Next Dialog
},
error: AjaxLog.HandleAjaxCallFail
});
The success = false of your result object doesn't means that the request failed. It stands only for data.success, nothing more. The resquest is still successful(HTTP 200), which I think is the right response code. If you return an error code like new HttpStatusCodeResult(404, "error message"); it means that your request failed, but it isn't true.
You request works whatever the result of the check is. So you may check this in your success callback, instead of the error callback:
success: function(data) {
if (data.success) {
//Next Dialog
}
else {
// error message
}
}

AngularJS navigation by HTTP status code. (MVC design)

I’m trying the convert an unstructured jQuery application to MVC AngularJS but at one point I’m kind of lost or I just don’t get it… (Unfortunately I’m not a JavaScript-God so the error might also be there)
This is the snippet of the original jQuery code.
$.ajax({
type: "GET",
url: "rest/users/" + userId + "/requests",
accept: "application/json; charset=utf-8",
statusCode: {
200: function(data) {
// do something
},
404: function() {
window.location = 'index.html';
},
500: function() {
alert("Server Error!");
}
}
});
A simple REST call where the HTTP response code is used to navigate. Unfortunately I can’t make this run in AnglularJS.
Here is my Controller:
// Inside the RequestController
$scope.requests = RequestModel.getRequestsByUser($rootScope.currentUser.userId);
if($scope.requests.statusCode == 200) {
// do something
}
else if($scope.requests.statusCode == 404) {
$location.path('/notFound');
} else if ($scope.requests.statusCode == 500) {
$location.path('/error');
}; // PROBLEM: The if/else statement is never true since statusCode is not available
Here is my Model:
// Inside the RequestModel
this.getRequestsByUser = function(userId) {
var RequestResource = $resource('../rest/users/' + userId + "/requests");
var requestList = RequestResource.get({}, function(response, getResponseHeaders) {
// PROBLEM: The property "stausCode" is "unavilable" at the Controller even if it was set here
requestList.statusCode = 200;
console.log("SUCCESS: getRequestsByUser() -> StatusCode: requestList.statusCode");
console.log(requestList);
}, function(response, getResponseHeaders) {
requestList.statusCode = response.status;
console.log("FAILED: getRequestsByUser() -> StatusCode: " + response.status);
});
return requestList;
};
This doesn't work since “statusCode” is “unavailable” inside my controller. The REST call works and also the data binding to the view is fine. I’m just not able to implement the “navigation part”. Do I miss something like $watch properties, asynchronous behavior or is my approach just incorrect?!
Thanks for your help!
You can make better use of resource parameter mapping in your service:
// Inside service
this.requestsByUser = $resource('../rest/users/:userId/requests', {userId:'#userId'});
That way you'll be able to reuse the same resource for different rest actions (eg. post, delete).
And controller code to handle statuses (response handlers were moved to controller):
// Inside the RequestController
$scope.requests = RequestModel.requestsByUser
.get(
{userId: $rootScope.currentUser.userId},
function(response) { // success handler
if(response.status == 200) {
// do something
}
},
function(response) { // error handler
if(response.status == 404) {
$location.path('/notFound');
} else if (response.status == 500) {
$location.path('/error');
}
}
);
Another way around is to use $q service to return promises from your service. But provided solutions seems cleaner to me

Issues with handling http errors with jQuery AJAX webservice calls

I'm developing an jQuery application in where I've a requirement to capture HTTP errors as and when it occurs. Below is my snippet.
// Function to validate URL
function validateURL(url)
{
var pattern = new RegExp();
pattern.compile("^[A-Za-z]+://[A-Za-z0-9-_]+\\.[A-Za-z0-9-_%&\?\/.=]+$");
if (!pattern.test(url))
{
return false;
}
return true;
}
// Generic error handler for handling the webservice requests.
function initWebService(wstype, wsurl,jsonData)
{
// If the method parameter is not either "GET" or "POST" display an error message to the developer.
var msgValidateArgument;
var wsCallStatus;
var callbackData;
if ((arguments[0] != 'GET') && (arguments[0] != 'POST'))
{
//alert("Invalid");
//alert("You must provide a valid http method in your webservice call.");
msgValidateArgument = "You must provide a valid http method in your webservice call.";
return msgValidateArgument;
}
// Making sure whether the developer is passing the required number of parameters.
if(arguments.length < 3)
{
//alert("Some required arguments seems to be missing. Please check your webservice invocation.");
msgValidateArgument = "Some required arguments seems to be missing. Please check your webservice invocation.";
return msgValidateArgument;
}
if (!validateURL(arguments[1]))
{
msgValidateArgument = "You must provide a valid URL in your webservice call.";
return msgValidateArgument;
}
if(arguments[2] != ''){
var response=jQuery.parseJSON(arguments[2]);
if(typeof response =='object'){
//It is JSON
alert(response.toSource());
}
else{
msgValidateArgument = "The JSON data being passed is not in valid JSON format.";
return msgValidateArgument;
}
}
// Making the AJAX call with the parameters being passed. The error handler handles some of the possble http error codes as of now.
$.ajax({
type: arguments[0],
url: arguments[1],
data: arguments[2],
dataType: 'json',
async:false,
statusCode:{
404: function(){
alert('Page not found');
},
500: function(){
alert('Page not found');
},
504: function(){
alert('Unknown host');
}
},
success: function(data){
//alert('Data being returned from server: ' +data.toSource());
//alert('Data being returned from server: ' +data.toSource());
//alert(data);
callbackData = data;
}
});
return callbackData;
}
But, when I programatically change the webservice url to hold a wrong value, and upon calling the html page, I'm able to see an error message in the firebug console, but my snippet doesn't seem to be catching the error at all.
For e.g, While calling the GEONames API, I'm encountering an stating "407 Authorization required" in firebug's console.but even if I handle that status code in my error block, it is not firing.. What could be the reason?.
Don't we have any comprehensive solution for handling these HTTP errors effectively?.
I think there are a few problems with your code ... firstly how is handleError called ? because you call a method called handleError but pass nothing ... im assuming your using .ajax()
You should do it like this :
$.ajax({
statusCode: {
404: function() {
alert('page not found');
},
500: function() {
alert('server error');
}
},
success : {
alert('it working');
},
complete : {
alert('im complete');
});

Categories