My angular promise unexpectedly goes to error callback, why? - angularjs

I have a client running on Angular + typescript.
I need to send a post request to a php API (which I developed). The request arrives correctly to the server and the server fills the response body with the correct data (I have checked it myself debugging the server).
The issue is that, when the server responds, the angular promise executes the error callback and the response data is empty. When I check the sent request in the browser it says it was answered with a 200 OK status but it has an empty body.
I have tried calling the same API endpoint with the same paramentres through Firefox Api-requester addon and i recieve the response with the correct body... why is my Angular client not succeeding then?
The following code fragment corresponds to my controller:
vm.query = {
'tx_filtre':'', 'idioma_filtre':'', 'tipus':'', 'id_dimfisica':'', 'tamPag':15, 'numPag':0
};
this.PropietatsService.getPropietats(vm.query)
.then((response: ng.IHttpPromiseCallbackArg<string>) => {
vm.objResult = JSON.parse(response.data);
vm.propietats = vm.objResult.info;
console.log('rebut', this.propietats);
}, (response: ng.IHttpPromiseCallbackArg<string>) => {
//always executes this error function, why????
vm.objResult = JSON.parse(response.data);
});
And this is the relevant code for the service:
getPropietats(query: any): ng.IPromise<ng.IHttpPromiseCallbackArg<string>> {
var config = {
headers : {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
}
};
return this.$http.post("http://localhost:8080/diccionaris/propietat/get",JSON.stringify(query),config);
}
On a side note, for some reason my server can't process the request if I set the request 'Content-Type' to 'application/json' in my client. That is the reason why I have set it to 'application/x-www-form-urlencoded'.

You set 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;', but you encode query params to JSON and then you try to decode a response like JSON. Try set application/json or try to remove JSON.encode request params and send to post method query.
If it doesn't help log error (in response) in error callback and look at it

If the server is not capable of accepting application/json, then the POST data needs to be encoded for application/x-www-form-urlencoded. To do this use the $httpParamSerializer Service:
getPropietats(query: any): ng.IPromise<ng.IHttpPromiseCallbackArg<string>> {
var config = {
headers : {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
},
transformRequest: $httpParamSerializer
};
return this.$http.post(url,query,config);
}

I finally found the solution: it was a CORS problem.
I was running my server and my client in two different localhost ports so, although the server processed the request (which doesn't make much sense to me), it wasn't returning the response because the client was not allowed to access the server. To deal with it for now I've added the following line to my server index.php:
header('Access-Control-Allow-Origin: *');
And now it works just fine.

Related

Django server unable to get data from react Axios

I'm not getting an error but when I saw the logs of my server it prints an empty object {} whenever I send a request to the sever from my react app using axios. I double checked everything every other request in another components of my app works fine, but only in this particular request the data is not being sent! I have no CORS issue!
My react axios request
// PrivateAxios instance to send api request
const axiosPrivate = useAxiosPrivate();
const handleSearch = async () => {
const data = JSON.stringify({ from_company: keyWord });
try {
const response = await axiosPrivate.get(SEARCH_URL, data);
console.log(response);
setRecords(response?.data);
} catch (err) {
if (!err?.response) {
console.log("NO SERVER RESPONSE");
} else {
console.log("SOMETHING WRONG");
}
}
};
Server log
{} <-- Prints the request.data as an empty object
"GET /api/find_many/ HTTP/1.1" 200 6276
The django server responses with correct details when I send a request with Postman or Thunder Client. The server also prints the object that were sent with the Postman request. I don't know why the server is unable to get the object or data when I request from my react app.
Request sent from Postman returns
{'from_company': 'Jethmal Paliwal'} <-- Prints the request.data correctly
"GET /api/find_many/ HTTP/1.1" 200 2284
I have double checked everything, my headers are set correctly, Content-Type: application/json, withCredentials: true, and every other possible settings, Even every request from other components works great, but why this particular request doesn't reach the server?
Tried writing the data as an Object in the request funcion itself
const response = axiosPrivate.get(SEARCH_URL, { "from_company": "Jethmal Paliwal" }); which doesn't work as well. The same empty object gets printed.
Tried JSON.stringify the data, which doesn't work as well.
I believe that axios is omitting the data as it's not per REST standard to submit data in the GET request. HTTP allows that, but people and apparently libraries are not expecting it.
This is the API for axios get method:
axios.get(url[, config])
as you see there is no data in the method signature. And if we look at the POST method:
axios.post(url[, data[, config]])
I suggest if you have data to submit to server that you use a POST method instead.

API cs-cart put request by react and axios

I use react in front-end and cs-cart API in back-end.
In the following code I used axios.put() as follows:
const data = JSON.stringify({
"test1": "val1"
});
const config = {
method: 'put',
url: 'https://example.com/api/product/111',
headers: {
'Authorization': `Basic ${token}`,
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(res => {
console.log(res)
});
When sending a request, the browser sends a request with the OPTIONS method, which error: 405
Method Not Allowed returns.
And the original request (PUT) is not sent.
cs-cart is installed on the server. And the react project on localhost
Have you made sure to understand the error correctly i.e
The HyperText Transfer Protocol (HTTP) 405 Method Not Allowed response
status code indicates that the server knows the request method, but
the target resource doesnt support this method.
The server must generate an Allow header field in a 405 status code
response. The field must contain a list of methods that the target
resource currently supports.
Make sure that the server is able to understand how to interpret your request so the clients are able to proceed.
You can look at this in more detail below here.

.. from origin .. has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status

I'm fairly new to making API requests. I'm am trying to set up an incoming slack webhook using a simple axios post request from my React project, however I keep receiving the CORS policy error. The request works perfectly in insomnia.
I'm using ngrok to expose my web server running on my local machine to the internet (I assumed this would correct the issue.) So I'm making the request from https://...ngrok.io, however I'm still receiving 'Status Code: 400' in my network tab along with the error above.
axios({
method: "post",
url:
"https://hooks.slack.com/services/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",
headers: { "Content-type": "application/json" },
data: { text: "Hello, World!" },
}).then(
(response) => {
console.log(response);
},
(error) => {
console.log(error);
}
);
};
There are similar errors on stackoverflow, but none fix my error. I'd really like to understand why this is happening so any advice would be appreciated.
Fixed it, for those having the same issue:
What worked for me is setting Content-Type header to application/x-www-form-urlencoded. found it in this thread: https://github.com/axios/axios/issues/475 It appears that this triggers "simple request" and therefore avoids triggering CORS preflight. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests

Unable to get $http.post request data in Node.js res.body

I am using Angular 1.3 and node.js 0.12.2 for a project. I am hitting the node.js api using
$http.post("url", request_data){}
And on server side using this:
console.log(req.body)
But everytime the api gets called, it gets empty object {} for request_data , Unable to get what the problem is. I have used body_parser like this:
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
Have also tried adding content-type header in angular $http as:
headers : {'Content-Type': 'applicatio n/x-www-form-urlencoded'}
But not getting request data.
EDIT:
Node.js code :
router.post('/url',function(req,res){
console.log(req.body)
})
Note: Developer Tool's network tab showing the data, I am sending, in request header correctly, but node.js server not receiving in req.body.
In POSTman getting data is correctly in response.
some ideas :
Maybe an URL error ? Make sure you aren't using a prefix like app.use('/api', router);
Look at the Content-Type :
application/x-www-form-urlencoded --> 'var1="SomeValue"&var2='+SomeVariable
application/json;charset=UTF-8 --> {var1:"SomeValue", var2:SomeVariable}
You could use $http more explicitly :
$http({
url: '...',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: 'var1="SomeValue"&var2='+SomeVariable
});
My best guess is that your angular $http request URL is pointing to a bad end-point.
Angularjs
// data to post nodejs server
var _data = {
'message': 'Can I help you?'
};
// angularjs $http post request
$http.post('/api/url', _data).then(function(respond){
// if success
console.log(respond);
}, function(error){
// if an error
console.error(error);
});
Nodejs
// router function
function something(req, res) {
// console.log the request body
console.log(req.body);
// respond JSON object
var _respond = {
'status': 200
};
// expressjs respond a JSON with status code 200
res.status(200).json(_respond);
}
// register route URL
router.post('/api/url', something);
Note that the code end point URLs are same : /api/url
Therefore as your code sample in above question, you'r missing a /

AngularJS POST fails with No 'Access-Control-Allow-Origin' when using data payload object but works using query params like payload

I am facing a weird issue. I am running my angularjs app in nodejs server locally which calls a POST API from my app located on Google App Engine. The API is configured with all CORS headers required as follows:
def post(self):
self.response.headers.add_header("Access-Control-Allow-Origin", "*")
self.response.headers.add_header("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE,OPTIONS")
self.response.headers.add_header("Access-Control-Allow-Headers", "X-Requested-With, content-type, accept, myapp-domain")
self.response.headers["Content-Type"] = “application/json; charset=utf-8”
GET requests to the API work without issues.
POST requests to the API work but ONLY when I send the post data as a 'string of params' and NOT when post data is sent as an object which is the right way to do. Eventually I need to be able to upload pictures using this API so the first solution below might not work for me. Please help!
METHOD 1: This works:
postMessageAPI = "https://myapp-qa.appspot.com/message";
var postData = "conversationid=1c34b4f2&userid=67e80bf6&content='Hello champs! - Web App'";
var postConfig = {
headers: {
"MYAPP-DOMAIN" : "myapp.bz",
'Content-Type': 'application/json; charset=UTF-8'
}
};
$http.post(postMessageAPI, postData, postConfig).
success(function(data){
$log.log("POST Message API success");
}).
error(function(data, status) {
$log.error("POST Message API FAILED. Status: "+status);
$log.error(JSON.stringify(postData));
});
METHOD 2: This fails:
postMessageAPI = "https://myapp-qa.appspot.com/message";
var postData = ({
'conversationid' : '1c34b4f2',
'userid' : '67e80bf6',
'content' : 'Hello champs! - Web App'
});
var postConfig = {
headers: {
"MYAPP-DOMAIN" : "myapp.bz"
'Content-Type': 'application/json; charset=UTF-8'
}
};
$http.post(postMessageAPI, postData, postConfig).
success(function(data){
$log.log("POST Message API success");
}).
error(function(data, status) {
$log.error("POST Message API FAILED. Status: "+status);
$log.error(JSON.stringify(postData));
});
When I use METHOD 2 it fails with the following error in the console:
XMLHttpRequest cannot load https://myapp-qa.appspot.com/message.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://0.0.0.0:8000' is therefore not allowed access.
Please let me know if you have any solution. Thanks in advance.
The issue is most likely with Angular sending a pre-flight OPTIONS request to check the access headers from the server. I am not sure how OPTIONS requests are handled in your API, but I am betting these headers are not being added. I suggest installing Fiddler to monitor the actual requests to see what is going on with the headers. You may only be adding them to your POST responses.
See this answer for details on why METHOD 1 may work in this scenario, while METHOD 2 does not.
Here are some more details about pre-flight requests.

Resources