I am trying to create a server for an app with a node JS server on AWS(not sure how relevant that is) and I am testing it with Postman. For some reason my hello world function, which is just a GET works perfectly but my POST to create a user keeps giving me this error:
TypeError: Cannot read property 'username' of undefined
at app.get.params.QueueUrl (/home/ec2-user/Outfitr/Server/index.js:40:29)
at Layer.handle [as handle_request] (/home/ec2-user/Outfitr/Server/node_modules/express/lib/router/layer.js:82:5)
at next (/home/ec2-user/Outfitr/Server/node_modules/express/lib/router/route.js:110:13)
at Route.dispatch (/home/ec2-user/Outfitr/Server/node_modules/express/lib/router/route.js:91:3)
at Layer.handle [as handle_request] (/home/ec2-user/Outfitr/Server/node_modules/express/lib/router/layer.js:82:5)
at /home/ec2-user/Outfitr/Server/node_modules/express/lib/router/index.js:267:22
at Function.proto.process_params (/home/ec2-user/Outfitr/Server/node_modules/express/lib/router/index.js:321:12)
at next (/home/ec2-user/Outfitr/Server/node_modules/express/lib/router/index.js:261:10)
at serveStatic (/home/ec2-user/Outfitr/Server/node_modules/express/node_modules/serve-static/index.js:59:14)
at Layer.handle [as handle_request] (/home/ec2-user/Outfitr/Server/node_modules/express/lib/router/layer.js:82:5)
Here is my code:
var express = require("express")
var app = express();
var gm = require("gm");
var fs = require("fs");
var async = require("async");
var s3 = new AWS.S3();
// set the region for the AWS API requests
AWS.config.region = 'us-west-2';
var DAO_QUEUE_URL = 'https://sqs.us-west-2.amazonaws.com/275333356355/DAO-Queue';
app.set('port', (process.env.PORT || 8080 ));
app.use(express.static(__dirname + '/public'));
app.get('/', function(request, response) {
response.send('Hello World (Finally)');
});
app.post('/create_user', function( request, response) {
process.stdout.write("WTF");
create_user( request.body.username, request.body.password, request.body.firstname, request.body.lastname, request.body.gender, request.body.latitude,
request.body.longitude, request.body.description, request.body.city,
request.body.state_province, request.body.country, request.body.email,
request.body.phone_number);
response.send('IT WORKED!');
});
function create_user( username, password, firstname, lastname, is_brand, gender,
description, city, state_province, country, birthday) {
messageBody = {"username":username, "password":password, "firstname": firstname,
"lastname":lastname, "is_brand":is_brand, "gender":gender, "city":city,
"state-province":state_province, "country":country, "birthday":birtyhday};
queueUrl = DAO_QUEUE_URL;
sendSQSMessage( JSON.stringify(messageBody),queueUrl);
}
What could be wrong?
Make sure that you are using the x-www-form-urlencoded tab in postman. I've fallen for that a few times.
Also, make sure you are using the body-parser package.
var express = require("express")
var app = express();
var gm = require("gm");
var fs = require("fs");
var async = require("async");
var bodyParser = require('body-parser');
var s3 = new AWS.S3();
// set the region for the AWS API requests
AWS.config.region = 'us-west-2';
var DAO_QUEUE_URL = 'https://sqs.us-west-2.amazonaws.com/275333356355/DAO-Queue';
// Add the middleware
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.set('port', (process.env.PORT || 8080 ));
app.use(express.static(__dirname + '/public'));
So I think that you are getting the error because there is no middleware setting up a req.body object for you, bodyParser should do the trick.
Related
I'm setting up a new server with node js and the framework express (Version 4.16). I want to route my Rest-Endpoints. In my route.js-file i want to call a function from app.js(my Server), but getting a Typeerror where the function, that i want to call from another file, is not a function.
Error:
TypeError: callFunction.getDataFromDb is not a function
at C:\Users\---\WebstormProjects\pwa_node_server\routes\recipes.js:7:18
at Layer.handle [as handle_request] (C:\Users\---\WebstormProjects\pwa_node_server\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\---\WebstormProjects\pwa_node_server\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\---\WebstormProjects\pwa_node_server\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\---\WebstormProjects\pwa_node_server\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\---\WebstormProjects\pwa_node_server\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\---\WebstormProjects\pwa_node_server\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\---\WebstormProjects\pwa_node_server\node_modules\express\lib\router\index.js:275:10)
at Function.handle (C:\Users\---\WebstormProjects\pwa_node_server\node_modules\express\lib\router\index.js:174:3)
at router (C:\Users\---\WebstormProjects\pwa_node_server\node_modules\express\lib\router\index.js:47:12)
My server:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var axios = require('axios');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var recipesRouter = require('./routes/recipes');
var cors = require('cors');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
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')));
app.use(cors({credentials: true, origin: true}));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/recipes', recipesRouter);
// app.use('/poste-dein-rezept', indexRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
console.log("catch404");
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');
});
var getDataFromDb = function (res) { // This function to call in another file
};
module.export = {
getDataFromDb
};
module.exports = app;
My route-file:
var express = require('express');
========
var router = express.Router();
var callFunction = require('../app');
router.get('/', function(req, res, next) {
console.log('Recipes-Endpoint received Request');
callFunction.getDataFromDb(res);
});
module.exports = router;
I just want to call a function from another file.
You're using module.export. The Correct property name is module.exports, which you are also using.
One way to solve this is:
app.getDataFromDb = getDataFromDb;
module.exports = app;
I'm new to node and having difficulty to get a simple express-handlebar to render a static html page:
require('./config/config');
const path = require('path');
const http = require('http');
const _ = require('lodash');
const express = require('express');
const bodyParser = require('body-parser');
const {ObjectID} = require('mongodb');
const socketIO = require('socket.io');
const exphbs = require('express-handlebars');
var {mongoose} = require('./db/mongoose');
var {Todo} = require('./models/todo');
var {User} = require('./models/user');
var {authenticate} = require('./middleware/authenticate');
var app = express();
var server = http.createServer(app);
var io =socketIO(server);
const port = process.env.PORT;
const publicPath = path.join(__dirname, './public');
app.use(bodyParser.json());
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', exphbs);
app.use(express.static(publicPath));
app.get('/', (req, res) => {
res.render('index');
});
Instead of index.html sitting in views folder, I get this error:
Error: Cannot find module 'function exphbs(config) {
return create(config).engine;
}'
at Function.Module._resolveFilename (module.js:538:15)
at Function.Module._load (module.js:468:25)
at Module.require (module.js:587:17)
at require (internal/module.js:11:18)
at new View (/home/me/nodechatapp/node_modules/express/lib/view.js:81:14)
at Function.render (/home/me/nodechatapp/node_modules/express/lib/application.js:570:12)
at ServerResponse.render (/home/me/nodechatapp/node_modules/express/lib/response.js:1008:7)
at app.get (/home/me/nodechatapp/server.js:37:7)
at Layer.handle [as handle_request] (/home/me/nodechatapp/node_modules/express/lib/router/layer.js:95:5)
at next (/home/me/nodechatapp/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/me/nodechatapp/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/me/nodechatapp/node_modules/express/lib/router/layer.js:95:5)
at /home/me/nodechatapp/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/home/me/nodechatapp/node_modules/express/lib/router/index.js:335:12)
at next (/home/me/nodechatapp/node_modules/express/lib/router/index.js:275:10)
at SendStream.error (/home/me/nodechatapp/node_modules/serve-static/index.js:121:7)
What could be wrong here? How can I fix it?
I'm pretty sure you are missing the app.engine() call in your server set up. Based on the docs you need:
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
You already use app.set for the view engine, but I think you need to call the prior line.
I need to save file into folder and want to get that file's name to save into database using Node.js.
api.js:
var multer = require('multer')
var storage =multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './../uploads');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
exports.saveCardDetails=function(upload.single('image'),req,res){
var name=req.body.name;
var company=req.body.company;
var position=req.body.position;
var mobile=req.body.mobile;
var email=req.body.email;
var landline=req.body.landline;
var url=req.body.url;
var postcode=req.body.postcode;
var address=req.body.address;
var image=req.body.image;
var userid=req.body.userid;
var profiletext=req.body.profile;
var biography=req.body.biography;
var token_id=req.body.token_id;
console.log('request',req);
}
server.js:
var express=require('express');
var morgan = require('morgan');
var http=require('http');
var bodyParser= require('body-parser');
var methodOverride = require('method-override');
var mongo = require('mongojs');
var session = require('express-session');
var app=module.exports=express();
var server=http.Server(app);
var port=8989;
var admin=require('./route/route.js');
var api=require('./api/api.js');
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.urlencoded({ extended: false })) // parse application/x-www-form-urlencoded
app.use(bodyParser.json()) // parse application/json
app.post('/api/users/save-card-details',api.saveCardDetails);
After this I am getting the following error:
POST /api/users/save-card-details 413 13.277 ms - 1120
Error: request entity too large
at readStream (/opt/lampp/htdocs/heroku/FGDP/node_modules/raw-body/index.js:196:17)
at getRawBody (/opt/lampp/htdocs/heroku/FGDP/node_modules/raw-body/index.js:106:12)
at read (/opt/lampp/htdocs/heroku/FGDP/node_modules/body-parser/lib/read.js:76:3)
at urlencodedParser (/opt/lampp/htdocs/heroku/FGDP/node_modules/body-parser/lib/types/urlencoded.js:115:5)
at Layer.handle [as handle_request] (/opt/lampp/htdocs/heroku/FGDP/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/opt/lampp/htdocs/heroku/FGDP/node_modules/express/lib/router/index.js:312:13)
at /opt/lampp/htdocs/heroku/FGDP/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/opt/lampp/htdocs/heroku/FGDP/node_modules/express/lib/router/index.js:330:12)
at next (/opt/lampp/htdocs/heroku/FGDP/node_modules/express/lib/router/index.js:271:10)
at logger (/opt/lampp/htdocs/heroku/FGDP/node_modules/morgan/index.js:144:5)
Here I am getting the image and need to save into folder. After saving into folder I need saved file name into exports.saveCardDetails function. My folder structure is given below.
--> api/api.js
--> upload
I am using multer npm package for this.
Looks like multer is failing for large file size.
Try setting the fieldSize variable in multer config like this -
multer({
storage: storage,
limits: { fileSize: maxSize }
})
You can find these settings here - https://www.npmjs.com/package/multer (search for limit).
Hope this helps!
I have this route:
var express = require('express');
var multer = require('multer');
const upload = multer();
module.exports = (function () {
var router = express.Router();
router.post('/avatar/:user', upload.single('avatar'), function (req, res, next) {
var file = req.file; // file passed from client
var meta = req.body; // all other values passed from the client, like name, etc..
console.log(file);
console.log(meta);
res.json({
success: true
});
});
return router;
})();
And when I try to post to it using Postman with header 'Content-Type : application/x-www-form-urlencoded' and in body 'form-data' File (image), the express crashes with error:
Error
at readStream (F:\Web\WorkoutFocus_Server\node_modules\raw-body\index.js:196
:17)
at getRawBody (F:\Web\WorkoutFocus_Server\node_modules\raw-body\index.js:106
:12)
at read (F:\Web\WorkoutFocus_Server\node_modules\body-parser\lib\read.js:76:
3)
at urlencodedParser (F:\Web\WorkoutFocus_Server\node_modules\body-parser\lib
\types\urlencoded.js:115:5)
at Layer.handle [as handle_request] (F:\Web\WorkoutFocus_Server\node_modules
\express\lib\router\layer.js:95:5)
at trim_prefix (F:\Web\WorkoutFocus_Server\node_modules\express\lib\router\i
ndex.js:317:13)
at F:\Web\WorkoutFocus_Server\node_modules\express\lib\router\index.js:284:7
at Function.process_params (F:\Web\WorkoutFocus_Server\node_modules\express\
lib\router\index.js:335:12)
at next (F:\Web\WorkoutFocus_Server\node_modules\express\lib\router\index.js
:275:10)
at jsonParser (F:\Web\WorkoutFocus_Server\node_modules\body-parser\lib\types
\json.js:112:7)
at Layer.handle [as handle_request] (F:\Web\WorkoutFocus_Server\node_modules
\express\lib\router\layer.js:95:5)
at trim_prefix (F:\Web\WorkoutFocus_Server\node_modules\express\lib\router\i
ndex.js:317:13)
at F:\Web\WorkoutFocus_Server\node_modules\express\lib\router\index.js:284:7
at Function.process_params (F:\Web\WorkoutFocus_Server\node_modules\express\
lib\router\index.js:335:12)
at next (F:\Web\WorkoutFocus_Server\node_modules\express\lib\router\index.js
:275:10)
at cors (F:\Web\WorkoutFocus_Server\node_modules\cors\lib\index.js:185:7)
Does this have something to do with file size or multipart/form-data perhaps?
I tried to set the bodyparser.json limit to '50mb', but no difference.
When I post to /insertUser and it schema.saveUser(req) it doesn't find the correct data. I am using node-inspector and it can't find my post data. I have also tried req.body and it finds nothing. I am sending a json
var express = require('express');
var bodyParser = require('body-parser');
var schema = require("./schemas");
var app = express();
app.get('/hello.txt', function(req, res){
res.send('Hello World2');
});
app.post('/insertUser', function(req, res){
console.log("Request handler 'insertUser' was called.");
//console.log(req.body);
schema.saveUser(req);
response.writeHead(200, {"Content-Type": "text/plain"});
res.send("You've sent the text: " + req);
response.write("The following data has been saved to the database: " + jsonString);
res.end();
});
var server = app.listen(8888, function() {
console.log('Listening on port %d', server.address().port);
});
function saveUser(postData){
var jsonObj = JSON.parse(postData);
var newUser = new User({
name: jsonObj.name,
email: jsonObj.email,
photoURL: jsonObj.photourl,
groups: jsonObj.groups
});
newUser.save(function(err, newUser) {
if (err) return console.error(err);
console.dir(newUser);
});
}
edit:
SyntaxError: Unexpected token o
at Object.parse (native)
at Object.saveUser (schemas.js:42:22)
at Object.handle (server.js:25:9)
at next_layer (route.js:103:13)
at Route.dispatch (route.js:107:5)
at c (index.js:195:24)
at Function.proto.process_params (index.js:251:12)
at next (index.js:189:19)
at next (index.js:166:38)
at Layer.urlencodedParser [as handle] (index.js:70:44)
In the client
Cannot GET /insertUser means this is a GET route which is called by the browser when clicking on a link or entering the page URL.
But you specified app.post('/insertUser'... which means that the route will be called only when using the POST method (used when submitting forms for instance, NEVER when clicking on links)
If this is the result of a form, don't forget to specify the method (<form method="post">). Same for ajax calls.
If you want to test in dev mode you can use Postman on chrome to easily call POST routes. If you don't have chrome use curl.
Back-end
Express body parser isn't included in express 4.0 so you need to install it then use it:
var express = require('express');
var bodyParser = require('body-parser');
var schema = require("./schemas");
var app = express();
app.use(bodyParser());
app.get('/hello.txt', function(req, res){
res.send('Hello World2');
});
Then you can use req.body
I think in Express 4 you need to use router object instead of app to define the routes... Something like this:
var express = require('express');
var bodyParser = require('body-parser');
var schema = require("./schemas");
var app = express();
var router = express.Router();
router.get('/hello.txt', function(req, res){
res.send('Hello World2');
});
router.post('/insertUser', function(req, res){
console.log("Request handler 'insertUser' was called.");
});
...