Problem
I just started out with Node.js my plan was to first set up a Server with some basic HTML and static files(css,js).
But when i try to Serve the static files with express.js or even without express the js/css code is getting replaced from my index.html code. Without Node.js everything seems to work fine i even tried it with flask in python which worked fine too.
Are there any common reasons for this?
Node.js code
var http = require("http");
var fs = require("fs");
var express = require("express");
var app = express();
app.use("/", express.static("public"));
http
.createServer(function(req, res) {
fs.readFile("index.html", function(err, data) {
if (err) {
res.writeHead(404, { "Content-Type": "text/html" });
return res.end("404 Not Found");
}
res.writeHead(200, { "Content-Type": "text/html" });
res.write(data);
return res.end();
});
})
.listen(8080);
Pictures
So even though you are using express to serve static files, you are not using express as server instead of that you are making a manual server which serves index.html for EVERY request.
http
.createServer(function(req, res) {
fs.readFile("index.html"....);
})
.listen(8080);
What this code means is create a server, and for each request read the index.html file and serve this
So when the request is http://localhost:8080/css.css it doesn't discriminate.
I would recommend reading about creating servers in node a little more. But the solution is use express as server.
var http = require("http");
var fs = require("fs");
var express = require("express");
var app = express();
app.use("/", express.static("public"));
app.listen(8080, ()=>{
console.log('Server started');
})
This will work just fine GIVEN that index.html IS IN A FOLDER NAMED PUBLIC
From the doc,
For example, use the following code to serve images, CSS files, and
JavaScript files in a directory named public:
app.use(express.static('public'))
Now, you can load the files that are
in the public directory:
Note, if your files are in your project root you can use:
app.use("/", express.static("."));
Related
I've tried to write node server which would run React app created by create-react-app. Actually, something strange happens and I don't have any clue what I'm doing wrong (run app as node server/index.js):
export default (app, dirname) => {
app.use(favicon(path.join(dirname, '..','build', 'favicon.ico')));
app.use(express.static(path.join(dirname, '..','build')));
// initialize routers
bootRotes(app);
if (process.env.NODE_ENV === AVAILABLE_ENVIROMENTS.DEVELOPMENT) {
expressBootDev(app, dirname);
} else {
app.get('/*', (req, res) => {
res.sendFile(path.join(dirname, '..', 'build', 'index.html'));
});
}
}
build folder contains build react app which created the following command npm run build
Strange things are happening when after uploading index page it tries to upload static content. For example http://localhost:5000/static/js/2.30e86b6e.chunk.js. Browser just adds / after each static content url and it turns to http://localhost:5000/static/js/2.30e86b6e.chunk.js/ and of course this url doesn't match to express.static middleware.
Moreover, I've checked via Postman, that url GET http://localhost:5000/static/js/2.30e86b6e.chunk.js withot / at the end provides content which is expected.
I work with PRODUCTION env, it means that expressBootDev doesn't have any impacts.
Has anybody has the same issue? I've spent whole day and don't know hopw to fix it.
When I'm creating a simple code in a root app folder with almost the same logic and run as node server.js and it works as expected:
//server.js
const express = require('express');
const favicon = require('express-favicon');
const path = require('path');
const port = process.env.PORT || 8080;
const app = express();
app.use(favicon(__dirname + '/build/favicon.ico'));
app.use(express.static(__dirname));
app.use(express.static(path.join(__dirname, 'build')));
app.get('/ping', function (req, res) {
return res.send('pong');
});
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(port);
And I don't see any principal difference
var fs = require('fs');
var express = require('express');
var router = express.Router();
// GET: Sent some basic info for usage
router.get('/', (req, res, next) => {
var fname = __dirname + '/../public/index.html';
var val = fs.readFile( fname, 'utf8', ( err, data) => {
//send can only be called once, write can be called many times,
// in short res.send(msg) == res.write(msg);res.end();
res.writeHeader(200, {"Content-Type": "text/html"});
res.write(data);
res.end();
});
});
module.exports = router;
Here is the example how you can do a static file serving with node.
https://github.com/msatyan/ApiServe1/blob/master/routes/index.js
The full project is
https://github.com/msatyan/ApiServe1
FYI: Node.js with HTTP1 is not an efficient for static file serving by design, I believe HTTP2 support in node has addressed this problem. The reason for inefficiency with HTTP1 is that it has to take the file content read at native layer to JavaScript layer and then send it through HTTP server.
I am new to "A Small Orange" and I am trying to run an express app in small orange following this link
I first created the following directory structure
/home/user/servercode/myapp with tmp directory and app.js file
/home/user/public_html/clientCode/myapp with .htaccess
/home/user/servercode/myapp/tmp contains an empty restart.txt file
In /home/user/servercode/myapp, I ran
npm init
npm install express --save
This is my app.js. Pretty much same as the one in the link mentioned in the post
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World Express App');
});
if (typeof(PhusionPassenger) != 'undefined') {
console.log( 'Example app listening with passenger' );
app.listen('passenger');
} else {
console.log( 'Example app listening with 3000' );
app.listen(3000);
}
.htaccess has 644 permission level and contains this
PassengerEnabled on
PassengerAppRoot /home/user/serverCode/myapp
SetEnv NODE_ENV production
SetEnv NODE_PATH /usr/lib/node_modules
When I try to access myapp, I get this error
Cannot GET /myapp/ and 404 in browser console
I could get a normal nodejs application running without express with the below content in app.js
var http = require('http');
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
server.listen(8000);
console.log("Server running at http://127.0.0.1:8000/");
But not able to get express app running
You need to add route in you application as :
app.get('/myapp', function(req, res){...});
I am integrating a 3rd party template which has a slideshow written using Mootools. The nodejs is configured with express and ejs
The data for the slideshow comes from a few xml files. For example data.xml. I placed the data.xml in public folder and added the following code to server.js (the main file)
app.use(express.static(__dirname + '/public'));
app.post('/data.xml', function(req, res){
res.contentType('application/xml');
res.sendFile('/data.xml');
});
Unfortunately this does not seems to work. I can see the file if I type the url
http://localhost:8080/data.xml
But the response I see in firebug is
" Cannot POST /data.xml "
I am assuming Mootools is trying to access the file using some POST method. Any suggestions for this problem?
when you are sending the file with sendFile() you need to point to the absolute address check this. note that I have the data.xml in the main folder.
you can access the file with localhost:8080/data (not localhost:8080/data.xml) and also as this is a post, you cannot access it through browser. use postman instead. or if you need it to be accessible on browser you need to change the protocol to get.
var express = require('express');
var path = require('path');
var app = express();
// you don't need this line!
// app.use(express.static(path.join(__dirname)));
app.post('/data', function(req, res){
res.contentType('application/xml');
res.sendFile(path.join(__dirname , 'data.xml'));
});
var server = app.listen(8080, () => {
console.log('Started listening on 8080');
});
I'm having trouble with Node JS.
With the Apache/php model, I'm able to make a standalone save.php file (takes a post request, saves to a txt file) without fooling around with the Apache server.
<?php file_put_contents ( 'content.txt' , $_POST['myData']);?>
In Node, I have server.js started to serve up whatever files I have in /public :
var express = require('express');
var app = express();
app.use(express.static('public'));
app.use(express.static(__dirname + '/public'));
app.use(function(req,res, next){
if(req.accepts('html')){
res.status(404).sendFile(__dirname+'/public/404.html');
}
});
app.listen(process.env.PORT || 80);
How can I make a save.js file, e.g. /public/test_project1/save.js, that can be executed on an HTML form submission?
var fs = require('fs');
fs.writeFile("content.txt", ???post data???)
Is there any way to avoid explicitly defining the app.post()... in server.js every time I make a new js file in /public? I'm looking for an architecture that allows me to create one node server to host various separate project files in /public
First you need to create a endpoint for your post request, then parse form data, a option could be body-parser middleware , finally save the content.
Something like:
var express = require('express');
var app = express();
var bodyparser = require("body-parser");
app.use(bodyparser.urlenconded({extended:true}); // middleware for parse form data
app.use(express.static('public'));
app.use(express.static(__dirname + '/public'));
app.post("/endpoint",function(req,res){
//myData is input name
var content = req.body.myData;
fs.writeFile("content.txt", content,function(err){
res.end("done");
})
})
app.use(function(req,res, next){
if(req.accepts('html')){
res.status(404).sendFile(__dirname+'/public/404.html');
}
});
app.listen(process.env.PORT || 80);
Then you make a POST request to /endpoint with myData as input.
Here's what I came up with - modifying server.js to handle any POST requests within that folder. Is this dangerous?
app.post('/:folder/:file',function(req, res){
filepath=__dirname+'/public/'+req.params.folder+'/'+req.params.file;
fs.stat(filepath, function(err, stat) {
if(err == null) {
console.log('File exists');
var anyFile=require(filepath)(req.body);
res.redirect(anyFile);
} else if(err.code == 'ENOENT') {
res.send('File does not exist.');
} else {
res.send('Error: '+ err.code);
}
});
});
Is there any way I can always serve the same file?
So, if they go to website.com/ajsdflkasjd it still serves the same file as website.com/asdnw
I would like to do this using express with node.
The file I have is a static html file, not a jade file.
By the way, the reason I'm wanting to do this, in case you were wondering, is I have an angularjs app that handles all the routing for me. So, all I need to do is serve that one page, and it will take care of the rest.
Thanks in advance!
new answer
const app= require('express')()
// static file serve
app.use(express.static(__dirname))
// not found in static files, so default to index.html
app.use((req, res) => res.sendFile(`${__dirname}/index.html`))
app.listen(3000)
old answer
var express = require('express');
var bodyParser = require('body-parser')
var path = require('path')
var app = express();
// url encoding
app.use(bodyParser.urlencoded({extended:false}));
// gzip
// redirect all html requests to `index.html`
app.use(function (req, res, next) {
if (path.extname(req.path).length > 0) {
// normal static file request
next();
}
else {
// should force return `index.html` for angular.js
req.url = '/index.html';
next();
}
});
// static file serve
app.use(express.static(__dirname))
app.listen(3000)
Below is what I'm using express with angularjs in my project. It will always send index.html unless the browser requests resource files (images, css, js, etc.) which contains extname.
var express = require('express');
var app = express();
app.configure(function () {
// url encoding
app.use(express.urlencoded());
// gzip
app.use(express.compress());
// redirect all html requests to `index.html`
app.use(function (req, res, next) {
if (path.extname(req.path).length > 0) {
// normal static file request
next();
}
else {
// should force return `index.html` for angular.js
req.url = '/index.html';
next();
}
});
// static file serve
app.use(express.static(__dirname));
});
Basic configuration for Express 4 is:
var express = require('express');
express()
.get(/.*/, function(req, res) {
res.sendFile('index.html', {
root: __dirname
});
})
.listen(8080);
Working example
Those snippets with GZip, BodyParser etc. are pretty cool, but I think over-complicated if you want to just test your single page app. Of course you can add all this "production stuff" when it starts to be needed.
Read more:
sending files
routing
Here a simple implementation with ExpressJs to create a virtual host and whenever return the index.html
var express = require('express');
var app = express();
var vhost = require('vhost');
// Function to create virtualhost
function createVhost(domain,rootDirectory){
var exp = express();
exp.use(express.static(rootDirectory));
exp.get(/.*/,function(req,res){
res.sendFile('index.html',{root:rootDirectory});
})
app.use(vhost(domain,exp));
}
// Virtual Host to create
createVhost('example.com','/home/[user]/[www]/[example.com]');
createVhost('othersite.com','/home/[user]/[www]/[othersite.com]');
// Start Server
app.listen(80,function(){
console.log('Node server on port 80');
});
Remember:
Add the domains in the "/etc/host" (in linux)
127.0.0.1 example.com
127.0.0.1 othersite.com
And run in the terminal the "app.js" with "sudo" for port 80
~/home/[server]$ sudo node app.js
You can do this in both angular as well as node side.
In Node side you can do something like this:
res.sendfile('<ur html file path');
In Angular if you using ui-router you can make use of
$urlRouterProvider.otherwise('/otherwise');
and this otherwise state needs to be defined as well
$stateProvider
.state("otherwise", { url : '/urPage'...})
If you using ngRoute, you can do
$routeProvider.otherwise({redirectTo: '/urPage'});
UPDATE
Since your routers are not configured to show a default urPage, in the server you can have something as:
var app = express.createServer();
app.get('/urPage',function(req,res){
res.sendfile('<ur html page>');
});