express routes do not load again - javascript

I'm encountering a problem with the express routes. Here's my case:
I have a node js app with the following code in app.js
var express = require('express');
var app = express();
var path = require('path');
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: false
}));
var cfenv = require('cfenv');
// request module provides a simple way to create HTTP requests in Node.js
var request = require('request');
var routes = require('./routes')(app);
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname + '/public/index.html'));
});
var appEnv = cfenv.getAppEnv();
// compose for mysql code
var dbcontroller = require('./controller/compose-mysql-connection');
dbcontroller.databaseconnection();
const util = require('util');
// and so is assert
const assert = require('assert');
var mysql = require('mysql');
var appEnv = cfenv.getAppEnv();
// Within the application environment (appenv) there's a services object
var services = appEnv.services;
// The services object is a map named by service so we extract the one for Compose for MySQL
var mysql_services = services["compose-for-mysql"];
// This check ensures there is a services for MySQL databases
assert(!util.isUndefined(mysql_services), "Must be bound to compose-for-mysql services");
// We now take the first bound Compose for MySQL database service and extract it's credentials object
var credentials = mysql_services[0].credentials;
var connectionString = credentials.uri;
// set up a new connection using our config details
var connection = mysql.createConnection(credentials.uri);
//reading from the database
app.get("/read_fb_info", function(request, response) {
connection.query('SELECT * FROM fb_info_table ORDER BY name ASC', function (err, result) {
if (err) {
console.log(err);
response.status(500).send(err);
} else {
console.log(result);
response.send(result);
}
});
});
app.use(express.static(__dirname + '/public'));
// start server on the specified port and binding host
app.listen(appEnv.port, '0.0.0.0', function() {
// print a message when the server starts listening
console.log("server starting on " + appEnv.url);
});
Then, in the routes folder I have a file with other two routes I use into the application.
Once the index page is loaded I have two button:
<body>
<div class="container">
<h1>External API Usage</h1>
<h3>LinkedIn</h3>
<a href='/info/linkedin'>
<img src="/images/LinkedIn_image.png" class="img-rounded" alt="LinkedIn" width="150" height="150">
</a>
<h3>Facebook</h3>
<a href='/info/facebook'>
<img src="/images/Facebook_image.png" class="img-rounded" alt="Facebook" width="150" height="150">
</a>
</div>
To handle routes I created an index.js file in the routes folder which includes the following:
retrieveFacebookUserInfo = function() {
var deferred = Q.defer();
var propertiesObject_FB = { id:'id', name:'name', access_token:'access_token' };
request({url:'https://graph.facebook.com/', qs:propertiesObject_FB}, function(err, response, body) {
if(err) {
deferred.resolve(null);
}
else {
var fb_json = JSON.parse(body);
console.log("Get response: " + response.statusCode);
console.log(fb_json);
//storing information to db
dbcontroller.writingtodb();
deferred.resolve(fb_json);
}
});
return deferred.promise;
};
app.get('/info/facebook', function(req, res){
retrieveFacebookUserInfo().then(function(result){
res.render('facebook.ejs', {
title : 'Facebook information',
fb_obj: result
});
});
});
app.get('/info/linkedin', function(req, res){
retrieveLinkedInUserInfo().then(function(result){
res.render('linkedin.ejs', {
title : 'LinkedIn information',
headline_linkedin: result.headline
});
});
});
If I try to open the second one (/info/facebook) at first e then the first one (/info/linkedin) it doesn't load the page related of /info/linkedin route. It shows this message:
404 Not Found: Requested route ('linkedin-demo-app.eu-gb.mybluemix.net') does not exist.
Do you guys know what is this kind of problem? It seems like it doesn' recognize and find the route again.
Thanks in advance

You simply don't have route handler for these two paths. You need to create them like you did for your /read_fb_info path:
app.get("/info/linkedin", function(request, response) {
//do somenthing and send your response
});
app.get("/info/facebook", function(request, response) {
//do somenthing and send your response
});

Related

Building a project around Bing translate and Node.js

I am trying to build a web app that allows a user to press a button and translate a piece of text using the Bing translator api. I try to run a translator.js file through a script tag but I of course cannot run this node.js code through the client html page. What would be the proper way to design this app. Is my only choice to use something such as requirejs? I also have an app.js file built using express from which I run the app. Sorry for posting a lot of code, I want to give people an idea of the structure of my app. My experience is limited so I am feeling somewhat lost as to how to approach the design of this portion of the app. I don't expect anyone to write the code for me, but to just point in a direction of techniques that I could research so that I could build this properly.
Here is my Node.js translation request called translator.js
const request = require('request');
const uuidv4 = require('uuid/v4');
var key_var = 'TRANSLATOR_TEXT_SUBSCRIPTION_KEY';
if (!process.env[key_var]) {
throw new Error('Please set/export the following environment variable: ' + key_var);
}
var subscriptionKey = process.env[key_var];
var endpoint_var = 'TRANSLATOR_TEXT_ENDPOINT';
if (!process.env[endpoint_var]) {
throw new Error('Please set/export the following environment variable: ' + endpoint_var);
}
var endpoint = process.env[endpoint_var];
let options = {
method: 'POST',
baseUrl: endpoint,
url: 'translate',
qs: {
'api-version': '3.0',
'to': ['en']
},
headers: {
'Ocp-Apim-Subscription-Key': subscriptionKey,
'Content-type': 'application/json',
'X-ClientTraceId': uuidv4().toString()
},
body: [{
'text': 'hallo welt'
}],
json: true,
};
function displayBingTranslate() {
request(options, function(err, res, body){
document.querySelector("#bingTranslateOutput") = JSON.stringify(body, null, 4);
});
};
var accessBingTranslate = document.getElementById("accessBingTranslateButton");
accessBingTranslate.addEventListener("click", function() {
displayBingTranslate();
});
And here is my html
<!-- Section to view online translation -->
<div class="container">
<div class="row">
<div class="col-lg-12 p-0">
<button
class="btn btn-outline-dark btn-sm mb-1"
id = "accessBingTranslateButton">Translate Flashcard</button>
<div class="row m-0 p-0">
<div id="bingTranslateOutput" class="col-lg-12 m-0">
</div>
<script>
// Overall list of flashcards.
var flashcardList = {
flashcards: [],
// Adds a flashcard object to Flashcard array.
addFlashcard: function(fcTextQuestion, fcTextTranslated) {
this.flashcards.push({
fcTextQuestion: fcTextQuestion,
fcTextTranslated: fcTextTranslated
});
},
};
// Add flashcards on load.
var flashcardsDB = <%- JSON.stringify(flashcardsDB) %>;
console.log("the DB:", flashcardsDB);
flashcardsDB.forEach(function(fcardDbToAdd){
flashcardList.addFlashcard(fcardDbToAdd.question, fcardDbToAdd.translation);
});
document.querySelector("#displayFlashcardTotal").textContent = flashcardList.flashcards.length;
console.log("the rest:",flashcardList.flashcards);
var currentFlashcard = 0;
</script>
<script src="/scripts/translator.js"></script>
</body>
</html>
and here is my app.js
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var mongoose = require("mongoose");
var methodOverride = require("method-override");
// Fix mongoose deprecations
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
mongoose.set('useUnifiedTopology', true);
// Connect to database.
var url = "///////";
mongoose.connect(url, {
useNewUrlParser: true,
useCreateIndex: true,
}).then(() => {
console.log("connected to mongoDB");
}).catch(err => {
console.log("Error:", err.message);
});
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static(__dirname + '/public'));
// Set 'views' directory for any views
// being rendered res.render()
app.set("view engine", "ejs");
// Override HTTP verbs if necessary.
app.use(methodOverride("_method"));
var flashcardSchema = new mongoose.Schema ({
question: String,
translation: String
});
//creates model with above schema and has methods such as .find etc.
var Flashcard = mongoose.model("Flashcard", flashcardSchema);
app.get('/', (req, res) => {
Flashcard.find({}, function(err, allFlashcards){
if(err){
console.log(err);
} else {
res.render("home", {flashcardsDB: allFlashcards});
}
});
});
// Post to an input action
app.post("/flashcards", function(req, res) {
var question = req.body.question;
var translation = req.body.translation;
var newFlashcard = {question: question, translation: translation};
console.log(newFlashcard);
Flashcard.create(newFlashcard, function(err, newlyCreated){
if(err){
console.log(err);
} else {
res.redirect("/flashcards");
}
});
});
// Show info.
app.get("/info",function (req, res) {
res.render("info");
});
// Show all flashcards
app.get("/flashcards", function(req, res){
Flashcard.find({}, function(err, allFlashcards){
if(err){
console.log(err);
} else {
res.render("flashcards", {flashcards: allFlashcards});
}
});
});
// Show form to create new campground
app.get("/new", function(req, res){
res.render("new");
});
// Edit flashcard
app.get("/flashcards/:id/edit", function(req, res){
Flashcard.findById(req.params.id, function(err, selectedFlashcard){
if(err){
req.flash("error", "Flashcard not found!");
} else {
res.render("edit", {flashcard: selectedFlashcard});
}
});
});
// Update flashcard
app.put("/flashcards/:id", function(req, res){
Flashcard.findByIdAndUpdate(req.params.id, req.body.flashcard, function(err, updatedFlashcard){
if(err){
res.redirect("/flashcards");
} else {
res.redirect("/flashcards");
}
});
});
// Destroy Flashcard
app.delete("/flashcards/:id", function(req, res){
Flashcard.findByIdAndRemove(req.params.id, function(err){
if(err){
res.redirect("back");
} else {
//req.flash("success", "flashcard deleted.");
res.redirect("/flashcards");
}
});
});
app.listen(3000, () => console.log("Flashcard app is listening"));
I think the best aproach would be to pass the translator.js to the node.js server. Create a route on express for translations, and through that route you will call the translator.js and return the result. Then, on your html page, instead of running the translator.js directly, send a request to your server passing the necessary data.
On your app.js, you can do a route like this:
const translator = require('path_to_translator');
app.get('/translation', translator);
And then on your translator.js, you can export a function that will receive the parameters you need and return the result:
const bingTranslate = (req, res) => {
// YOUR CODE HERE
}
module.exports = bingTranslate
And then on your html you will make the button send a request to your server instead of calling translator.js, so you can change the value of the #bingTranslateOutput button based on the response you will receive from the server.

Express over Node.js - TypeError: Cannot read property 'forEach' of undefined

I'm building my first node/express app and am following this tut.
I am at a point where I am trying to get all JSON data and put it in an array to be sent to the template and rendered. When I try to run the app via CLI, I get the following error:
Directory Structure
The data output at the var blogsurlall location
hellotest.js
var routes = require('./routes/index');
var express = require('express');
var app = express();
var request = require("request");
var blogsurlall = "https://[JSON export URL location configured in a Drupal 8 view]";
app.set('view engine','ejs');
var server = app.listen (2000, function(){ console.log('Waiting for you on port 2000'); });
/* Get all global blogs data */
request({
url: blogsurlall,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
blogsdata_all = body;
}
// Create blogs array for footer.
var blogs = [];
// Fill up the array with blogs.
blogsdata_all.blogs.forEach(function(item){
blogs = blogs.concat(item);
});
app.locals.blogsdata = blogs;
});
app.use('/', routes);
index.js
var express = require('express');
var routes = express.Router();
routes.get('/', function(req, res){ res.render('default',{title: 'Home', body: 'blogsdata'}); });
routes.get('/about-us', function(req, res){ res.send('<h1>Lucius Websystems</h1>Amsterdam, The Netherlands'); });
routes.get('/about/:name?', function(req, res){ var name = req.params.name; res.send('<h1>' +name +'</h1>About text'); });
/* GET Blog detail page. */
routes.get('/blog/:blogid', function(req, res, next) {
// Place json data in a var.
var blogsdata = req.app.locals.blogsdata;
// Create array.
var blogItem = [];
// Check and build current URL
var currentURL = '/blog/' + req.params.blogid;
// Lop through json data and pick correct blog-item based on current URL.
blogsdata.forEach(function (item) {
if (item.title == currentURL) {
blogItem = item;
}
});
if (blogItem.length == 0) {
// Render the 404 page.
res.render('404', {
title: '404',
body: '404'
});
} else {
// Render the blog page.
res.render('blog-detail', {
blog: blogItem
});
}
});
module.exports = routes;
From the CLI error, it appears no blog data is even returned to be read into the array.
I have carefully gone through the tutorial several times and I think there are steps that may be implied that I am missing.
Can someone please help me understand how to get the blog data so that it can be read into the array and output to my template?
Also open to troubleshooting suggestions in comments.
Thanks for reading!
The error is raising in this line:
blogsdata_all.blogs.forEach(function(item){
As the error says, blogs is undefined.
If there is an error in the request or status code isn't 200, the body is not assigned to the variable, but you are not finishing the execution, so the variable in that case would be undefined.
Other possible problem is the json received doesn't have blogs as key of the body.
Check this both things and let us know if you found the problem

Post request not getting sent with Angular.js. What am i doing wrong?

So im trying to get a name with a click from the client, and send the name ( which i changed to json in order to actually be able to send the info) it to the server . Right now the server sends it back, and the client posts it to the index page (which im doing just so i can see the data that the server is getting). When i see the data its showing up as [object Object]. So Something is going wrong, im hoping someone can help me out.
index.html
<body>
<div ng-app="myApp" ng-controller="customersCtrl">
<table style="width:100%">
<tr ng-repeat="contact in databases.databases">
<td>{{ contact.name }} <button type="button"ng-click="addContactlist(contact.name)">Click Me</button></td>
<td>{{ contact.sizeOnDisk }} </td>
<td>{{ contact.empty }} </td>
</tr>
</table>
DB name clicked: <p ng-bind="DB_NAME"></p>
</div>
</body>
client.js
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
console.log("controller connected");
function refresh(){
// create contacklist route
$http.get('/databases').success(function(response) {
console.log("recived data requested");
$scope.databases = response;
});
}
// Call refresh to init cantacklist
refresh();
// add Doc to table
$scope.addContactlist = function(contactItem) {
alert("Working ");
$http.post('/collection', JSON.stringify({'contactItem': contactItem})).success(function(response) {
$scope.DB_NAME = response ;
});
console.log("posted: "+contactItem);
};
});// Controller
server.js
var express = require('express');
var path = require('path'); //core module
var databaseUrl = "localhost:27017/DB"; // default env
var bodyParser = require('body-parser');
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
ReplSetServers = require('mongodb').ReplSetServers,
ObjectID = require('mongodb').ObjectID,
Binary = require('mongodb').Binary,
GridStore = require('mongodb').GridStore,
Grid = require('mongodb').Grid,
Code = require('mongodb').Code,
assert = require('assert');
//configure app
var app = express();
var db = new Db('DB', new Server('localhost', 27017));
db.on('error', function (err) {
console.log('database error', err)
});
db.on('connect', function () {
console.log('database connected')
});
// store all html files in views
app.use(express.static(__dirname + '/views'));
// parses recived json input
app.use(bodyParser.json());
// store all js in Scripts folder
app.use(express.static(__dirname + '/scripts'));
// Technology not needed but good practice, especailly when serval people are working on it
app.get('/', function (req, res) {
res.sendFile('index.html');
});
// listen for contactlist get request, aka transfers the contacklist in mongo to client
app.get('/databases', function (req, res) {
console.log("-- recived GET request --");
db.open(function(err, db) {
// Use the admin database for the operation
var adminDb = db.admin();
// List all the available databases
adminDb.listDatabases(function(err, dbs) {
assert.equal(null, err);
assert.ok(dbs.databases.length > 0);
console.log(dbs);
res.json(dbs);
db.close();
});
});
});
// listen for contactlist get request
app.post('/collection', function (req, res) {
console.log("-- recived collection post request --");
console.log('req ' + req.body);
res.json(req.body);
db.open(function(err, db) {
// Grab a collection without a callback no safe mode
// once request is working will switch to re.body
var col1 = db.collection('DB');
});
});
// Implement a web server to listen to requests
app.listen(4444, function(){
console.log('ready on port 4444');
});
With fix
The response is an object, try this:
DB name clicked: <p ng-bind="DB_NAME | json"></p>
json filter converts the object in JSON notation: https://docs.angularjs.org/api/ng/filter/json

How to update and read a collection in MongoDB using Mongoose

I am having trouble with a project I am working on. I want to create a database in which I can store dates and links to YouTube videos in a MongoDB database. I am using Mongoose as the ORM. The problem seems to be that the database and collection is created and I can read and update it outside the routes but not inside (if anyone can understand what I am saying). I want to be able to make a GET request for the current items in the database on the /database route as well as make a POST to the /database route.
My code is below. Please help:
//grab express and Mongoose
var express = require('express');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//create an express app
var app = express();
app.use(express.static('/public/css', {"root": __dirname}));
//create a database
mongoose.connect('mongodb://localhost/__dirname/data');
//connect to the data store on the set up the database
var db = mongoose.connection;
//Create a model which connects to the schema and entries collection in the __dirname database
var Entry = mongoose.model("Entry", new Schema({date: 'date', link: 'string'}), "entries");
mongoose.connection.on("open", function() {
console.log("mongodb is connected!");
});
//start the server on the port 8080
app.listen(8080);
//The routes
//The route for getting data for the database
app.get("/database", function(req, res) {
Entry.find({}, function(err, data) {console.log(err, data, data.length); });
});
//The route for posting data on the database
app.post("/database", function(req, res) {
//test new post
var newMonth = new Entry({date: '1997-10-30', link: 'https://wwww.youtube.com/'});
newMonth.save(function(err) {
if (err !== null) {
//object was not save
console.log(err);
} else {
console.log("it was saved!")
};
});
});
//create an express route for the home page at http://localhost:8080/
app.get('/', function(req, res) {
res.send('ok');
res.sendFile('/views/index.html', {"root": __dirname + ''});
});
//Send a message to the console
console.log('The server has started');
Your GET request should have worked because a browser executes a GET request by default. Try the following.
app.get("/database", function(req, res) {
Entry.find(function(err, data) {
if(err) {
console.log(err);
} else {
console.log(data);
}
});
});
As far as testing your POST route is concerned, install a plugin for Google Chrome called Postman. You can execute all sorts of requests using it. It's great for testing purposes.

Express JS + Multer query database before file upload

I'm using Node.JS + Express.JS + Multer to handle file uploads. The problem is that I need to query the database to see if a file with this name has been uploaded in the past. If it hasn't been uploaded, then it should be accepted. Otherwise, the file should not be accepted. I'm trying to get this to work using the onFileUploadStart function; however, the database query is asynchronous and I see no way to return false given that the result of the query appears in a callback. If there is a way to execute the query synchronously, my goal will be easy to accomplish. Here is the code:
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var connection = mysql.createConnection({
//connection details
});
router.post('/upload', multer({
onFileUploadStart: function(file, req, res) {
var queryString = "SELECT count(fileName) as count FROM table WHERE fileName = ?;",
queryInserts = [file.originalname];
queryString = mysql.format(queryString, queryInserts);
connection.query(queryString, function(err, rows) {
if (err) {
// handle error
} else {
if (rows[0].count > 0) {
// file should not be accepted
} else {
// file should be accepted
}
}
});
},
dest: "./uploads/"
}), function(req, res) {
// do other stuff
});
Any ideas of how I can accomplish this will be greatly appreciated. Thanks.
My quick reaction would be to use promises. You could have your onFileUploadStart handler create a deferred, assign its promise to the active request object and handle the resolution or rejection of the promise. Then in the main handler for the upload route, you could use then.
I believe this would basically be the new code as applied to your current code. I Note that I am using the Q promises library, but there are other options (promises are also built into ES6 if you are using it).
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var Q = requires('q');
var connection = mysql.createConnection({
//connection details
});
router.post('/upload', multer({
onFileUploadStart: function(file, req, res) {
var deferred = Q.defer();
req.fileUploadPromise = deferred.promise;
var queryString = "SELECT count(fileName) as count FROM table WHERE fileName = ?;",
queryInserts = [file.originalname];
queryString = mysql.format(queryString, queryInserts);
connection.query(queryString, function(err, rows) {
if (err) {
// handle error
deferred.reject('You had an error...');
} else {
if (rows[0].count > 0) {
// file should not be accepted
deferred.reject('You had a duplicate file');
} else {
deferred.resolve(file); // ?? or something useful
// file should be accepted
}
}
});
},
dest: "./uploads/"
}), function(req, res) {
req.fileUploadPromise
.then(function(successResult){
// do other stuff
res.status(200).send('success');
})
.catch(function(errorResult){
// read the error result to provide correct code & error message for user
})
.done();
});

Categories

Resources