Background
I tried to use angular-file-upload module to upload the images from localhost:3000 to localhost:9000 which I assume they are different domain and should belongs to CORS (Cross-origin resource sharing). I see this module supports CORS. I also follow the express server setup that they recommend here. but still I can not see anything in either the body object or files object in the request.
Questions
Since this module supports CORS, why seems still not work.
Should I explicitly tell node server to set up something in the responds header like
(Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Allow-Headers)
and how to do that in express ?
res.setHeader(.....) ?
How can I fix this problem?
Code
/* ***************************** ANGULAR ***************************************** */
var myApp = angular.module('myApp', ['angularFileUpload']);
myApp.controller('MyCtrl', [ '$scope', '$upload', function($scope, $upload) {
$scope.$watch('files', function(files) {
if (files) {
for (var i = 0; i < $scope.files.length; i++) {
var file = $scope.files[i];
$scope.upload = $upload.upload({
url: 'http://localhost:9000/upload/',
data: {myObj: $scope.myModelObj},
file: file,
}).progress(function(evt) {
console.log('progress: ' + parseInt(100.0 * evt.loaded / evt.total) + '% file :'+ evt.config.file.name);
}).success(function(data, status, headers, config) {
console.log('file ' + config.file.name + 'is uploaded successfully. Response: ' + data);
});
}
}
});
}]);
/* ***************************** SERVER SIDE ***************************************** */
var multipart = require('connect-multiparty');
var express = require('express');
var bodyParser = require('body-parser')
var _ = require('underscore');
var path = require('path');
var app = express();
app.use(multipart({
uploadDir: './uploads'
}));
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
app.use(function (req, res, next) {
console.log(req.files); // {} why ????
console.log(req.body); // {} why ????
});
app.listen(9000);
Actually, I figure it out by using a middleware called cors. so the server code looks like this
var multipart = require('connect-multiparty');
var express = require('express');
var cors = require('cors');
var bodyParser = require('body-parser')
var app = express();
app.use(multipart({
uploadDir: './uploads'
}));
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
// cors middleware
app.use(cors());
app.use(function (req, res, next) {
console.log(req.files); // then there is something : )
next();
});
app.listen(9000);
Related
NodeJS File server.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var morgan = require('morgan');
var mongoose = require('mongoose');
var moment = require('moment');
var http = require('http');
var jwt = require('jsonwebtoken');
var config = require('./config');
var User = require('./app/models/user');
var port = process.env.PORT || 8080;
mongoose.connect(config.database);
app.set('superSecret', config.secret);
app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
app.post('/onboardAuthentication', function(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
res.setHeader('contentType', 'application/x-www-form-urlencoded;charset=utf-8;');
res.json(req.body);
});
var server = http.createServer(app);
server.listen(port);
console.log('Magic happens at http://localhost:' + port);
Angular API Hit Code where Front side API hit
var serviceRoot='http://localhost:8080/onboardAuthentication';
var deferred=$q.defer();
var req = {
method: 'POST',
url: serviceRoot,
data: { key: 'value' },
contentType: 'application/x-www-form-urlencoded;charset=utf-8;'
};
$http(req).then(goodResponse,badResponse);
return deferred.promise;
function goodResponse(response)
{
console.log("Good response");
console.log(response);
}
function badResponse(response)
{
console.log("Bad response");
console.log(response.data);
}
It print result in this formate, it make post data as key and value is blank, but i want to access post data in json format using body-parsar node js.
{"key":"value"}: ""
If you want to send simple text/ ASCII data, then x-www-form-urlencoded will work,
by default angular will send application/json to the server.
var req = {
method: 'POST',
url: serviceRoot,
data: { key: 'value' },
// comment this line, you don't need it
//contentType: 'application/x-www-form-urlencoded;charset=utf-8;'
};
My angular client has a postrequest that looks like this:
$http.post("api/login/", { foo: 'bar' }).success(function(data, status) {
$scope.hello = data;
})
The server is implemented in express:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var cors = require('cors');
var express = require('express');
var request = require('request');
app.set('port', process.env.PORT || 3000);
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/api/login', function(req, res) {
res.send({message:'hello from api/login'});
});
app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
When I click 'login' I get an error:
Status Code:405 Method Not Allowed
How can I resolve this error?
github:https://github.com/dimitri-a/oauth_stuff
I'am trying to create a restful api but I need to use an external api quandl to build my api, when i try to use my api from the client(built in angularjs) i get a 500 internal server error and No default engine was specified and no extension was provided in command line. i know my api work cause i tested it with postman, its just not working from the client.
I tried looking at this post : express js 4 how to serve json results without rendering any views /css but it wasnt helpful.
module.exports = function(io){
var q = require('q');
var request = require('request');
var mongoose = require('mongoose');
var Stock = mongoose.model('Stock');
var base_url = "https://www.quandl.com/api/v3/datasets/WIKI/";
var dotjson = ".json"
var apiKey = "?api_key=" + process.env.quandl_apiKey;
function sendJsonResponse(res,status,content){
res.status(status);
res.json(content);
}
// get stock data using quandl api
function stockData(name){
var deferred = q.defer();
var d = new Date();
var year = d.getFullYear();
var month = d.getMonth() + 1;
var date = d.getDate();
request({
url: base_url + name + dotjson + apiKey,
qs:{
start_date:(year-1) + '-' + month + '-' + date,
end_date:year + '-' + month + '-' + date
}
},function(error,response,body){
if(error){
deferred.reject('Error: ' + error);
}else if(response.statusCode !== 200){
deferred.reject('Invalid Status Code: ' + response.statusCode);
}else{
deferred.resolve(body);
}
})
return deferred.promise;
}
// get stock data that is stored in database
function getStockInDatabase(req,res){
Stock.find({},function(err,stock){
if(err){
sendJsonResponse(res,404,err);
} else {
sendJsonResponse(res,200,stock);
}
})
}
// create stock data to be stored in database
function createStockData(req,res){
var stockDatas;
stockData(req.body.name.toUpperCase())
.then(function(stock){
stockDatas = JSON.parse(stock);
Stock.create({
name:stockDatas.dataset.name,
symbol:stockDatas.dataset.dataset_code
},function(err,stk){
if(err){
sendJsonResponse(res,400,err)
}else{
sendJsonResponse(res,201,stk);
io.emit('stock',stockDatas);
}
})
})
.catch(function(err){
sendJsonResponse(res,404,err);
})
}
// delete stock data in database
function deleteStockData(req,res){
Stock
.findByIdAndRemove(req.body._id)
.exec(function(err,stock){
if(err){
sendJsonResponse(res,404,err);
}else {
sendJsonResponse(res,204,null);
}
})
}
return {
getStockInDatabase:getStockInDatabase,
createStockData:createStockData,
deleteStockData:deleteStockData
}
}
angular service to use api:
(function(){
'use strict'
angular
.module('app.common')
.factory('stockService',stockService);
stockService.$inject = ['$http'];
function stockService($http){
function getStock(){
return $http.get('/api/stocks');
}
function getStockInDatabase(){
return $http.get('api/stocks/database');
}
function createStock(data){
return $http.post('/api/stocks',data);
}
function deleteStock(data){
return $http.delete('/api/stocks',data);
}
return{
getStockInDatabase:getStockInDatabase,
createStock:createStock,
deleteStock:deleteStock
}
}
})()
app.js configuration
require('dotenv').load();
var express = require('express');
var socketio = require('socket.io');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var io = socketio();
require('./api/models/db');
var app = express();
app.io = io;
var apiRoute = require('./api/routes/index')(io);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'client')));
app.use('/api', apiRoute);
app.use(function(req, res) {
res.sendFile(path.join(__dirname, 'client', 'index.html'));
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500).send({
message: err.message,
error: {}
})
});
module.exports = app;
No default engine specified error comes when you have not specified any content serving engine in express.. for you views or html files.
Try using
app.set('views', 'html page location');
app.set('view engine', 'jade');
You might have to additionally require jade.
I'm new to express and i'm trying to save some data in session and then retrieve it in another query. My client app is an AngularJS app.
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var cookieSession = require('cookie-session');
app.use(cookieParser());
app.use(cookieSession({
name: 'session',
keys: ['mySecret']
}));
app.use(bodyParser.json());
When retrieving session, it's always an empty object
{}
What can be the cause ?
Thank you !
EDIT
This my app.js now
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
//var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var cookieSession = require('cookie-session');
var methodOverride = require('method-override');
var session = require('express-session');
//Services
var routes = require('./routes/index');
var users = require('./routes/users');
var typesOperateurs = require('./routes/typesOperateurs');
var domains = require('./routes/domains');
var categories = require('./routes/categories');
var donnees = require('./routes/donnees');
var arcepData = require('./routes/arcepData');
var generalData = require('./routes/generalData');
var app = express();
var properties = require('./configs/properties');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//app.use(cookieParser('arcepSecret'));
/*app.use(cookieSession({
name: 'session',
keys: ['arcepSecret'],
httpOnly : false
}));*/
app.use(session({
secret:'arcepSecret',
resave: true,
saveUninitialized: true,
name : 'arcep.sid'
}));
app.use(bodyParser.json());
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', properties.clientHost);
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
//app.use(methodOverride);
//app.use(express.static(path.join(__dirname, 'public')));
//storing models
app.use(function(req, res, next) {
req.models = app.models;
next();
});
// Routes
app.use('/arcep', routes);
app.use('/arcep/users', users);
app.use('/arcep/typesOperateurs', typesOperateurs);
app.use('/arcep/domains', domains);
app.use('/arcep/categories', categories);
app.use('/arcep/donnees', donnees);
app.use('/arcep/arcep_data', arcepData);
app.use('/arcep/general_data', generalData);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
I'm populating the session inside
router.post('/link1', function (req, res, next) {
req.session.name = 'khalil';
});
And i'm trying to retrieve it inside
router.post('/link2', function (req, res, next) {
console.log(req.session);
})
EDIT2
I found that if invoke the services from the browser directly, everything goes fine, but when trying that from the client app wich is an angular app hosted on a tomcat server, the problem occures.
The solution is to allow credentials in the angular app.
.config(function ($routeProvider, $httpProvider) {
$httpProvider.defaults.withCredentials = true;
$http doesn't send cookie in Requests
I suggest you import the express-session (https://github.com/expressjs/session).
Try this:
var expressSession = require('express-session');
app.use(expressSession({secret:'somesecrettokenhere'}));
After to set and get the values in session:
app.get('/', function(req, res) {
req.session.hello_message = "Hello world";
res.send(req.session.hello_message);
});
The session variable hello_message will be available at everywhere in the application.
Follow full example.
1) Create file called confi.json in the same level of the app.js:
{
"SECRET": "Test",
"KEY": "test.sid",
"MAX_AGE": {
"maxAge": 3600000
}
}
2) Alter the app.js for this:
var express = require('express')
, cfg = require('./config.json')
, load = require('express-load')
, bodyParser = require('body-parser')
, compression = require('compression')
, methodOverride = require('method-override')
, expressSession = require('express-session')
, cookieParser = require('cookie-parser')
, app = express()
, cookie = cookieParser(cfg.SECRET);
app.use(compression());
app.use(cookie);
app.use(expressSession({
secret: cfg.SECRET,
name: cfg.KEY,
resave: false,
saveUninitialized: false,
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(methodOverride('_method'));
app.get('/', function(req, res) {
req.session.hello_message = "Hello world";
console.log(req.session.hello_message);
});
app.listen(5000, function(){
console.log("Test running");
});
module.exports = app;
3) Update the package.js:
{
"name": "test",
"version": "0.0.1",
"description": "test",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"body-parser": "~1.12.0",
"cookie-parser": "~1.3.4",
"debug": "~2.1.1",
"ejs": "~2.3.1",
"express": "~4.12.2",
"express-load": "1.1.8",
"morgan": "~1.5.1",
"serve-favicon": "~2.2.0"
}
}
4) Run npm update --save for save the dependencies.
5) Open the browser: localhost:5000 and the message should appear in the console.
As noted in the answer to a related SO question, this can occur if you're using fetch to get data from your server but you don't pass in the credentials option:
fetch('/link2', {
method: 'POST',
credentials: 'same-origin' // <- this is mandatory to deal with cookies
})
Cookies won't be passed to the server unless you include this option.
I'm inexperienced in backend and working with Node and trying to set up an $http POST request to send a form to Express. Each time I make the request, my callback data is null. Perhaps my Express routes are not configured correctly? I'm using Angular to communicate with Express/Node to send an email through nodemailer (which I've already properly configured).
Here is my $http POST request:
client/service/emailer/emailer.js
angular.module('public').factory('EmailerService',function($http) {
return {
postEmail: function(emailData, callback) {
console.log('call http with object', emailData);
$http({
method: 'POST',
url: 'http://my-website.com/server/routes/emailer',
data: emailData,
headers: { "Content-Type": "application/json" },
responseType: 'json'
}).success(function(data, status, headers, config) {
console.log('success', data, status);
}).error(function(data, status, headers, config) {
console.log('error', data, status);
}).catch(function(error){
console.log('catch', error);
});
}
};
});
Here is my server side Express configuration:
server/routes/emailer.js
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var logger = require('morgan');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(logger('dev'));
app.post('/emailer', function(req,res) {
// NOTHING LOGS HERE
console.log(res, req, req.body, res.body);
});
module.exports = app;
Nothing logs to the console here, and the error handling on the $http request returns this:
emailer.js:4 call http with Object {email: "asdf"}
angular.js:8632 OPTIONS http://matt-mcdaniel.com/server/routes/emailer net::ERR_CONNECTION_TIMED_OUT(anonymous function) # angular.js:8632sendReq # angular.js:8426$get.serverRequest # angular.js:8146deferred.promise.then.wrappedCallback # angular.js:11682deferred.promise.then.wrappedCallback # angular.js:11682(anonymous function) # angular.js:11768$get.Scope.$eval # angular.js:12811$get.Scope.$digest # angular.js:12623$get.Scope.$apply # angular.js:12915(anonymous function) # angular.js:19264jQuery.event.dispatch # jquery.js:4676jQuery.event.add.elemData.handle # jquery.js:4360
emailer.js:14 error null 0
emailer.js:16 catch Object {data: null, status: 0, headers: function, config: Object, statusText: ""}
For good measure, and since I'm new to learning Express, I'll post my server side app.js.
server/app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var compression = require('compression');
var routes = require('./routes/index');
var contact = require('./routes/emailer');
var app = express();
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(compression());
app.use(require('connect-livereload')({
port: 35729,
ignore: ['.js']
}));
/** Development Settings */
if (app.get('env') === 'development') {
// This will change in production since we'll be using the dist folder
app.use(express.static(path.join(__dirname, '../client')));
// This covers serving up the index page
// app.use(express.static(path.join(__dirname, '../client/.tmp')));
// app.use(express.static(path.join(__dirname, '../client/public')));
// Error Handling
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
/**
* Production Settings
*/
if (app.get('env') === 'production') {
// changes it to use the optimized version for production
app.use(express.static(path.join(__dirname, '/dist')));
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
}
module.exports = app;
app.use(function(req, res) {
res.sendfile(__dirname + '/dist/index.html');
});
Here is my file Structure:
You've definitely got some problems in your emailer.js route. You should only have routing logic there, you shouldn't be recreating your express app. Express gives you a Router object to make this easy. For example, your emailer.js could look like this:
module.exports = express.Router()
.post('/emailer', function(req,res) {
console.log(res, req, req.body, res.body);
res.json({hello:'world'});
});
And you can map this route in server/app.js like so:
var emailer = require('./routes/emailer');
// ...After all app.use statements, but *before* your error handlers
app.use('/server/routes', emailer);