I have a Nodejs express server and an angularJs client which sends data to the server.
The problem is when I try to send a JSON to the server with angularJS, the received JSON becomes like this:
{"{\"question\":\"What will be result of code int a ":" 5/2\",\"answers\":[{\"a\":\"2.50\",\"b\":\"1\",\"c\":\"2\",\"d\":\"no right answer\"}],\"answer\":\"c\",\"score\":\"100\"}"}
Here is my post method in angularJS:
createQuestion: function(question){
delete question["_id"];
console.log(JSON.stringify(question))
return $http.post('http://localhost:3000/questions/', question, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
})
.then(
function(response){
return response.data;
},
function(errResponse){
console.error('Error while creating question');
return $q.reject(errResponse);
}
);
}
the output of console.log(JSON.stringify(question)) is:
{"question":"What will be result of code int a = 5/2","answers":[{"a":"2.50","b":"1","c":"2","d":"no right answer"}],"answer":"c","score":"100"}
Here is the part of the code in nodejs responsible for POST methods:
exports.create_a_question = function(req, res) {
console.log(JSON.stringify(req.body))
var new_question = new Question(req.body);
new_question.save(function(err, question) {
if (err)
res.send(err);
res.json(question);
});
};
After a search I found out that this problem happens because of application/x-www-form-urlencoded in the header of requests but I add this configuration to my nodejs server and the problem still persists:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
Here is CORS headers on nodejs server:
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Max-Ag', '3600');
How can I solve the problem?
The back slashes ("\") happen when JSON.stringify is called twice:
var x = {a:1, b:2};
var y1 = JSON.stringify(x);
var y2 = JSON.stringify(y1);
console.log(y2);
The AngularJS framework automatically does a JSON.stringify with the $http.post method. The second JSON.stringify was called in the Node.js code.
The solution is to use JSON.parse in the Node.js code:
var x = {a:1, b:2};
var y1 = JSON.stringify(x);
var y2 = JSON.parse(y1);
console.log(y2);
So here is how I solved the problem:
download the cors library via npm:
npm install --save cors
use it in the code:
var cors = require('cors');
app.use(cors());
then I removed the unnecessary header option when calling angularjs $http.post
Possibly:
headers: { 'Content-Type': 'multipart/form-data', 'Cache-Control': 'no-cache', 'Pragma': 'no-cache'}
Since there are multiple content types at issue here ...
Related
I've seen several questions and answers around this and mine is half working.
I have a node.js api server with url api.domain.com and the website on an nginx server at www.domain.com when I do the following in angular the request goes through on the api server, I see the request I see it getting parsed and put into the database. However, on the client side I do not get a return right away and then eventually I will see No 'Access-Control-Allow-Origin' header is present on the requested resource.
I know what is causing this behavior but shouldn't it throw the error before it hits the API server? Also note that the node.js server has cors enabled. The response that should be coming back is json.
$http({
method: 'POST',
url: "http://api.domain.com/addtrans/" + $scope.accountID,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT',
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: function (obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {
payload: JSON.stringify(trans)
}
}).success(function (result) {
$scope.trans = {};
console.log(result);
});
I have used the below middleware for all of our projects and it has been proven to work best.
const allowCors = (req, res, next) => {
/** Allow all origins, for now TODO */
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', 'Authorization, Content-Type');
res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
/** Browser check for pre-flight request to determine whether the server is webdav compatible */
if ('OPTIONS' == req.method) {
res.sendStatus(204);
}
else next();
};
// Put this code before the routes you want to allow CORS to
app.use(allowCors);
You should change the Allow-Origin to something more restricted for security reasons.
The above code covers CORS as well as pre-flight on most browsers(this ia major issue we were having in the beginning).
i used this a while ago (express 3.x):
// npm install --save cors
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
app.use(express.static());
app.get('*', function(){});
require('http').createServer(app).listen(3000)
Remember that the cors header should be on the response which is coming from server not the request which is sent from client.
You can use a middleware to enable cors on the server:
//CORS middleware
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'example.com');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
//...
app.configure(function() {
...
app.use(allowCrossDomain);
...
});
I am developing an ionic app when I am sending a post request using angularjs $http.post to my express js server, I cannot see the data in the req.body.
I am running my server on localhost:3000
Code in my server for CORS
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type");
res.header("Access-Control-Allow-Methods", "GET,PUT,DELETE,POST");
next();
});
My angular Js post request
$http.post('http://localhost:3000/signup',{"username":"x","password":"y"}).success(function(res){
console.log(res);
if(res.msg=="success")
{
//do something
}
}
I am able to see data in req.body as "key" like:
{'{"username":"x","password":"y"}':''}
When I am setting the header from ionic app as:
$http.defaults.headers.post["Content-Type"] = 'application/x-www-form- urlencoded; charset=UTF-8';
Please let me know how to debug this
You are getting the entire data as key in req.body. This is because the angular request that you are making is wrong. Here is the part of code that should work
$http({
url: 'http://localhost:3000/signup',
method: "POST",
data: { username : "a" , password : "b" }
})
.then(function(response) {
// success
},
function(response) { // optional
// failed
});
Well I figured that out
I have used this stackoverflow link Ionic framework http post request to parse my data before its send to my server
$http.defaults.headers.post["Content-Type"] = 'application/x-www-form-urlencoded; charset=UTF-8';
Object.toparams = function ObjecttoParams(obj)
{
var p = [];
for (var key in obj)
{
p.push(key + '=' + encodeURIComponent(obj[key]));
}
return p.join('&');
};
$http({
url: 'http://localhost:3000/signup',
method: "POST",
data: Object.toparams(u)
})
.then(function(response) {
console.log(response);
},
function(response) { // optional
// failed
});
I have created an application in angularjs. The server side is covered by servicestack, I'd like to process a json file that is provided by the servicestack application. To do it I use following code in angularjs:
taskListApp.factory('Fact', function ($resource) {
return $resource("http://localhost:55267/hello?format=json", {},
{
query: {method: 'GET', url: "http://localhost:55267/hello?format=json"},
});
});
However I get the error in console about same origin policy, missing CORS header.
I'm trying to use the default node.js template to create a proxxy server, but I'm clueless about what ports should I use. Any headers?
EDIT:
this is my node.js code, which returns unhandled 'error' error
httpProxy.createServer({
target:'http://localhost:55267'
}).listen(8003);
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
res.end();
}).listen(55267);
Not sure if this will resolve the issue with node but if you want to add CORS Response Headers to the ServiceStack response you need to register the CORS plugin in your AppHost's Configure():
Plugins.Add(new CorsFeature());
If you want to add CORS Response Headers to the ServiceStack response. Please add the below lines:
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
I am developin app in angularjs and nodejs. I want to upload the image using angular and node. Image is sern dusing multipart/form-data. when i send data post request looks like:
{name="customer.pen.13", email="temp#temp.com", website="http://www.tels-tra.com,image:FileList { 0=File, length=1, item=item()}}
I want to get same format in nodejs.But in my node js I got:
{name="customer.pen.13", email="temp#temp.com", website="http://www.tels-tra.com}
Image is missing in request.
Here is my code:
exports.updateExchangeSetup = function(req, res, next) {
var request = require('request');
console.log(req);
console.log(req.body);
}
var headers = {
'headers': {
'User-Agent': 'Super Agent/0.0.1',
'Authorization': 'test',
'Access-Control-Allow-Methods': 'POST, GET, PUT, DELETE, OPTIONS',
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept,Authorization",
'Content-Type': 'application/json'
}
}
As per very short description from you code snippets, I am assuming you are using expressJS on the server side, could you please check the content-type you are handling on express side. I think its application/JSON, and it makes your app disable to understand multipart form data. However I need more details on nodeJs side to answer better.
Everything looks okay as per your snippets. Are you putting your image data on URL?
"http://www.tels-tra.com,image:FileList { 0=File, length=1, item=item()}}"
if this is a string, then it should not get tempered.
Instead of your snippet you could try the following example to upload image and sending other parameters. Maybe this is not the exact solution you are looking for, but it may give you an idea if you are dealing with file upload with extra parameters.
Use ngFileUploadat angular to upload file
Upload.upload({
url: "/api/enpoint/resources",
data: {file: filePath, 'name': "customer.pen.13", 'email'="temp#temp.com"},
headers: {/* your header object here */}
}).then(function (res) {
// do something
});
Node/ExpressJS router
use connect-multiparty middleware to intercept file
var multipartyMiddleware = require('connect-multiparty')();
router.post('/api/enpoint/resources',multipartyMiddleware, ctrl.updateExchangeSetup);
Node/ExpressJS Controller
exports.updateExchangeSetup = function(req, res, next) {
// files will be at: req.files
var imageFile = req.files.file;
var email = req.body.email
}
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 /