Can't use Express to send data back to client more than once - ajax

In my app, I send a post request to the server with data containing a CSV file:
$.ajax({
type:"POST",
contentType: "application/json",
url:"/",
data: JSON.stringify({fileData:My_CSV_FILE}),
success: function(csvJson) {
console.log('in the done block!');
//can use csvJson in this handler
});
});
Note: I'm posting to the home route, and I am able to get a response with the data converted from the server. The problem is that whether I run on localhost or Heroku, I am only able to trigger the POST request once, then I have to restart the server (even if I refresh the page). So I know the issue is with my route somewhere:
UPDATED TO INCLUDE FULL SERVER FILE:
'use strict';
const express = require('express');
const csvtojson = require('csvtojson');
const PORT = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const Converter = require('csvtojson').Converter;
var converter = new Converter({});
let app = express();
app.use(bodyParser.json({limit: '300kb'}));
app.use(express.static(__dirname +'/public'));
app.post('/',function(req,res) {
var csvFile = (req.body.fileData);
converter.fromString(csvFile, function(err, result) {
if(!err) {
console.log(result);
res.json(result);
}else {
res.json({error: 'Could not convert'});
}
})
});
app.listen(PORT, () => {
console.log(`app listening on port ${PORT}`);
});
I'm using Express 4. Again, everything works, but only once. When I run Heroku logs, or check the console on localhost I get:
Error: Can't set headers after they are sent.
But I don't understand how I'm re-setting them.
If wanting to run on localhost, here is a link to the projects github: https://github.com/qctimes/calendar_export

You should move the converter instantiation to be done inside the app.post callback method. This way it will instantiate a new object at every request.
This is is how your code should be:
'use strict';
const express = require('express');
const csvtojson = require('csvtojson');
const PORT = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const Converter = require('csvtojson').Converter;
let app = express();
app.use(bodyParser.json({limit: '300kb'}));
app.use(express.static(__dirname +'/public'));
app.post('/',function(req,res) {
var csvFile = (req.body.fileData);
var converter = new Converter({}); // instantiation is done here
converter.fromString(csvFile, function(err, result) {
if(!err) {
console.log(result);
res.send(result);
}else {
res.send({error: 'Could not convert'});
}
});
});
app.listen(PORT, () => {
console.log(`app listening on port ${PORT}`);
});

Related

koa2 post always show Method Not Allowed?

//server.js
const Koa = require('koa')
const app = new Koa();
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());
const Router = require('koa-router');
const fs = require('fs');
const router = new Router();
const UserController = require('./server/controller/user.js');
const checkToken = require('./server/token/checkToken.js');
router.get('/user/login', async ctx => {
ctx.body = JSON.parse(fs.readFileSync( './pass.json'));
console.log(ctx.body);
});
router.post('/signin', async (ctx, next) => {
var
name = ctx.request.body.name || '',
password = ctx.request.body.password || '';
console.log(`signin with name: ${name}, password: ${password}`);
if (name === 'koa' && password === '12345') {
ctx.response.body = `<h1>Welcome, ${name}!</h1>`;
} else {
ctx.response.body = `<h1>Login failed!</h1>
<p>Try again</p>`;
}
});
app.use(router.routes()).use(router.allowedMethods());
app.listen(8090, () => {
console.log('The server is running at http://localhost:' + 8090);
});
koa:2.52
koa-bodyparse:4.21
koa-router:7.4
when I type http://localhost:8090/user/login can get the Json data,but type http://localhost:8090/signin always show 405 Methods Not Allowed ,(debian firefxo) show Request Method "GET",response Allow: POST,Connection: "keep-alive"
I hope get your help.
I guess you shouldn't use the chrome to do the post cause when you type some url, the default method is GET not POST, you can check it out from the NETwork。 Try postman it will work.Sorry for my bad english,I hope it will help XD

koa js async await not working when used with ajax and promise

I'm using koa as a rest backend but I can't get the routing and request/response to work properly, when the URL is called using axios the promise is failing.
server.js
const route = require('koa-route');
const serve = require('koa-static');
const Koa = require('koa');
const app = new Koa();
const path = require('path');
const bodyParser = require('koa-bodyparser');
const Datastore = require('nedb'),
db = new Datastore({
filename: __dirname +'/storage.db' ,
autoload: true
});
// something
app.use(bodyParser());
app.use(serve(__dirname + '/dist'));
app.use(route.get('/api/projects', async function (next) {
let projects = [];
await db.find({}, function (err, docs) {
projects = docs;
});
this.body = projects;
}));
const PORT = process.argv[2] || process.env.PORT || 3000;
app.listen(3000);
when I make a request to /api/projects using axios I get and empty array
from my package.json
"scripts": {
"start": "nodemon server.js --exec babel-node --presets es2015,stage-2"
},
You're mixing promises with callbacks, which is most likely causing your problems.
Stick to using promises:
app.use(route.get('/api/projects', async function (next) {
let projects = await db.find({});
this.body = projects;
}));

Navigate to a page after a GET request in express?

I'm fairly new to express and was wondering how to navigate to a page as a result of a GET request? I'm building my page from a template, and the following works if I manually input the '/id' url:
const express = require('express');
const template = require('./template.js');
const app = express();
const bodyParser = require('body-parser');
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send(template({
body: "Home",
title: "Home Title"
}))
});
app.get('/id', (req, res) => {
console.log("received get request for id");
res.send(template({
body: "id",
title: "ID"
}));
});
const server = app.listen(port);
console.log("listening...");
But if I send a GET request from the client, it gets received and nothing happens. Any tips or help would be appreciated! Thank you!

Node JS works on localhost, online 404

So i am trying to publish an node js app , but it is returning me 404 for my post calls . It works perfectly on localhost. This is my code :
app.js
var express = require('express');
var path = require('path');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
var server = require('http').Server(app);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, '/')));
app.use('/', routes);
app.use('/users', users);
server.listen(process.env.PORT || 3000,function(){
console.log("Working on " + process.env.PORT);
});
module.exports = app;
This is my routes index.js
var express = require('express');
var request = require('request');
var path = require('path');
var bodyParser = require('body-parser');
var router = express.Router();
var app = express();
var jsonParser = bodyParser.json()
app.use(bodyParser.json())
var Connection = require('tedious').Connection;
var databaseConnection
var config = {}
var Connection = require('tedious').Connection;
var config = {
userName: 'asdasd',
password: 'password',
server: 'server',
options: {encrypt: true, database: 'asdasd'}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
console.log("Connected");
});
router.post('/call',jsonParser, function(req,res){
res.send('someresponse')
}
I am simply calling /call through ajax , but it keeps throwing 404 not found.
What am i doing wrong ? It doesnt make sense to me to work on localhost but not online.
If you are using express you cann start server directly with express.
app.listen(port)
If you want to do it with nodejs http you also have to set the port nodejs should listen to.
nodejs http
express app.listen
The problem was my auto generated web config was not doing its job , i have swaped it with another one i found on internet
https://github.com/projectkudu/kudu/wiki/Using-a-custom-web.config-for-Node-apps
Just changed from server.js to app.js

how can I get sessions to work using redis, express & socket.io?

So I am trying to get Sessions to work inside my socket.on('connection', ...)
I am trying to get this working using recent versions: Socket.io - 0.9.13, Express - 3.1.0 and latest versions of other modules.
Anyway I have tried using both modules 'connect-redis' and 'session.socket.io' and they both have similar problems.
In my code I have 2 redis stores (socketio.RedisStore and require('connect-redis')(express)), now this program all runs fine, but because express and socket.io need to share session data, I was wondering if this setup will use sessions correctly? do the session stores need to be the same object for express/socketio? A bit of a gray area to me, because the 2 RedisStore's will use the same db in the background?
I have tried using either the socket.io redisStore or the connect-redis redisStore in both places, but socket.io doesnt like the connect-redis redisStore and express doesnt like the socketio.redisStore.
If I use the connect-redis RedisStore then socket.io/lib/manager.js complains:
this.store.subscribe(...
TypeError Object # has no method 'subscribe'
If I use socketio.RedisStore then express/node_modules/connect/lib/middleware/session.js complains:
TypeError: Object # has no method 'get'
*Note I would rather get the session.socket.io plugin working, but when I do the same setup with that plugin, express (also) complains:
TypeError: Object # has no method 'get'
So is it ok that I use 2 different RedisStores for sessions, or do I need to somehow get one or the other working for both, and if so any ideas on how to fix?
My current code looks like this:
var
CONST = {
port: 80,
sessionKey: 'your secret sauce'
};
var
redis = require('redis');
var
express = require('express'),
socketio = require('socket.io'),
RedisStore = require('connect-redis')(express);
var
redisStore = new RedisStore(),
socketStore = new socketio.RedisStore();
var
app = express(),
server = require('http').createServer(app),
io = socketio.listen(server);
app.configure(function(){
app.use(express.cookieParser( CONST.sessionKey ));
app.use(express.session({ secret: CONST.sessionKey, store: redisStore }));
app.use(express.static(__dirname + '/test'));
app.get('/', function (req, res) {res.sendfile(__dirname + '/test/' + 'index.htm');});
});
io.configure(function(){
io.set('log level', 1);
io.enable('browser client minification');
io.enable('browser client etag');
io.enable('browser client gzip');
io.set('store', socketStore);
});
io.sockets.on('connection', function(socket){
socket.emit('message', 'Test 1 from server')
});
server.listen( CONST.port );
console.log('running...');
inside the io.configure, you have to link the socket with the http session.
Here's a piece of code that extracts the cookie (This is using socket.io with xhr-polling, I don't know if this would work for websocket, although I suspect it would work).
var cookie = require('cookie');
var connect = require('connect');
var sessionStore = new RedisStore({
client: redis // the redis client
});
socketio.set('authorization', function(data, cb) {
if (data.headers.cookie) {
var sessionCookie = cookie.parse(data.headers.cookie);
var sessionID = connect.utils.parseSignedCookie(sessionCookie['connect.sid'], secret);
sessionStore.get(sessionID, function(err, session) {
if (err || !session) {
cb('Error', false);
} else {
data.session = session;
data.sessionID = sessionID;
cb(null, true);
}
});
} else {
cb('No cookie', false);
}
});
Then you can access the session using:
socket.on("selector", function(data, reply) {
var session = this.handshake.session;
...
}
This also has the added benefit that it checks there is a valid session, so only your logged in users can use sockets. You can use a different logic, though.
Looking at your last note (won't be able to share its state over multiple processes using redis) I had the same problem and found a solution:
var express = require("express.io");
var swig = require('swig');
var redis = require('redis');
var RedisStore = require('connect-redis')(express);
workers = function() {
var app = express().http().io();
app.use(express.cookieParser());
app.use(express.session({
secret: 'very cool secretcode',
store: new RedisStore({ client: redis.createClient() })
}));
app.io.set('store', new express.io.RedisStore({
redisPub: redis.createClient(),
redisSub: redis.createClient(),
redisClient: redis.createClient()
}));
app.get('/', function(req, res) {
res.render('index');
});
app.listen(3000);
app.io.route('ready', function(req){
//setup session stuff, use session stuff, etc. Or make new routes
});
};
cluster = require('cluster');
numCPUs = require('os').cpus().length;
if (cluster.isMaster)
{
for (var i = 0; i < numCPUs; i++)
{
cluster.fork();
}
}
else
{
workers();
}

Resources