I don't know if this is a limitation to node-static or is it a bug in my code, but I can't seem to get it to serve files above or beyond the current directory. My current directory structure is this:
project
public
...public stuff here...
system
core
server.js
server.js lives in core directory, making the path to public as ../../public - but this code won't run. It returns a 404.
staticServer = new (static.Server)('../../public');
webServer = http.createServer(function (request, response) {
staticServer.serve(request,response);
})
webServer.listen(appServerConfig.port, appServerConfig.address);
However, if I change the structure to make the public folder live beside server.js and change the code accordingly, it works:
project
system
core
server.js
public
...public stuff here...
staticServer = new (static.Server)('./public');
webServer = http.createServer(function (request, response) {
staticServer.serve(request,response);
})
webServer.listen(appServerConfig.port, appServerConfig.address);
Why is this so?
Be aware that using relative paths will resolve those paths relative to the current working directory of the node.js process, that is, the directory you were in when you ran node server.js. So as coded, your could looks OK to me as long as you are in the core directory when you launch node. Are you sure you always launch node from the core directory?
If you want to be independent of the cwd (more robust IMHO), use __dirname to get the absolute directory path of the current file and then tack on your relative paths to that: __dirname + '/../../public'.
Beyond that, consider fs.realpath to resolve those. I can't say whether node-static in particular has special code to prevent this, but most other modules I've seen such as connect's static middleware will happily serve any arbitrary directory without special restrictions.
Related
I recently decided to update the way I serve my index.html file from
app.use('/', express.static(__dirname + '/..'));
to
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/../index.html'));
});
Both work fine as they both properly serve my index.html file. However when I switch to using app.get ...
I can no longer get my paths to work in my index.html file.
For example, I have a .svg file inside my index.html file that it serves as follows:
<img src="dist/images/svg/favicon.svg" width="128" height="128">
The request which now fails ( 404 error ) looks like this in the console:
http://localhost:3000/dist/images/svg/favicon.svg
I have tried adding in the root directory as follows:
<img src="ll-server/dist/images/svg/favicon.svg" width="128" height="128">
but this does not help - both give 404 errors.
Why is changing the way I serve my index.html file breaking my paths inside the index.html file?
How can I fix this?
Why is changing the way I serve my index.html file breaking my paths inside the index.html file?
use runs some code for every URL which starts with the specified path. That code (static) looks at the URL, finds a matching file on the specified path, and serves up that file.
get runs some for for a specific URL (at least in this case because you haven’t used * or a parameter) and that code serves up index.html and only index.html.
Your images have stopped working because you removed the code which serves up the the HTML AND the images with code which serves up ONLY the HTML.
How can I fix this?
Put the code back the way it was. The changes you made are not reasonable.
——-
Then fix your security issue.
The directory you are serving your static files from is the parent if the directory your JS module lives in. This means you have given your JS module (and probably all your JS modules) URLs on your webserver.
Don’t expose your server-side business logic.
Change your directory structure. A typical one is:
/ (containing the project)
/src/ (containing the JS)
/static/ (containing the static files)
I understand how to return a file using express with:
res.sendFile(path.join(__dirname, 'fileName.html'))
And I understand how to serve up a folder using:
app.use('/customAPI', express.static('folderName'));
using the documentation here.
The folder with the UI is created using angular 4 build. So, it all goes into one folder creating a index.html and a bunch of *.bundle.html files.
However, I don't understand how to serve up a the UI after doing some logic. For example:
router.get("/", function (req, res) {
let myParam = req.query.whatever;
if (whatever) {
res.redirect('//google.com'); //this works fine
}
else {
//I don't know what to do here
app.use("/somePath", 'dist'); //won't work because what do I put in "somePath"?
res.sendFile(path.join(__dirname, '../../dist/index.html'));
//^ this only serves up the file but fails because it can't find the library files that index.html needs to load.
}
});
I've tried going down the road of trying to use res.render but I'm not 100% sure if that is what I'm looking for.
Question: How do I serve up a folder containing all ui information correctly
When you serve a specific path these are sending the content only for that path, for example an HTML with the interface, the HTML file can make calls to other files, like CSS, JS etc ...
You need to serve the static files in a public folder
app.use('/static', express.static(path.join(__dirname, 'public')))
All files in the static folder will be served in the url /static/filename
In the html of the path, you must include the resources of the static folder that you need
My workflow is as follows:
1) I build my front-end usingwebpack with all the cool [chunkhash] to make sure my generated files have different names when there are changes and therefore busting the cache and finish with something like:
app.asdf4354234asdfchunkhashname.js
app.asdf4354234asdfchunkhashname.css
index.html
Awesome!
2) I then have a node express server to serve the above pages and an API, short version:
var express = require('express');
app.use(express.static(path.join(__dirname, '../client'))); // Where the wekback files are located after the build
...app.listen(...
So great, my JS and CSS have unique names for each versions, but the problem is that index.html gets cached and so the browser doesn't notice the new JS/CSS files. I don't think changing the name of index.html and having node filter the requests to redirect to newIndex.html is a great solution.
Question: Anything wrong in my workflow? How do I not cache index.html or let the browser know there is a new version of my files?
I am totally new to NodeJS and I wonder what's the difference between those two.
For example, in this project (https://github.com/fikriauliya/hipku), we have index.js and dist/hipku.js. They are similar except the last line:
module.exports = publicMethods; vs return publicMethods;
I guess dist/hipku.js is generated from index.js? How is it generated and why does it need to be generated?
Things in the dist folder are usually the product of building from index.js in this case. You'll notice it gets minified, and that folder would eventually be used on production sites. If you look at the package.json file, you'll notice that index.js is the main file, so if you're doing any edits, that would be the place to do so.
It depends on how you want to use this package, in browser or server side.
server side
index.js is the entry of NPM package. When you do require('hipku'), actually NodeJS locates the file module node_modules/hipku and run index.js ends up with the object adhere to module.exports
browser
Just load dist/hipku.js into your browser by <script>, it will register hipku into your global namespace, then you can use it's API.
I actually have:
Nginx running to serve static files (css, js, etc.)
Node with express.js, template engine: ECT (I may change for Swig)
I am currently trying to find the best way to distribute static files with a custom prefix with versioning:
'http://static.mydomain.com/' in production
'/path/to/static' in devel
So to do that, I only set a variable containing the prefix (which depends on the environment).
Then for each request, I set add the prefix to locals in an express middleware in order to access this variable in any html template:
this.use(function(req, res, next) {
res.locals.staticPrefix = staticPrefix;
next();
});
But since I also want these static files to be also cached by the client's browser, Nginx serves these files with expire = 30d.
Now to force a client to retrieve a static file (if it has changed for example), I need to provide static urls with a dynamic url parameter.
My first idea would be to set a version variable when I start the nodejs app to append it to the final url:
var staticVersion = new Date().getTime();
So in the html template, the final url for a 'myFile.css' would like this: staticPrefix + 'myFile.css?' + staticVersion
In this case, I only need to restart the nodejs application when one of the static files has been updated. It will make the url to change (according to the new date) and the client to do a new request of the file.
Is there a better way to handle this situation with node?
Best way to handle static assets like css/js files is to minify them in production. Use file name based on file contents. This way every time you change anything in js/css files, the minification code will take care of generating new file if needed. You can hook minification script to run post deployment.
I have written a package smush to help with minification tasks. Head onto its github page for example usage and sample codes.
You could use other tools/package for minification if it suits better to your use case.
Coming back to your question, you can set the root dir for nginx to static dir of your node server(/path/to/node/server/public?). This way nginx will cache and serve your static files. The node server will not be bothered to serve the static assets afterwards.
Let me know if this makes sense or if you need any further clarification.