NodeJS Method not allowed - node.js

module.exports.login = function (request, response, next) {
if (request.body.user && request.body.password) {
response.end('submitted');
} else {
common.render('login', function (error, file) {
if (error) {
next(error);
} else {
response.writeHead(200, 'OK', { 'Content-Type': 'text/html' });
var stream = fs.createReadStream(file);
stream.pipe(response);
}
});
}
};
I am using connect with body-parser. When I first time open this app I see login form - nice, but when I submit a form I see in a console 405 Method not allowed error. I was trying to add some headers but it didn't work. Anyone can help?

I finally solved it. The problem was serve-static and serve-index. It was written some extra headers like allowed methods!

I believe the syntax should be:
module.exports = function(request, response, next) {
if (request.body.user && request.body.password) {
response.end('submitted');
} else {
common.render('login', function (error, file) {
if (error) {
next(error);
} else {
response.writeHead(200, 'OK', { 'Content-Type': 'text/html' });
var stream = fs.createReadStream(file);
stream.pipe(response);
}
});
}
};
or
function login(request, response, next) {
if (request.body.user && request.body.password) {
response.end('submitted');
} else {
common.render('login', function (error, file) {
if (error) {
next(error);
} else {
response.writeHead(200, 'OK', { 'Content-Type': 'text/html' });
var stream = fs.createReadStream(file);
stream.pipe(response);
}
});
}
};
module.exports = login;

Related

node.js - home page doesn't load but other pages do

I'm learning node.js. This code is from a class. It has if else statements. The point is to simplify it and one of the ways I'm doing is using switch case. I'm not sure why the home page doesn't load but "other page" and other other page" does.
As a secondary problem, does figlet work on windows? I use npm install figlet in my node_modules folder. Not sure if I can post multiple problems in one thread. If not, I would like to have my home page solved first.
const http = require("http");
const fs = require("fs");
const url = require("url");
const querystring = require("querystring");
// const figlet = require("figlet");
const server = http.createServer((req, res) => {
const page = url.parse(req.url).pathname;
const params = querystring.parse(url.parse(req.url).query);
console.log(page);
switch (page) {
case "/":
fs.readFile("index.html", function (err, data) {
res.writeHead(200, { "Content-Type": "text/html" });
res.write(data);
res.end();
});
break;
case "/otherpage":
fs.readFile("otherpage.html", function (err, data) {
res.writeHead(200, { "Content-Type": "text/html" });
res.write(data);
res.end();
});
break;
case "/otherotherpage":
fs.readFile("otherotherpage.html", function (err, data) {
res.writeHead(200, { "Content-Type": "text/html" });
res.write(data);
res.end();
});
break;
case "/api":
if ("student" in params) {
if (params["student"] == "leon") {
res.writeHead(200, { "Content-Type": "application/json" });
const objToJson = {
name: "leon",
status: "Boss Man",
currentOccupation: "Baller",
};
res.end(JSON.stringify(objToJson));
} else if (params["student"] != "leon") {
res.writeHead(200, { "Content-Type": "application/json" });
const objToJson = {
name: "unknown",
status: "unknown",
currentOccupation: "unknown",
};
res.end(JSON.stringify(objToJson));
}
}
break;
case "/ccs/style.css":
fs.readFile("css/style.css", function (err, data) {
res.write(data);
res.end();
});
break;
case "/js/main.js":
fs.readFile("js/main.js", function (err, data) {
res.writeHead(200, { "Content-Type": "text/javascript" });
res.write(data);
res.end();
});
break;
default:
figlet("404!!", function (err, data) {
if (err) {
console.log("Something went wrong...");
console.dir(err);
return;
}
res.write(data);
res.end();
});
}
});
server.listen(8000);
Did you tried using empty string "" instead of "/" in your case?

How can i use promise method in node

I was trying out the promise function for the REST API instead of using axios method. so I can wait for the result and if there is any error. can anyone help me change this code to promise in node.js so I can do a fetch using promise method. thank you
this is my code
const email = "xxx#xxxx.com"
function isUserExists(email, kc_accessToken) {
let url = `${path}/users?email=${email}`;
return axios_instance.get(url,
{
headers: {
"content-type": "application/json",
"authorization": `Bearer ${kc_accessToken}`
}
}).then(function (response) {
if (response.data.length > 0) {
return true;
} else {
return false;
}
})
.catch(function (error) {
console.log("some error occured");
});
}
Method call
http.createServer(function Test() {
getAccessToken().then(function (response) {
kc_accessToken = response.data.access_token;
IsUserExists(email, kc_accessToken).then((resp) => {
console.log(resp)
if(resp) {
console.log("Do Not Create")
} else if (!resp) {
console.log("Creat a new User")
}
})
}).catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});;
}).listen(8081);
I think you need something like that :
const email = "xxx#xxxx.com"
const request = require('request');
function isUserExists(email, kc_accessToken) {
let url = `${path}/users?email=${email}`;
return new Promise(function(resolve, reject){
request({
url: url,
headers: {
"content-type": "application/json",
"authorization": `Bearer ${kc_accessToken}`
}
}, function (error, response, body) {
if (error) {
console.log("some error occured");
}
if (response.data.length > 0) {
return resolve();
}
return reject();
});
});
}

how to get data outside request

I have a scenario where i need to take response (body) of request method outside request. How can i do it?
request.post({
url: 'http://localhost/api/messages',
form: { key: message }
}, function (err, httpResponse, body) {
tmsg = body;
})
console.log(tmsg);
I need this tmsg outside for next processing, Actual scenario is as below.
app.post('/incomemsg', function (req, res) {
var mediaCount = req.body.NumMedia;
if (mediaCount == 0) {
//var twiml = getResponse(message);
var twiml = new MessagingResponse();
request.post({
url: 'http://localhost:3978/api/messages',
form: { key: message }
}, function (err, httpResponse, body) {
tmsg = body;
})
console.log(tmsg);
}else {
//dosomething which outputs tmsg
}
res.writeHead(200, { 'Content-Type': 'text/xml' });
res.end(tmsg.toString());
});
The problem is you are trying to assign value to a global variable in request.post's callback() which is only called after request.post is executed by Asynchronous logic(API calls are all async), so a better way would be to promisify request.post and await the request.post to make it seem synchronous.
const requestPromisified = requestObject =>
new Promise((resolve, reject) => {
request.post(requestObject, function(err, httpResponse, body) {
if (err) {
reject(err);
}
resolve(body);
});
});
const body = await requestPromisified({
method: "POST",
url: "http://localhost/api/messages",
form: { key: message }
});
You only can do something with tmsg when you made the request so you need to rearrange your code like this:
app.post('/incomemsg', function (req, res) {
var mediaCount = req.body.NumMedia;
var twiml = new MessagingResponse();
request.post({
url: 'http://localhost:3978/api/messages',
form: { key: message }
}, function (err, httpResponse, body) {
tmsg = body;
console.log(tmsg);
if (mediaCount === 0) {
//do something with tmsg
} else {
//do something else with tmsg
}
res.writeHead(200, { 'Content-Type': 'text/xml' });
res.end(tmsg.toString());
});
});
Otherwise tmsg will be null because there was no request made to fill that variable.

TypeError: callback is not a function in nodejs

I am trying learn nodejs and stumble upon this error
TypeError: callback is not a function
when I am trying to call the server using this command.
curl http://localhost:8090/albums.json
and here is the code for my server.js
var http = require('http'),
fs = require('fs');
function load_album(album_name, callback) {
fs.readdir("albums/", +album_name, (err, files) => {
if (err) {
if (err.code == "ENOENT") {
callback(make_error("no_such_album", "That album doesn't exist"));
} else {
callback(make_error("can't load album", "The server is broken"));
}
} else {
//callback(null, files);
var only_files = [];
var path = 'albums/${album_name}/';
var iterator = (index) => {
if (index == files.length) {
var obj = {
short_name: album_name,
photos: only_files
};
callback(null, obj);
return;
}
fs.stat(path + files[index], (err, stats) => {
if (!err && stats.isFile()) {
only_files.push(files[index]);
}
iterator(index + 1);
});
};
iterator(0);
}
});
}
function handle_incoming_request(req, res) {
console.log("incoming request: " + req.method + " " + req.url);
if (req.url == '/albums.json') {
load_album((err, albums) => {
if (err) {
res.writeHead(500, {
"Content-Type": "application/json "
});
res.end(JSON.stringify({
code: "cant_load_albums",
message: err.message
}));
} else {
var output = {
error: null,
data: {
albums: albums
}
};
res.writeHead(200, {
"Content-Type": "application/json"
});
res.end(JSON.stringify(output) + "\n");
}
});
} else if (req.url.substr(0, 7) == '/albums' && req.url.substr(req.url.length - 5) == '.json') {
//user is requesting contents of album
load_album(req.url.substr(7, req.url.length - 12), (err, photos) => {
if (err) {
res.writeHead(500, {
"Content-type": "application/json"
});
res.end(JSON.stringify(err));
} else {
var output = {
error: null,
data: {
photos: photos
}
};
res.writeHead(200, {
"Content-Type": application / json
});
res.end(JSON.stringify(output) + "\n");
}
});
} else {
res.writeHead(404, {
"Content-type": "application/json"
});
res.end(JSON.stringify({
code: "no_such_page",
message: "No such page"
}));
}
}
var s = http.createServer(handle_incoming_request);
s.listen(8090);
can you tell me what's wrong with my code that I got an error telling me callback isn't a function?
thanks though
for more formatted code then you can go here https://jsfiddle.net/02dbx6m9/
var http = require('http'),
fs = require('fs');
function load_album(album_name, callback) {
fs.readdir("albums/", +album_name, (err, files) => {
if (err) {
if (err.code == "ENOENT") {
callback(make_error("no_such_album", "That album doesn't exist"));
} else {
callback(make_error("can't load album", "The server is broken"));
}
} else {
//callback(null, files);
var only_files = [];
var path = 'albums/${album_name}/';
var iterator = (index) => {
if (index == files.length) {
var obj = {
short_name: album_name,
photos: only_files
};
callback(null, obj);
return;
}
fs.stat(path + files[index], (err, stats) => {
if (!err && stats.isFile()) {
only_files.push(files[index]);
}
iterator(index + 1);
});
};
iterator(0);
}
});
}
function handle_incoming_request(req, res) {
console.log("incoming request: " + req.method + " " + req.url);
if (req.url == '/albums.json') {
load_album("ALBUM NAME", (err, albums) => {
if (err) {
res.writeHead(500, {
"Content-Type": "application/json "
});
res.end(JSON.stringify({
code: "cant_load_albums",
message: err.message
}));
} else {
var output = {
error: null,
data: {
albums: albums
}
};
res.writeHead(200, {
"Content-Type": "application/json"
});
res.end(JSON.stringify(output) + "\n");
}
});
} else if (req.url.substr(0, 7) == '/albums' && req.url.substr(req.url.length - 5) == '.json') {
//user is requesting contents of album
load_album("Album Name", req.url.substr(7, req.url.length - 12), (err, photos) => {
if (err) {
res.writeHead(500, {
"Content-type": "application/json"
});
res.end(JSON.stringify(err));
} else {
var output = {
error: null,
data: {
photos: photos
}
};
res.writeHead(200, {
"Content-Type": application / json
});
res.end(JSON.stringify(output) + "\n");
}
});
} else {
res.writeHead(404, {
"Content-type": "application/json"
});
res.end(JSON.stringify({
code: "no_such_page",
message: "No such page"
}));
}
}
var s = http.createServer(handle_incoming_request);
s.listen(8090);
You forgot to pass album name parameter in load_album method. That's why album_name parameter is assigned the actual callback, while callback parameter remains undefined.
Here is the root cause of your issue:
load_album((err, albums) => {
// ...
});
The signature for the function requires two parameters, yet you're only passing the first one:
function load_album(album_name, callback) {}
Therein, once called, callback will be undefined, yet you're trying to treat it as a callable. Here's a more succint example of how to reproduce the error:
function foo(bar, baz) {
baz()
}
foo(() => {})

Can't set headers after they are sent error with async

I'm trying a pretty complex computation in my code below. I'm trying to get the list of bugs from github in the given project using the api https://api.github.com/repos/marklogic/java-client-api/issues?page=1&per_page=10. From the list of bugs I'm trying to get each issues' corresponding events and comments from their corresponding endpoints ex: https://api.github.com/repos/marklogic/java-client-api/issues/291/events and https://api.github.com/repos/marklogic/java-client-api/issues/291/comments.
I'm using async library. I'm using waterfall function and parallel function to return a consolidated JSON for each bug such that each issue will have comment, & events in the same response for each issue. The problem is its throwing Can't set headers after they are sent error & its pointing to line 2 lines, I understand what the error is saying but I can't figure out how to fix it, because commenting out either of the offending lines results in request hang because the server is not sending the response. Please help! Thanks in advance
exports.listGitHubBugs = function(req, res) {
var _page = req.query.page || 1;
var _per_page = req.query.per_page || 25;
var finalResult = []
//console.log('url:', 'https://api.github.com/repos/marklogic/' + req.query.project + '/issues?page=' + _page + '&per_page=' + _per_page);
var options = {
url: 'https://api.github.com/repos/marklogic/' + req.query.project + '/issues?page=' + _page + '&per_page=' + _per_page,
headers: {
'User-Agent': req.query.project
},
auth: githubAuth
};
request(options, function(error, response, body) {
if (error) {
console.log(error);
res.send(error);
}
if (!error && response.statusCode === 200) {
var issues = JSON.parse(response.body)
async.waterfall([
// get comments & events for all bugs and then send the response
function(callback) {
issues.forEach(function(issue) {
// for each bug, get comments and events
async.parallel([
function(parallelCallback) {
var options = {
url: issue.events_url,
headers: {
'User-Agent': getProjectNameFromURL(issue.events_url)
},
auth: githubAuth
};
request(options, function(error, response, body) {
if (error) {
console.log('ERROR', error);
parallelCallback(error)
}
if (!error && response.statusCode === 200) {
// console.log('events:', body);
parallelCallback(null, body)
}
})
},
function(parallelCallback) {
var options = {
url: issue.comments_url,
headers: {
'User-Agent': getProjectNameFromURL(issue.comments_url)
},
auth: githubAuth
};
request(options, function(error, response, body) {
if (error) {
console.log('ERROR', error);
parallelCallback(error)
}
if (!error && response.statusCode === 200) {
// console.log('comments:', body);
parallelCallback(null, body)
}
})
}
], function(err, result) {
if (err) {
console.log('ERROR:', err);
callback(err);
}
console.log('parallel process done');
issue.events = JSON.parse(result[0]);
issue.comments = JSON.parse(result[1]);
finalResult.push(issue)
callback(null, finalResult) // offending line#1
})
}) // forEach end
}
], function(err, result) {
if (err) {
res.send(err);
}
console.log('waterfall done');
console.log(result);
res.send(result); // offending line#2
})
} // if end
}) // reqest end
}
Error
UncaughtException: Can't set headers after they are sent.
ERROR Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:691:11)
at ServerResponse.res.set.res.header (/Users/sreddy/space/angularjs/BugTrack/node_modules/express/lib/response.js:524:10)
at ServerResponse.res.send (/Users/sreddy/space/angularjs/BugTrack/node_modules/express/lib/response.js:125:10)
at ServerResponse.res.json (/Users/sreddy/space/angularjs/BugTrack/node_modules/express/lib/response.js:191:15)
at /Users/sreddy/space/angularjs/BugTrack/server/api/common/common.controller.js:163:33
at /Users/sreddy/space/angularjs/BugTrack/server/api/common/common.controller.js:153:29
at /Users/sreddy/space/angularjs/BugTrack/node_modules/async/lib/async.js:254:17
at done (/Users/sreddy/space/angularjs/BugTrack/node_modules/async/lib/async.js:135:19)
at /Users/sreddy/space/angularjs/BugTrack/node_modules/async/lib/async.js:32:16
at /Users/sreddy/space/angularjs/BugTrack/node_modules/async/lib/async.js:251:21
Final working code
exports.listGitHubBugs = function(req, res) {
var _page = req.query.page || 1;
var _per_page = req.query.per_page || 25;
var finalResult = []
//console.log('url:', 'https://api.github.com/repos/marklogic/' + req.query.project + '/issues?page=' + _page + '&per_page=' + _per_page);
var options = {
url: 'https://api.github.com/repos/marklogic/' + req.query.project + '/issues?page=' + _page + '&per_page=' + _per_page,
headers: {
'User-Agent': req.query.project
},
auth: githubAuth
};
request(options, function(error, response, body) {
if (error) {
console.log(error);
return res.send(error);
}
if (!error && response.statusCode === 200) {
var issues = JSON.parse(response.body)
async.waterfall([
// get events and comments for all bugs and return the final processes list of bugs
function getEventsAndCommentsForAllBugs(callback) {
issues.forEach(function getEventsAndComments(issue, index) {
// for each bug, get comments and events
async.parallel([
function getEvents(parallelCallback) {
var options = {
url: issue.events_url,
headers: {
'User-Agent': getProjectNameFromURL(issue.events_url)
},
auth: githubAuth
};
request(options, function(error, response, body) {
if (error) {
console.log('ERROR', error);
parallelCallback(error)
}
if (response.statusCode === 200) {
// console.log('events:', body);
parallelCallback(null, body)
}
})
},
function getComments(parallelCallback) {
var options = {
url: issue.comments_url,
headers: {
'User-Agent': getProjectNameFromURL(issue.comments_url)
},
auth: githubAuth
};
request(options, function(error, response, body) {
if (error) {
console.log('ERROR', error);
parallelCallback(error)
}
if (response.statusCode === 200) {
// console.log('comments:', body);
parallelCallback(null, body)
}
})
}
], function attachEventsAndComments(err, result) {
if (err) {
console.log('ERROR:', err);
callback(err);
}
console.log('parallel process done');
issue.eventList = JSON.parse(result[0]);
issue.commentList= JSON.parse(result[1]);
finalResult.push(issue)
if (index === (issues.length - 1)) {
callback(null, finalResult)
}
//
})
}) // forEach end
}
], function processedBugs(err, result) {
if (err) {
res.send(err);
}
console.log('waterfall done');
console.log(result);
res.send(result);
})
} // if end
}) // reqest end
}
could you provide a complete working example of the code, something we can try.
this said, there are several errors in this source code.
Onthe first request, if an error occurs, you write it in app.response,, but you don t stop execution. Thus, if an error occurs, you ll write twice the response object.
You should do
if (error) {
console.log(error);
return res.send(error);
}
instead of
if (error) {
console.log(error);
res.send(error);
}
Then, this can be changed
if (!error && response.statusCode === 200) {
to
if (response.statusCode === 200) {
Same mistake occurs while fetching issues events and comments, please consider to fix it.
And also in the final callback of async.//
And in the final callback of async.waterfall.
finally, i suggest you to make use of named functions. That would help you to debug by providing more meaningfull error stack trace.
For example instead of doing,
async.prallel([function(){/* code here*/}]);
You would write
async.parallel([function nameOfTheTask(){/* code here*/}]);
consider also to use a linter such as eslint, several missing ; could break your code, see http://eslint.org/
I figured it out. I was calling the parellelCallback() for every iteration instead of calling it at the end of the loop. Simple if condition was all that was required.
if (index === (issues.length-1)) {
callback(null, finalResult)
}

Resources