My Nodejs req.on('data') not trigger, but req.on('end') works. I'm learning Nodejs and I don't know how to fix it.
My Nodejs file:
let routes = {
'GET': {
'/': (req,res) => {
fs.readFile('./public/index.html', (err, html) => {
if(err) throw err;
res.writeHead(200, {'Content-type': 'text/html'});
res.write(html);
res.end();
});
}
},
'POST': {
'/api/login': (req, res) => {
let body = '';
req.on('data', data => {
console.log('req data fired!');
body += data;
});
req.on('end', () => {
console.log('req end fired!')
res.end();
})
}
}
}
function router(req, res) {
let baseURL = url.parse(req.url, true);
let resolveRoute = routes[req.method][baseURL.pathname];
if(resolveRoute != undefined) {
resolveRoute(req, res);
}
}
http.createServer(router).listen(3000, () => console.log('Server running in port 3000'));
How to fix the req.on('data') triggering?
If the data event doesn't fire, but the end event does, then it's because there is no actual body data in the POST request.
With your exact code, the only way I could reproduce what you describe is when the POST body was empty and there was no data there to read. If, for example, you are submitting a form in the browser and there are no elements in the form with a name attribute, no data will be sent with the request.
As soon as I made sure there was some data in the POST request, then the data event fires and it presents a Buffer with the data in it.
Related
This code is receiving data from curl and suppose to show that data on the header body response. But it's not working. Where am I wrong???
const server = http.createServer((req , res) => {
res.writeHead(200, {'Content-type': 'text/plain'});
const { headers, method, url } = req;
let body = [];
req.on('error', (err) => {
console.error(err);
})
req.on('data', (chunk) => {
body.push(chunk);
})
req.on('end', () => {
body = Buffer.concat(body).toString();
});
});
This should do the job if you what All together now! to be set in the response body.
const http = require('http');
const server = http.createServer((req, res) => {
let body = [];
req.on('error', (err) => {
console.error(err);
})
req.on('data', (chunk) => {
body.push(chunk);
})
req.on('end', () => {
body = Buffer.concat(body).toString();
// set response
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(body);
});
});
server.listen('3000');
I'm trying to create REST API. My API should return a list of users taken from a 3rd party (after some manipulations) and return it.
Here is my code:
function getUsersFrom3rdParty(options) {
https.get(options, (resp) => {
let data ='';
// A chunk of data has been received.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(JSON.parse(data));
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
exports.getUsers = (req, res, next) => {
var data = getUsersFrom3rdParty();
//do the manilupations and return to the api
};
I don't get the data in getUsers function.
I'd suggest using something like axios - npmjs - for making asynchronous calls to a 3rd party API:
const axios = require('axios')
function getUsersFrom3rdParty(options) {
const processResponse = (response) => {
const processedResponse = ...
// do whatever you need to do, then return
return processedResponse
}
return axios.get('/example.com')
.then(processResponse)
}
// then, you can use `getUsersFrom3rdParty` as a promise
exports.getUsers = (req, res, next) => {
const handleResponse = (data) => {
res.json({ data }) // or whatever you need to do
}
const handleError = (err) => {
res.json({ error: 'Something went wrong!' }) // or whatever you need to do
}
getUsersFrom3rdParty(...)
.then(handleResponse)
.catch(handleError)
}
This way, you're waiting for your API call to finish before you render something and/or return a response.
You are not passing options variable when you are calling getUsersFrom3rdParty function
var data = getUsersFrom3rdParty(options);
You have to pass options to make it work and I suggest to use request module .It works better than https module.
Here is your code using request
const request = require("request");
function getUsersFrom3rdParty(options) {
request(options, (error, response, body) => {
if (!error && response.statusCode == 200) {
//Returned data
console.log(JSON.parse(body));
}
});
}
exports.getUsers = (req, res, next) => {
var data = getUsersFrom3rdParty(options);
};
I use Nodejs version 10.10.0 on Debian 9 with this simple code but it doesn't show any data in console nor response.
code:
const http = require('http');
const { parse } = require('querystring');
http.createServer((request, response) => {
const { headers, method, url } = request;
let body = [];
request.on('error', (err) => {
console.error(err);
}).on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
console.log(parse(body));
response.statusCode = 200;
response.setHeader('Content-Type', 'text/html');
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Credentials', true);
response.write('body: ' + body);
response.end();
});
}).listen(3030); // Activates this server, listening on port 8080.
result:
{}
Thank you for the comment. I am new to Nodejs and was thinking data should include either GET or POST requests' data; looks like it takes care of only POST requests and GET should be parsed from headers.
I write API in order to client upload file. API has content-type multiple/form-data. But I don't know get values from client send to my
router.post('/upload/file', async (req, res) => {
var body = "";
try {
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
console.log('body: ' + body);
var formData = new FormData(body);
console.log("=====================", formData.entries);
// var {accessTok, type, file} = req.params;
//
// if (!accessTok || !type || !file) {
res.json({
code: -1000,
message: 'Missing parameter(s). Please provide accessToken, type upload, file upload.'
});
res.end();
return null;
})
// }
}catch(err){
res.json({err: err.message});
res.end();
return;
}
I tried use FormData but not done. I get error is not function, formData.getKey('') is them same.
When posting data from jquery to a node.js process sometimes it work, sometimes it doesn't. It depends on how I structure the code. This way it works:
http.createServer(router).listen(5000, '127.0.0.1');
console.log('Server running at http://127.0.0.1:5000/');
function router(req, res){
var page = url.parse(req.url, true);
switch(page.pathname){
case '/new-task': tasks.postNewTask(req, res); break;
}
}
"tasks" is a module I load. Inside there's postNewTask:
function postNewTask(req, res){
core.postRequest(req, res, function () {
// lots of stuff inside
})
}
postRequest is a function I "borrowed" here from Stackoverflow. It's defined as:
function postRequest(request, response, callback) {
var queryData = "";
if(typeof callback !== 'function') return null;
if(request.method == 'POST') {
console.log("it's post");
request.on('data', function(data) {
console.log("it's data");
queryData += data;
if(queryData.length > 1e6) {
console("too much stuff");
queryData = "";
response.writeHead(413, {'Content-Type': 'text/plain'});
request.connection.destroy();
}
});
request.on('end', function() {
console.log("it's end");
response.post = querystring.parse(queryData);
callback();
});
} else {
console.log("no post");
response.writeHead(405, {'Content-Type': 'text/plain'});
response.end();
}
}
This works perfectly and and the code inside tasks.postNewTask runs. However when I change the router to this:
function router(req, res){
var page = url.parse(req.url, true);
var session = core.getCookies(req).s;
if (page.pathname == '/login') {
core.postLogin(req, res); return; }
database.query('SELECT * from Members WHERE Session = ?;', [session], function(err, rows, fields) {
if (err) throw err;
if (rows.length>0) {
switch(page.pathname){
case '/new-task': tasks.postNewTask(req, res); break;
}
} else {
res.writeHead(200, "OK", {'Content-Type': 'application/json'});
res.end(JSON.stringify('login'));
};
});
}
then postRequest no longer works. It will only print "it's post" and that's it. It never prints data or that it reaches end. It also seems to never return to the client as I get a timeout on the browser.
The problem here is that "data" and "end" events in postRequest are never called, when the only thing I changed was to wrap the database call around the switch statement.
Thanks!
You have 3 console outputs in postRequest
it's post
it's data
it's end
First is fired regardless because the if condition just checks for request type, rest two are done when request gets data and end signals, asynchronously. So if postNewTask returns or sends response to the request then it may not reach that part. Check what you are doing in // lots of stuff inside
Also on searching for your mysql documentation https://npmjs.org/package/mysql I found :
You MUST NOT provide a callback to the query() method when streaming rows.
So check on that too.