Node express static files - node.js

I'm working with node and express. I try to create a simple server using express.static. I have a file in the following folder on my server :
client/index.html
However, when I try this url : http://myServer.com/index.html, the server answers that :
Cannot GET /index.html
Here, you will find my used code :
var express = require('express');
var app = express();
app.use(express.static('client'));
/*
app.get('/', function (req, res) {
res.send('Hello World!');
});*/
var server = app.listen(8080, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
My file index.html is available. I already used other way to keep this like by using
app.get('/index.html', function (req, res, next) {
var options = {
root: __dirname + '/client/',
dotfiles: 'deny',
headers: {
'x-timestamp': Date.now(),
'x-sent': true
}
};
res.sendFile("index.html", options, function (err) {
if (err) {
console.log(err);
res.status(err.status).end();
}
else {
console.log('Sent:', "index.html");
}
});
});
And this approach works.

You said that you were trying this URL:
http://myServer.com/index.html
But, your server is listening on port 8080, so you need to use this URL:
http://myServer.com:8080/index.html
or this:
http://myServer.com:8080
Because express.static() will automatically use index.html for the / path.
FYI, when I run your first block of code on my laptop with the proper URL, it works just fine. The browser shows me the contents of client/index.html where "client" is a sub-directory below where my app.js file is run from to start the server.

Related

In what folder should I install my socket.io app?

I'm on shared hosting and let's say my domain is example.com and I want to run a socket.io app in one folder called myapp so it can be accessed from here: example.com/myapp. Then I install node.js and put the app.js file right under example.com/myapp so whenever I access it I get the confirmation message: hello world node.js. The file looks like this:
const http = require('http')
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello world node.js \n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
next, I install the modules, inside the same folder: npm install express and npm install socket.io so I get a folder called node_modules directly under /myapp so the path will look like myapp/node_modules, right?
My question is, where do I put the files of my socket.io app (it's a chat)? The index.js file looks like this:
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
socket.on('chat message', msg => {
io.emit('chat message', msg);
});
});
http.listen(port, () => {
console.log(`Socket.IO server running at http://localhost:${port}/`);
});
Should I put it in the same folder as app.js or somewhere else? Because if I put it along with app.js then this happens: if I access example.com/myapp I get the "hello world" page, which I don't want whereas in order to see the front page of my chat app I need to add a / like this: example.com/myapp/ but that is not accepted by cpanel as a valid application on the application manager. What's the right method to do this?
Thank you.

Setup Vue.js with nodejs server

Im trying to get nodejs http to serve a vuejs application.
Vue is configured as SPA with history mode enabled.
My nodejs server is set up like this:
http.createServer((req, res) => {
fs.readFile('dist/index.html', 'utf-8', (err, content) => {
if (err) {
console.log('We cannot open "index.html" file.')
}
res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8'
})
res.end(content)
})
}).listen(port, () => {
console.log('Server listening on: http://localhost:%s', port)
})
Taken from here: https://router.vuejs.org/guide/essentials/history-mode.html#native-node-js
This does indeed start the server and i can navigate to localhost:3000 but see a blank page.
Problem is, that with this configuration the server always returns the index.html file. Which is not wanted for static files like .js files, which results in errors.
How do i have to configure my http server so Vue will work as expected?
You have to serve the whole dist folder, not just the index file so it can get the whole vuejs app.
You can make this easier for you by using modules like https://github.com/cloudhead/node-static
const static = require('node-static');
const http = require('http');
const distFolder = new static.Server('./dist');
http.createServer(function (req, res) {
distFolder.serve(req, res);
}).listen(port, () => {
console.log('Server listening on: http://localhost:%s', port)
})
With expressjs this would become
const express = require('express')
const app = express()
app.use(express.static('dist'))
app.listen(port, () => {
console.log('Server listening on: http://localhost:%s', port)
})
EDIT:
Fallback for history mode:
http.createServer(function (req, res) {
distFolder.serve(req, res, function (err, result) {
// Fallback for history mode
if (err !== null && err.status === 404) {
distFolder.serveFile('/index.html', 200, {}, req, res);
}
});
}).listen(port, () => {
console.log('Server listening on: http://localhost:%s', port)
})
You are right, the example is a bit misleading. They say "If the URL doesn't match any static assets, it should serve the same index.html page that your app lives in." on the page but example completely ignores other static files.
You can use express - see this SO answer

Nodejs - BrowserSync running on express server

I want to pull a URL from the DB and use it as the proxied URL. However the setup I've come up with initializes a new BrowserSync server for each URL, using incrementing port numbers.
Is there a way to accomplish this without initializing a new BrowserSync server every time?
Or should I be using another approach?
var bs = require("browser-sync");
var express = require("express");
var router = express.Router();
var app = express();
router.get("/", function(req, res){
var proxyUrl = getUrl() //get url from db (www.example.com)
bs.create("bs1").init({
notify: false,
open: false,
ui: false,
port: 10000,
proxy: proxyUrl
});
res.send();
});
app.use(router);
app.listen(8080, function(){
console.log('listening on *:8080');
});
The above is fine(ish) but is it good practice to be initializing a new server for every URL (potentially thousands)?
And is it safe to be exposing a new port number to every user of the system? (Can I mask this with a subdomain?)
Update
My end goal is to use a unique subdomain to refer to each proxy url.
For example:
sub1.mysite.com proxies www.example.com,
sub2.mysite.com proxies www.example2.com
Browser-sync will not work as the proxy is tie to server setup.
I use following packages:
express
express-http-proxy
vhost (express vhost)
const port = 8080;
var app = require('express')();
var proxy = require('express-http-proxy');
var url = require('url');
var vhost = require('vhost');
app.listen(port);
/* Assuming getUrl() will return an array of sites */
// var sites = getUrl();
// DO NOT put '/' at the end of site
var sites = [
'http://www.bing.com',
'http://samanthagooden.com',
'http://www.courtleigh.com'
];
var i = 0;
sites.forEach(site => {
i++;
var subDomain = 'sub' + i + '.mysite.com';
app.use(vhost(subDomain, proxy(site, {
forwardPath: (req, res) => url.parse(req.url).path,
intercept: (rsp, data, req, res, callback) => {
if (res._headers['content-type']) {
var contentType = res._headers['content-type'];
if (
contentType.indexOf('text') !== -1 ||
contentType.indexOf('javascript') !== -1
) {
// Replace link if content-type = text or javascript
var reg = new RegExp(site, 'g');
res.send(data.toString().replace(reg, ''));
} else {
res.send(data);
}
} else {
res.send(data);
}
}
})));
console.log(subDomain + ':' + port + ' proxy: ' + site);
});
The above example will create following proxies:
sub1.mysite.com:8080 proxy: www.bing.com
sub2.mysite.com:8080 proxy: www.example.com
Maybe I'm misunderstanding what you are trying to do, but Browsersync and express seems a bit overkill in this case, why not just use node-http-proxy with the native http module?
var http = require('http')
var httpProxy = require('http-proxy')
var options = ...
var proxy = httpProxy.createProxyServer(options)
var server = http.createServer(function (req, res) {
var proxyUrl = getUrl()
proxy.web(req, res, { target: proxyUrl })
})
server.listen(8080, function () {
console.log('listening on *:8080')
})
As per me If you want SAAS service using proxy is not the good idea to go is what am thinking.. if you are going with proxy for each client will create process with new port... My Solution is to create node server with listen localhost and map *.domain.com to the server..
If you are using individual database for each client :-
in node logic get cname from request host and use that reference to connect database.
Final Controller code would be..
var express = require('express');
var router = express.Router();
var MongoClient = require('mongodb').MongoClient;
/* GET home page. */
router.get('/', function(req, res, next) {
var client = req.subdomains[0];
console.log(client);
MongoClient.connect('mongodb://localhost:27017/'+client, function(err, db) {
if (err) {
throw err;
}
db.collection('app1').find().toArray(function(err, result) {
if (err) {
throw err;
}
console.log('data');
console.log(result);
});
});
res.render('index', { title: 'Express' });
});
module.exports = router;
~
~
In future if you get more clients you can implement node cluster or standard Ubuntu cluster using webservice

HTTPS with NodeJS swagger-express-mw npm package

I am using swagger-express-mw NPM package for creating REST services, when I run the project with "swagger project start" then it publishes the APIs over HTTP, how can I use HTTPS instead.
I have used HTTPS using vanilla npm packages as below:
var fs = require('fs');
var https = require('https');
var app = require('express')();
var options = {
key : fs.readFileSync('my.private.key'),
cert : fs.readFileSync('my.certificate.cer')
};
app.get('/', function (req, res) {
res.send('Yuhooo! Response over HTTPS!!! ');
});
https.createServer(options, app).listen(8443, function () {
console.log('Server started # 8443!');
});
But I am not sure how to achieve the same with swagger-express-mw, Below is the code snippet from my app.js which starts the listener. Not getting any option to use HTTPS as the protocol here
SwaggerExpress.create(configuration, function(err, swaggerExpress) {
if (err) { throw err; }
// install middleware
swaggerExpress.register(app);
var port = config.get('server.port') || process.env.PORT || 8080;
app.listen(port);
console.log('Server started at port %d', port);
});
var swaggerDoc = jsYaml.load(fs.readFileSync('./api/swagger/swagger.yaml'));
// Initialize the Swagger middleware for the api doc purpose
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
// Serve the Swagger documents and Swagger UI
app.use(middleware.swaggerUi());
});
app.listen is simply a shortcut you can use
SwaggerExpress.create(configuration, function(err, swaggerExpress) {
if (err) { throw err; }
// install middleware
swaggerExpress.register(app);
var port = process.env.PORT || 443;
https.createServer(options, app).listen(port, function () {
console.log('Server started # %s!', port);
});
});
Using Swagger 2.0 spec with middleware your swagger configuration file can be set to only accept certain schemes:
# Schemes is statically set here but will be overridden in app.js with
swagger object
schemes:
- https
You can review the specification and go to Fixed Fields: http://swagger.io/specification/

Html content is not showed in NodeJS

I'm trying to create an http server. The server is created correctly but does NOT show the html content. It works when I do it without listeners. What am I failing then?
app.js
var server = require("./server.js");
server.server3((req, res, html) => {
res.writeHead(200, {"Content-Type": "text/html"});
html.pipe(res);
res.end();
}, 3000, "./index.html");
server.js
function Server3(applyFunction, port, path) {
var fs = require("fs"),
html = fs.createReadStream(path.toString().trim()), // Create stream from path
http = require("http");
html.on("data", _ => {})
.on("end", () => { // create server when all data is ready
http.createServer(function(req, res){ // createServer method
applyFunction(req, res, html); // execute the function
}).listen(+port); // add the port
});
}
module.exports.server3 = Server3;
If you're just trying to create an HTTP server on node.js, using the express framework (npm install express --save) would simplify your life a great deal. If you place the index.html file in the same directory as app.js, you can create the server with the following 5 lines of code:
// Setup Express
const express = require("express");
const app = express();
// Use main directory to find HTML file
app.use(express.static(__dirname));
// Render index.html
app.get("/", (req, res) => res.render("index"));
// Start Server on port 3000
app.listen(3000, () => console.log('Server started on port 3000'));

Resources