I just started learning Node.js and Express, and I'm currently trying to build a static file server. My question is: How do I prevent node from crashing every time the user inserts a wrong path?
Here's my code:
var express=require('express')
var fs=require('fs')
var app=express()
var server=app.listen(3000, listening)
console.log('Server Started on Port 3000')
function listening(){
console.log('Listening...')
}
app.use(express.static('website'))
app.get('/search/:page', goTo)
function goTo(req, res){
var data=req.params
fs.createReadStream('./website/'+data.page+'.html').pipe(res)
}
Thank you!
With try-catch your app will try to open the specified path. If it fails, your app will send an error instead of crashing.
Try this:
function goTo(req, res) {
var data = req.params;
try{
fs.createReadStream('./website/'+data.page+'.html').pipe(res);
} catch(err) {
res.send(err);
}
}
Hope it helps.
Related
I would like to know why is there a difference when I launch my project with NodeJS and when I launch directly with the HTML file.
Here is what I am supposed to have (with the HTML file) :
And here is what I have through NodeJS :
As you can see, it seems that the VueJS variable is not working anymore.
I don't know why because, i just create a short NodeJS program to launch this HTML file. I know that it is not a huge problem and can be easily solved.
Here is my JS program
var http = require ('http');
var fs = require('fs');
var port = 3000
var server = http.createServer(function(req,res){
res.writeHead(200,{'Content-Type': 'text/html'})
fs.readFile('index.html', function(error,data){
if (error) {
res.writeHead(404);
res.write('Error file not found');
}else {
res.write(data);
}
res.end();
})
})
server.listen(port,function(error){
if(error){
console.log('Something went wrong', error);
}else {
console.log("server is listening on port 3000");
}
})
Thank you guys in advance for your help. I look forward to see your responses.
As a javascript newbie, I want to create a front-end project with a very little backend solution using Node.js.
I have a user inteface with some variables and a button. These variables have to be passed to a simple .txt file(on my filesystem) and overwrite its content. For this, I'm using a nodejs script:
var fs = require('fs');
fs.writeFile('log.txt', 'This is my text', function (err) {
if (err) throw err;
console.log('Replaced!');
});
But I want this to work onClick, whereas this only works from the command-line.
So I have the two following problems:
I want to update the .txt file with the button click. So basically the above written code has to be executed, when I click the button. But I don't understand, how to connect the front-end with this nodejs file.
I want the content to be dynamical. I'm sure, once the first problem is solved, this will be straightforward, but right now I don't know this either.
I'm 100% sure I'm missing something(maybe a web-server, but even then, how?). I did my research but all I found was either an overkill or I didn't even understand it. Any help would be appreciated, a tutorial, an advice or just a keyword, that I can use for my research.
Have a look at express. It's a "Fast, unopinionated, minimalist web framework for node". With this you can build a small webserver:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World');
});
app.listen(3000); // Webserver is running on port 3000
If you run it and got to your browser on http://localhost:3000, it would print Hello World.
Now what you would do is calling your logging function every time a specific URL is requested.
var fs = require('fs');
function log(text, callback) {
fs.writeFile('log.txt', text, callback);
}
app.get('/', function (req, res) {
log('This is my text', function (err) {
if (err) throw err;
res.send('Replaced!');
});
});
Now when you click the button you need to make an AJAX request to the server (maybe using jQuery).
Node.js doesnt have a built in front-library like some other scripting languages such as Python or VB. To create a node.js your intuition was correct in that you will need your app to expose itself as a web-server.
The popular library to do this is called express and it is very easy to get started.
I suggest that you follow the express quickstart tutorial to get into it.
From here you can wrap your code inside a route of the webserver (say /save) for example
var fs = require('fs');
var express = require('express');
var app = express();
app.get('/save', function (req, res) {
fs.writeFile('log.txt', 'This is my text', function (err) {
if (err) throw err;
console.log('Replaced!');
res.send('Replaced!')
});
})
app.listen(3000, () => console.log('Example app listening on port 3000!'))
With this example with the dependencies installed opening localhost:3000/save in your browser would cause your code to be run.
So I'm querying the Blizzard API Battle.Net for some information, character name and the realm they're in. Ofcourse it's possible for a user to query for a character that Does Not Exist, so Blizzard throws a 404 back to me and my server.js file doesn't know what to do with it even though I put something in place to handle it.
Releveant server.js code:
var express = require('express');
var app = express();
var fs = require('fs');
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json();
const blizzard = require('blizzard.js').initialize({apikey: "dummy"});
app.use(express.static(__dirname + '/Source'));
//Listen on port 3000
app.listen(3000, function() {
console.log("Launch successful. To access app, open your browser and insert the following URL into your address bar: http://localhost:3000/");
});
app.post('/buttonpress', jsonParser, function (req, res) {
blizzard.wow.character(['profile'], { origin: 'us', realm: req.body.realm.name, name: req.body.name })
.then(response => {
if(response.status != 200){
res.send("That character doesn't exist! Please enter a valid character name.");
} else {
console.log(response.data);
res.send(response.data);
}
});
});
I attempt to handle anything that's not a 200 by sending something to the client to tell the user: Character DNE!, but instead vscode gives me some red error codes mentioned in the title of this post (in vscode debugger anyway).
When I try this from a command line, just running node server.js, nothing happens when I click the Search Button. I've set breakpoints and it looks like the function doesn't get a response from the server. So the 404 is happening no matter what but I can't figure out how to handle it.
Try placing your app.listen below/after your app.post Express.js runs in a middleware functionality so your listen is blocking all preceding code.
I'd like to start my node js application on boot. Therefore I start a service from Systemd:
[Unit]
Description=Node.js server
After=network.target
[Service]
ExecStart=/usr/bin/node /var/www/Raspberry-Pi-Status/js/server.js
Restart = always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=nodejs-server
Environment=NODE_ENV=production PORT=8000
Environment=PYTHONPATH=/usr/bin/python
[INSTALL]
WantedBy=multi-user.target
The server.js looks like this:
var util = require('util'),
spawn = require('child_process').spawn,
py = spawn('python',['temperature.py'],{detached: true});
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'monitor',
password : 'password',
database : 'temps'});
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs'),
sys = require('util'),
exec = require('child_process').exec,
child;
// Listen on port 8000
app.listen(8000);
// If all goes well when you open the browser, load the index.html file
function handler(req, res) {
fs.readFile(__dirname+'/../index.html', function(err, data) {
if (err) {
// If no error, send an error message 500
console.log(err);
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
py.stdout.on('data', function(data){
console.log('testing');
date = new Date().getTime();
temp = parseFloat(data);
io.sockets.emit('temperatureUpdate',date,temp);
});
// When we open the browser establish a connection to socket.io.
// Every 5 seconds to send the graph a new value.
io.sockets.on('connection', function(socket) {
console.log('user connected');
});
The node.js application should start a python script which reads out a temperature sensor. When I start node.js via the console everything works fine. However, when I start from Systemd, the python script is not spawned.
What's the problem there? Am I missing something?
Thanks in advance
Alexander
An issue could be the difference in the current working directory when run manually vs systemd. The spawn call used is documented has a default to inherit the current working directory.
When run via the shell, that would be whatever directory you are currently in. In man systemd.exec, you find the "WorkingDirectory=` directive, which documents systemd's default current working directory: "defaults to the root directory when systemd is running as a system instance".
So if your temperature.py is located in /var/www/Raspberry-Pi-Status, then set:
workingDirectory=/var/www/Raspberry-Pi-Status in your `[Service]` section.
i'm currently working on my thesis project which consists of an educational desktop videogame for public and private schools in my city.
I also really like electron so i thought it would be a nice idea to make my app using it, however it's here when the problem starts. My university demands that all apps must use a relational database (SQL) and not non-relational db like MongoDB. Since the database i'll have it's relative small i chose SQLite.
For some reason i began to get a certain error:
C:\Users\Alejandro\Documents\Proyectos\express\node_modules\sqlite3\lib\binding\electron-v1.4-win32-ia32\node_sqlite3.node
After some research i found out that the reason was because electron executes on the client side and databases can only work on server side, to solve this issue i installed express on my app to execute a server in the background while electron executes the client (local client-server desktop app).
After some coding this was the result:
Main.js (Electron code changes)
const express = require('./resources/express')
const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow
const path = require('path')
const url = require('url')
// Keep a global reference of the window object, if you don't, the window will be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadURL('http://localhost:8080/')
// Emitted when the window is closed.
mainWindow.on('closed', function () {
console.log('app server is closing')
express.closeServer()
mainWindow = null
})
}
Express.js (Express code):
const http = require('http')
const express = require('express')
const dbmanager = require('./dbmanager.js')
app = express()
app.set('view engine', 'pug')
app.get('/',function(request, response){
console.log('server started :D')
response.end()
})
app.get('/checktable',function(request, response){
dbmanager.createTable()
response.redirect('/receive')
})
app.get('/receive',function(request, response){
dbmanager.selectAll(function(err,data){
data.forEach(function(row){
console.log(row.id + " " + row.name + "Edad: " + row.age)
})
response.render('index', { title: 'Usuario', message: data[0].name + " " + data[0].last })
response.end()
})
})
var server = http.createServer(app).listen(8080)
var serverManager = {}
serverManager.closeServer = function(){// This executes
console.log('This is executing')
console.log('Server should close now')
server.close()
}
module.exports = serverManager
dbmanager.js (SQLite queries)
var sqlite3 = require('sqlite3').verbose()
var db = new sqlite3.Database('memory')
var queryManager = {}
queryManager.createTable = function(){
db.run("CREATE TABLE IF NOT EXISTS students (id int, name TEXT,last TEXT, age int)")
}
queryManager.deleteTable = function(){
db.run('DROP TABLE students')
}
queryManager.insertStudent = function(student){
var stmt = db.prepare("INSERT INTO students VALUES (?,?,?,?)")
stmt.run(student.id,student.name,student.last,student.age)
stmt.finalize()
console.log('Insert Successful')
}
queryManager.selectAll = function(callback){
db.all('SELECT * FROM students', function(err,rows){
if(err)
{
throw err;
}
else
{
callback(null, rows);
}
})
}
module.exports= queryManager
Index.pug (view)
html
head
title= title
body
table#table
h1= message
Before trying to execute the entire app i tried only executing the server and it worked.
I modified the npm start line from "electron ." to "electron . && node ./resources/express.js" so i could execute both the client and the server.
At that moment i commented all the lines related to the dbmanager.js to test if the client and server were working.
Needing to close the server at the moment the app windows was close i created a function to close the server when window close funcion is called, but it doesn't.
That's the first problem. The second problem shows up when i undo the comment on the dbmanager lines, i get the same error as before:
'C:\Users\Alejandro\Documents\Proyectos\express\node_modules\sqlite3\lib\binding\electron-v1.4-win32-ia32\node_sqlite3.node'
Am i doing something wrong? Please i really need help.
You're spinning up an Express server on the same machine as your Electron app, if your server can access a local database then what makes you think your app can't? You don't need an Express server. To use the sqlite3 module in an Electron app you just have to rebuild it to target the specific Electron version using one of the documented approaches.