I am having a serious issue with Angularjs and jQuery with this particular REST API. I am not in the same domain as said API, and can get the data back, however I am getting a "SyntaxError: invalid label "name" :{" error.
If I were to do something like $http.get or $.get I get a timeout after 10 seconds. However, if I use jsonp with either library I will see in Firebug that the data is returned in the net tab, however I get the error above in the console tab. After doing some research, I have seen plenty of people having issue with the API (a Jive product) and this specific line of text that is returned along with the JSON. The response looks something like this:
throw 'allowIllegalResourceCall is false.';
{"name":{ "givenName": "xxx"}}
The big problem is the first "throw" line. I have tried a bunch of ways to remove that line but I haven't found the proper way to do it. I apologize for not being able to provide a code sample, but if there is any way to get this work in Angularjs or jQuery, I will take it. I don't know if the answer lies in Angularjs interceptors, or transformResponse.
Any help that can be provided will be appreciated.
Thank you
AngularJs allows you do define the methods for transforming the http response data (so you can remove the first line of the response data). You can do this either for a single request or add a httpInterceptor.
Single request:
$http.get('...', {
transformResponse: $http.defaults.transformResponse.unshift(function(data) {
// Remove first line of response
data.split("\n").slice(1).join("\n")
}
});
HttpInterceptor
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(function() {
return {
'request': function(config) {
config.transformResponse.unshift(function(data) {
return data.split("\n").slice(1).join("\n")
})
return config;
}
}
})
}])
Plunker: http://plnkr.co/edit/6WCxcpmRKxIivl4yK4Fc?p=preview
Related
When using an api I often find myself with a rather complicated error object.
Depending on the API that I am using the error texts are quite helpful and I would actually sometimes like to display them directly to the user. The problem, of course, is that the error objects can look quite differently so it would be very verbose to go through them and pick individual objects in case they exists (dependant on the status code of the error).
Is this just the nature of the error object or is there a better way to do this?
What I do to handle API calls that end up with error is this:
try {
const response = await axios.post("Your URL");
// Your code to handle the result
} catch (error) {
console.log(error.response.data.error)
// Code to display the error to the user
}
error.response.data.error is the actual error message sent from the server, not the error code
My API implemented with expressJS returns json as normal response, but when an error occurred, returns error code with a plain text, by simply calling res.sendStatus(401).
This causes a problem on my frontend, I use angular ngResoruce, and the resource code is like this:
svc.authenticateApi = function() {
return $resource(apiEndpoint + 'authenticate', null, {
'save': {
method: 'POST',
transformResponse: function (data, header) {
console.log("transformResponse, header:", header());
console.log("transformResponse, data:", data);
return { data: angular.fromJson(data) };
},
},
});
};
This works fine when normal JSON data is returned, however, when error status is returned, the data parameter is not a serialised JSON string, it's plain text, and I get errors like this:
Apparently transformResponse tries to parse text Unauthorised as JSON and failed. I can work around this by sending every error response as JSON on the server end by calling something like `res.status(401).send({error: "Unauthorised"}, but that feels like a hack, and I don't want to manually repeat error text for each status code.
Is there a better way to handle this? I don't want it sounds like a rant, but ngResource document is really poor and I start to think using $http is a much better solution.
I've moved away from $resource and am using $http everywhere. I just find everything about $resource to be a bit wonky. I do think returning JSON from the server in all scenarios sounds like the best approach though. You could implement a custom handler to test your incoming responses to work around this, but that doesn't really feel right to me.
I'd guess that the error is occurring on the return { data: angular.fromJson(data) }; line though. You could wrap this in a try/catch as well.
I did find success following the suggestion by Mike Feltman to wrap the fromJson call in a try / catch. The idea is if there is an error, there's no need to bother transforming the response.
function transformIgnoringErrors(original) {
var data;
try {
data = angular.fromJson(original);
/* code to perform transformation */
} catch (err) {
/* return what came in because no need to transform */
data = original;
}
return data;
}
I'm just following tutorials and figuring out how to handle get requests in NodeJS.
Here are snippets of my code:
NodeJS:
router.get('/test', function(request, response, next) {
console.log("Received Get Request");
response.jsonp({
data: 'test'
});
});
Angular:
$http.get("http://localhost:3000/test").
success(function(response) {
alert("OK");
}).
error(function(response) {
alert("FAIL");
});
If I try to access the link directly # localhost:3000/test, I'm able to receive the JSON message correctly. But when I use angularJS $http call, the request always fails and I'll find this error in the network inspector (Response)
SyntaxError:JSON.parse:unexpected end of data at line 1 column 1 of
the JSON data
The reason for that is because the response is empty but the response code is 200 in both cases.
I've tried searching for hours but maybe someone can enlighten me on this?
you could try and send
res.send('test')
and then on your http request you can use 'then'
$http.get("http://localhost:3000/test").then(function(res) {
console.log(res);
})
unlike success, then will give you a complete object (with 'test' - string as res.data)
success will bring you only the data;
then will bring you the whole object (with the status and such)..
now about that jsonp .. it's used to override a json response. you could simply use 'res.json({data: 'test'})' and it should also work for you..
hope it helps
You're using jsonp in node, which you probably don't need to. This adds extra characters to the response and so the JSON parser fails to parse (that's what the error is telling you, the JSON is malformed)
Try changing the server to look like
response.json({
data: 'test'
});
If you look in the Network pane of the developer tools, you should be able to see the raw response. It should look something like:
{"data" : "test"}
In the latest release of Angular (v1.3.0) they added a fix for the content-type header for application/json. Now all my responses get an error cause they are not valid JSON. I know I should change the back-end to respond with a plain text header, but I can't control that at the moment. Is there any way for me to pre-parse the response before Angular tries to parse it?
i think that this was the fix they made:
https://github.com/angular/angular.js/commit/7b6c1d08aceba6704a40302f373400aed9ed0e0b
The problem I have is that the response I get from the back-end has a protection prefix that doesn't match the one that Angular is checking for.
I have tried to add an http interceptor in the config, but that didn't help, still parses after Angular itself.
$httpProvider.interceptors.push('parsePrefixedJson');
The error i get in my console (it comes from the deserializing of a JSON string in Angular):
SyntaxError: Unexpected token w
at Object.parse (native)
at fromJson ...
You should use
$http.defaults.transformResponse
You also don't wanna use .push(). You need your transformer to do its thing before angular's default transformers. You should use .unshift() instead.
So your code should be
$http.defaults.transformResponse.unshift(transformResponse);
where transformResponse is a function which will transform the response from the server into a proper JSON.
I found a way to change the default transformer by adding this to the Angular app:
app.run(['$http',
function($http) {
var parseResponse = function(response) {
// parse response here
return response;
};
$http.defaults.transformResponse = [parseResponse];
}
]);
This will override the default behavior, you can also set it as an empty array if only selected responses need to be transformed.
See this question/answer: AngularJS, $http and transformResponse
Using a normal html form, I can add a new task by sending POST request to /api/tasks/insert/
POST data includes $name and $description of the task.
However, when I use Angular to push the data to REST API in php, only a POST request is sent and an empty row is created in the database.
This means that the POST variables are not being passed i.e. name and description.
What am I doing wrong?
I have been stuck at this for the last few hours now. I have checked countless tutorials and am pretty sure of the syntax. My backend REST api in PHP works fine.
var res=$resource('http://localhost/api/tasks/insert/',{},
{
createTask:{method:'POST'}
});
postData={name:"Hello",description:"DescBaby"}
res.createTask({},postData);
//res.createTask(postData); tried this also, but doesn't work
Another variation that I tried based on an comment was this:
res.createTask({name:"TestName", description:"descBaby"}).$promise.then(function(value)
{
console.log("Success"); //I get success in console.
},function(errResponse)
{
console.log("Error");
});
Angular Does not give me any errors. Just sends a blank POST request to the url.
EDIT:
I checked in the network pane in Chrome whether the data was sent or not and as it turns out it is being sent.
However, in the response it's showing this :
Undefined index: name in XYZ.php line ABC.
The line pointed above is the following line in my PHP:
$obj->InsertTask($_POST['name'],$_POST['description']);
Thanks to a friend of mine, I finally got the code running. The problem wasn't with my Angualar Code but with php code.
As it turns out I cannot read POST data as $_POST[].
file_get_contents should be used in such cases as data is sent through a JSON payload and not through request parameters!
Here's how I got it running : Angularjs $http.post, passing array to PHP
Did you look at the network tab of debugger? You can check if valid data was sent to server. If it was ok this is not JS or Angular question. On the first look it seems that you have valid code for angular. Just in case check if you have set proper ajax headers.
"X-Requested-With": "XMLHttpRequest"
Does other AJAX calls work for you?
Try this (and create a factory to follow the best practices):
Service
services.factory("Tasks", function($resource) {
return $resource('http://localhost/api/tasks/insert/', {}, {
createTask: {method:'POST', params: {name:"Hello",description:"DescBaby"}}
})
});
Controller
Tasks.$createTask();