I have built few rest API on server and calling them from other domain the Get request is working fine but I am facing an issue in calling the POST request.
I am unable to receive data on server send by the clients.
Server Code:
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
//var fn = require('fn')
var app = express();
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
// intercept OPTIONS method
if ('OPTIONS' === req.method) {
res.send(200);
}
else {
next();
}
};
// all environments
app.set('port', process.env.PORT || 3000);
app.use(allowCrossDomain);
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.post('/user', user.saveUser);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
exports.saveUser = function(req, res) {
var key = req.body.key; //fb,twitter,web
var userData = req.body.userData;
var result = checkUser(userData,key);
}
Clients code where the request is made :
var data = { key: 'web', userData: userData }
$.ajax({
method: "POST",
//contentType: 'application/json',
url: "www.acbd.com/user",
//url:"http://prayable-21641.onmodulus.net/user",
data: data,
crossDomain: true,
dataType: "json"
}).success(function (data, textstatus) {
// this callback will be called asynchronously
// when the response is available
console.log(data)
console.log(textstatus)
}).error(function (data, textstatus) {
console.log(data)
console.log(textstatus)
// called asynchronously if an error occurs
// or server returns response with an error status.
});
I am unable to get key or userData on server, it say they are not defined:
TypeError: Cannot read property 'key' of undefined
You forgot to require and use the body-parser middleware module.
And also, why is content-type commented out? You need it
Server code should look like this:
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
//var fn = require('fn')
//requiring body-parser
var bodyParser = require('body-parser');
var app = express();
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
// intercept OPTIONS method
if ('OPTIONS' === req.method) {
res.send(200);
}
else {
next();
}
};
// all environments
app.set('port', process.env.PORT || 3000);
app.use(allowCrossDomain);
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
// using body-parser
app.use(bodyParser());
app.post('/user', user.saveUser);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
also, don't forget to npm install it:
npm install body-parser
//REquire the body parser, make sure you install it using
npm install body-parser
var bodyParser = require('body-parser');
and then use it
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
Hope that helps
Related
I am getting this error when trying to do a get request from my vue app. I am running an express Node.js express app that is connected to my local Mysql server. I already have the headers set to allow my Vue app running on localhost:8081 to access the node server but I'm still getting the error. I have CORS installed on node and vue. My teamates are using the same code I am and not getting this but I am still getting the CORS errors(image for errors). Any help would be greatly appreciated. Thanks!
app.js for my node server
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const cors = require('cors');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/courses');
var app = express();
var corsOptions = {
origin: 'http://localhost:8081',
}
app.use(cors(corsOptions));
app.options('*', cors());
app.get('http://localhost:8081', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'})
})
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
var mysql = require("mysql");
app.use(function(req, res, next){
res.locals.connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'course'
})
res.locals.connection.connect();
next();
});
app.use('/api', indexRouter);
app.use('/api/courses', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
course-services.js for rest requests to my node app
import axios from "axios";
var baseurl = "";
if (process.env.NODE_ENV === "development") {
baseurl = "http://localhost/api/";
} else {
baseurl = "/api/";
}
const apiClient = axios.create({
baseURL: baseurl,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
"Access-Control-Allow-Origin" : "*",
crossDomain: true
},
transformRequest: (data, headers) => {
let token = localStorage.getItem("token");
let authHeader = "";
if (token != null && token != "") authHeader = "Bearer " + token;
headers.common["Authorization"] = authHeader;
return JSON.stringify(data);
},
transformResponse: function(data) {
data = JSON.parse(data);
if (!data.success && data.code == "expired-session") {
localStorage.deleteItem("token");
}
return data;
}
});
export default {
getCourses() {
return apiClient.get("courses");
},
getCourse(id) {
return apiClient.get("courses/" + id);
},
addCourse(course) {
return apiClient.post("courses", course);
},
updateCourse(courseId, course) {
return apiClient.put("courses/" + courseId, course);
},
deleteCourse(courseId) {
return apiClient.delete("courses/" + courseId);
},
};
I don't know why your setting headers many times if you use cors() module you don't have to set header again
var corsOptions = {
origin: 'http://localhost:8081',
}
app.use(cors(corsOptions));
app.options('*', cors());
This route is enough and use as middleware for certain routes And at last, only fetch from http://localhost:8081 don't fetch from any random chrome dev console which will violent cors policy as you setting a specific port and domain as localhost:8081 and please check that you using 127.0.0.1:8081 if so it will again throw an error
only use http://localhost:8081
If you use 127.0.0.1 will not work cause the host don't match
Hope this will help with your problem
You have a custom header in your request:
"X-Requested-With": "XMLHttpRequest",
Either you need to remove it from request header or you need to support it in your server response header by setting it in 'Access-Control-Allow-Headers' :
if you think there might be more custom headers simply set it to *
res.setHeader('Access-Control-Allow-Headers', '*');
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
I would send data from angular to Express.
in my service ;
sendtext(text): Observable<any> {
console.log(text);
return this.http.post<string>(this.url, text, httpOptions);
}
I configure headers
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded'
})
my console.log(text) prints me the right text typed in an input.
In my server side I have created my server.js file
var http = require("http");
var admin = require('firebase-admin');
var firebase = require("firebase");
var express = require("express");
var app = express();
var routerProj = require("./routes/routes");
var bodyParser = require("body-parser");
var port = process.env.app_port || 8080; // set our port
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var server = app.listen(port);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,*");
next();
});
var config = {
......configuration...
};
firebase.initializeApp(config);
var serviceAccount = require("./ServiceAcountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://datatable-18f93.firebaseio.com"
});
app.use("/v1", routerProj);
//Create HTTP server and listen on port 8000 for requests
// Print URL for accessing server
console.log("Server running at http://127.0.0.1:8080/");
And I have created my router file:
var express = require("express"); // call express
var router = express.Router(); // get an instance of the express Router
var admin = require("firebase-admin");
router
.route("/")
.post(function (req, res, err) {
console.log(req.body);
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.push(
{
"text": req.body
}
);
});
module.exports = router;
Here console.log(req.body) prints an empty object {}
Is it because of the headers ? if yes how can I configure them ? I have already tried'Content-Type': 'application/json', and without headers, no result.
I have the following file: (auth.js)
module.exports = function (express, mongoose, router) {
router.route('/setup')
.get(function (req, res) {
var salt = bcrypt.genSaltSync(10);
var hashed = bcrypt.hashSync(req.query.password, salt);
// create a sample user
mongoose.models.playlist.create({username: 'Hieratic', password: hashed}, function (err, item) {
if (err) throw err;
console.log('User saved successfully');
res.json({ success: true });
});
});
return router;
};
And the current server file: (server.js)
"use strict";
var url = require('url');
var express = require('express');
var bodyParser = require('body-parser');
var fs = require('fs');
var crypto = require('crypto');
//npm install request
var request = require('request');
var config = require('./config/access.json');
var admin = require("firebase-admin");
var fireBaseConfig = require('./config/firebase.config.json');
var mongoose = require('mongoose');
var MongoClient = require('mongodb').MongoClient;
var mongodbConfig = require('./config/database.json');
var exec = require('child-process-promise').exec;
var app = express();
/**
* Schemas
*/
var UserModel = require('./schemas/user.schema.js')(mongoose);
var PlayListModel = require('./schemas/playlist.schema.js')(mongoose);
app.use(function (req, res, next) {
// CORS headers
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, x-access-token, Cache-Control, Pragma"
);
next();
});
var router = express.Router();
app.use(bodyParser.json({limit: '4mb'}));
app.use(bodyParser.urlencoded({
extended: true,
limit: '4mb'
}));
if (mongodbConfig.username && mongodbConfig.password) {
mongoose.connect(`mongodb://${mongodbConfig.username}:${mongodbConfig.password}#${mongodbConfig.host}:${mongodbConfig.port}/${mongodbConfig.database}`);
}
else {
mongoose.connect(`mongodb://${mongodbConfig.host}:${mongodbConfig.port}/${mongodbConfig.database}`);
}
process.on('disconnect', function () {
// If mongodb connection is not terminated child process never dies
mongoose.disconnect();
});
require('./auth.js')(express, mongoose, router);
var port = 51000;
app.listen(port);
console.log('Magic happens at http://localhost:' + port);
When i attempt to access the /setup route it does hit the server however it throws an html page:
(http://localhost:51000/setup):
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /setup</pre>
</body>
Can anyone see what ive done wrong?
You have created router, but not registered it as a middleware:
var router = express.Router();
require('./auth.js')(express, mongoose, router);
app.use(router);
Refer to Cannot GET / Nodejs Error
You have no route set up.
Serve your page like this:
app.get('/', function (req, res) {
res.render('index', {});
});
I have a node server and an angularJS app.
I have a route to get informations about one record.
The route is '/pacientes/:id'
When I request data from that route i am getting an error.
What am I doing wrong?
//error:
Error: Can't set headers after they are sent.
at ServerResponse.setHeader (_http_outgoing.js:367:11)
at ServerResponse.header (C:\nodeapp\cloudapp\node_modules\express\lib\respo
nse.js:719:10)
at ServerResponse.send (C:\nodeapp\cloudapp\node_modules\express\lib\respons
e.js:164:12)
at ServerResponse.json (C:\nodeapp\cloudapp\node_modules\express\lib\respons
e.js:250:15)
at C:\nodeapp\cloudapp\server.js:973:10
at Array.forEach (native)
at C:\nodeapp\cloudapp\server.js:971:13
at Layer.handle [as handle_request] (C:\nodeapp\cloudapp\node_modules\expres
s\lib\router\layer.js:95:5)
at next (C:\nodeapp\cloudapp\node_modules\express\lib\router\route.js:131:13
)
at Route.dispatch (C:\nodeapp\cloudapp\node_modules\express\lib\router\route
.js:112:3)
Here is app controller:
angular.module("clinang").controller('ProcedimentosCtrl',['$scope','$http','$state',function($scope,$http,$state){
$scope.modelo={}
var tipoId=$state.params.tipoId;
if (tipoId) {
$http.get('/pacientes/' + tipoId).then(function(response){
$scope.modelo=response.data;
}, function(error){
console.log(error)
});
}
}]);
node - server.js
var express = require('express');
var bodyParser = require('body-parser');
var jwt = require('jsonwebtoken');
var expressJwt = require('express-jwt');
var path = require('path');
var app = express();
// Define the port to run on
app.set('port', process.env.port || 80);
app.use(bodyParser.json());
app.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
var pacientes=[
{id:1, nome:'Joao'},
{id:2, nome:'Maria'}
];
app.get('/pacientes/:id', function(req, res) {
pacientes.forEach(function (paciente) {
if (paciente.id == req.params.id) {
res.json(paciente);
return;
}
});
res.status(404).end();
});
//The 404 Route (ALWAYS Keep this as the last route)
app.get('*', function(req, res){
res.status(404).end();
});
// Listen for requests
var server = app.listen(app.get('port'), function() {
var port = server.address().port;
console.log('Magic happens on port ' + port);
});
You are trying to send multiple responses to the same request from the client, but you can only send it once.
Change this:
pacientes.forEach(function (paciente) {
if (paciente.id == req.params.id) {
res.json(paciente);
return;
}
});
To this:
var result;
pacientes.forEach(function (paciente) {
if (paciente.id == req.params.id) {
result = paciente;
}
});
if (result !== undefined) {
res.json(result);
} else {
res.sendStatus(404);
}
The functions res.json, and res.sendStatus sets the header and the response's body, and call the .end() function after that, so you don't need to do it.
I'm trying to use nodejs as a layer between my public website and a server on the inside of our network.
I'm using express.js to create a simple REST api. The API endpoint should trigger a request call to a webservice, and return the result.
But the request call inside my .get() function doesn't do anything.
I want to return the result from the nested call to be returned.
Code:
// Dependencies
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
//Port
var port = process.env.PORT || 8080;
// Express
var app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
// Routes
app.get('/invoice', function(req, res){
res.send('Express is workiung on IISNode')
});
app.get('/invoice/api/costumer=:customerId&invoice=:invoiceId', function(req, res){
res.send('Customer ID: ' + req.params.customerId + ' Invoice ID: '+ req.params.invoiceId)
var url = 'http://xxx/invapp/getinvoice?company='+req.params.customerId+'S&customerno=13968&invoiceno='+req.params.invoiceId+'';
request('http://www.google.com', function (error, response, body) {
res.send(body);
})
});
// Start server
app.listen(port);
console.log("API is running on port " + port);
Any suggestions?
You can write in this way
// Dependencies
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
//Port
var port = process.env.PORT || 8080;
// Express
var app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
// Routes
app.get('/invoice', function(req, res){
res.send('Express is working')
});
app.get('/invoice/api/costumer=:customerId&invoice=:invoiceId', function(req, res){
var url = 'http://xxx/invapp/getinvoice?company='+req.params.customerId+'S&customerno=13968&invoiceno='+req.params.invoiceId+'';
request(url, function (error, response, body) {
var data={
body:body,
customerID:req.params.customerId,
invoiceID:req.params.invoiceId
};
res.send(data);
});
});
// Start server
app.listen(port);
console.log("API is running on port " + port);
Please find the snippet I am using. Hope this helps for you as well.
var body="";
function callyourservice(customerId,invoiceId,callback) {
var options = {
uri : url + 'costumer=:customerId&invoice=:invoiceId',
method : 'GET'
}
request(options, function (error, response, body) {
console.log(response);
if (!error && response.statusCode == 200) {
res = body;
}
else {
res = 'Not Found';
}
callback(res);
});
}
callyourservice("customerId value","invoiceId value", function(resp){
body=JSON.stringify(resp);;
});
You can write callyourservice inside a get method from client like
app.get('/'){
}
You can try doing it the node way using pipe
var http = require('http');
http.createServer(function(request, response) {
var proxy = http.createClient(9000, 'localhost')
var proxyRequest = proxy.request(request.method, request.url, request.headers);
proxyRequest.on('response', function (proxyResponse) {
proxyResponse.pipe(response);
});
request.pipe(proxyRequest);
}).listen(8080);
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied to port 9000!' + '\n' + JSON.stringify(req.headers, true, 2));
res.end();
}).listen(9000);
You can find the reference here