I'm using restify for node to create a simple API. I want to have a directory /public where people can simply browse to that directory and download the file they browse to.
To accomplish this, I have used in /routes/public.js:
server.get(/\/public\/?.*/, restify.serveStatic({
directory: __dirname + '/../'
}));
as my file structure is like:
index.js
/routes
public.js
/public
files
to
be
served
however, I have noticed a big security issue. By browsing to http://domain.com/public/../index.js the source code can be downloaded! Obviously, I do not want this to happen.
Is this a permissions job or is there something else I should be doing? Thanks
Restify does check to make sure that you're not serving files outside of the specified directory. You're specifying the root directory for static files as __dirname + '/../' which is the root of the application. That means all of the files in your application can be served via static. If you only want files in the ./public/ folder served by restify, you have to use that as the directory.
The problem stems from the confusing (and in my opinion poorly planned) way they handle mapping routes to static files. As you said, the full route is included in the path of the requested file. This leads to awkward situations like this one. You have a public folder, and also want the route to include public. That means you have to have a ./public/public folder for your resources. An alternative approach would be to not include public in your route. You can setup your static handler like this:
server.get(/.*/, restify.serveStatic({
directory: './public/'
}));
Then a request to /somefile.txt would route to `./public/somefile.txt'.
Related
I'm starting out with express.js and trying to serve lots of static files from the server (could be .css, .jpg, .svg, .js or other file types). Is there a way to do this without typing app.get() for each file? I know about express.Router() but then the clutter just goes over into another file.
You might want to use express.static middleware.
For example, use the following code to serve all the files from directory named public:
app.use(express.static('public'))
Now, you can load the files that are in the public directory:
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
More info here: https://expressjs.com/en/starter/static-files.html
Currently, I can 'upload' my images onto my server with Multer but now, how can I serve that file? If I visit the path which is: http://localhost:3001/public/backend/public/uploads/user-admin-1556247519876.PNG, i get a 404 cannot get.
I feel like i'm just missing a single step but I can't spot my error.
To serve static files such as images, CSS files, and JavaScript files, use the express.static built-in middleware function in Express.
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:
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
Express looks up the files relative to the static directory, so the name of the static directory is not part of the URL.
I'm looking at this sample Angular application.
In the index.html file, there are lines like
<script type="text/javascript" src="/static/angular.js"></script>
However, upon closer inspection there are no folders in the project called static.
How does this work? How does angular locate these references?
Angular has nothing to do with this. It is the express server which takes care of the paths.
Take a look at server/config.js. You will see staticUrl: '/static' mentioned there.
Now open server/server.js (server.js is the script which runs before anything else runs in the app so all the configuration is done within this file) and on line 21 you will see require('./lib/routes/static').addRoutes(app, config);. This requires the static.js file which instructs the app to use /static (mentioned in the config.js file) as the path for static files such as CSS and javascript files.
This is a server side phenomenon. There is a middleware in this file server/lib/routes/static.js :
line : 9
app.use(config.server.staticUrl, express.static(config.server.distFolder));
What this does is : if any http request is started from config.server.staticUrl (whitch is /static for this app) the server tries to respond with the resource that are kept in a config.server.distFolder folder (which is client/dist for this app).
For example :
when you request to this url /static/angular.js the middleware tries to find angular.js file in client/dist/. Because client/dist directory is mapped to the url which starts with /static by the middleware.
When that HTML file is processed by the browser, the layout engine is making a separate HTTP request to the server to download the resource in question:
/static/angular.js
Since all of that is handled by the server routing mechanism there doesn't have to be a folder named static in client code. Your example is using Node.js Express routing which maps /static routes to actual physical paths.
Here is a piece of code that configures static routes:
https://github.com/angular-app/angular-app/blob/master/server/config.js
The important parts are:
staticUrl: '/static', // The base url from which we serve static files (such as js, css and images)
And the destination folder that /static maps to:
distFolder: path.resolve(__dirname, '../client/dist'), // The folder that contains the application files (note that the files are in a different repository) - relative to this file
Per the documentation the dist folder contains the Grunt build results, and if you take a look at the gruntfile you will find all the grunt configuration that makes this possible.
https://github.com/angular-app/angular-app/blob/master/client/gruntFile.js
I have an app like this
/app
/views
index.jade
/controllers
controllers1.js
controllers2.js
server.js
Inside server.js I use app.use(express.static(path.join(__dirname, 'app'))); and all requests render index.jade. Inside index.jade I call the controllers with regular <script> tags.
My Problem
I'm uncomfortable with exposing all my scripts to the front-end. e.g.: I don't want people to type www.myurl.com/controllers/controllers1.js and see the script, because I don't want to show all my business logic right away, especially to users who aren't logged in.
Question
Having deactivated express.static(), is it possible through express Middleware to get the contents a certain javascript files and include/send them to index.jade? Ideally I want to control which script files the front-end can receive/see.
There's probably many ways to do this. Should I be using some kind of library for this (maybe Requirejs, idk much about it)?
deactivating express.static is not required
use public folder for all the content which you want to expose to users
like
app
->controllers
public
->js
->->jQuery.js
->->abc.js
->css
->->bootstrap.css
htmls goes here
and use express.static(__dirname,'public') to expose public folder.
One strategy I've used is to separate the public and private node files. The public libraries implement dual purpose node/browser code. I use a folder structure that looks something like this:
/app
/lib
/public
public_library.js
private_library.js
Then it's simple to expose the public directory so that you can do both:
var mylib = require('public/public_library.js');
in your node files and
<script src="lib/public/public_library.js"></script>
in your browser facing code.
Put all libraries you want to expose in the public directory. Put all libraries you want to keep private outside of the public directory.
I have a node.js file server running which (when visited) returns a html content. Also in the same directory of the node.js file, there is a javascript file called test.js. Also in the html content being returned, I need to load that javascript file. However in the html content, being returned, which comes out to be called index.html, the script looks like
<script type="text/javascript" src="test.js"></script>
But the server isn't sending the test.js file, its only sending the index.html file, and the script link is loading it relatively from the same directory.
Now I don't want to give the url to the test.js file. I want the node.js file to also send the test.js file, so that it ends up in the same directory as index.html. And then index.html can load it from the same directory.
Is there a way I can specify in the node.js with code to also send the test.js file?
Thanks.
Are you familiar with Express, as dandavis mentioned? Express allows you to set a directory for your static files. See my standard config below:
app
.use('view engine', jade)
.use(express.compress())
.use(express.limit('10mb'))
.use(express.bodyParser())
.use(app.router)
.use(stylus.middleware({
src: __dirname + '/www',
compile: function(str, path) {
return stylus(str)
.set('filename', path)
.set('compress', false)
.set('warn', true);
}
}))
.use(express.static(__dirname + '/www'))
.use(express.logger());
The important part here is second from the bottom. Essentially, Express now knows to look for any assets you specify in your HTML within that static directory. For me, I create a folder titled WWW within my server folder, then add to it my JS, CSS, and images.
For example, say I create the "stylus" folder within my WWW folder, and add to it store.css. My link to that CSS asset would be the following in my Jade template:
link(rel="stylesheet", type="text/css", href="stylus/store.css")
Express knows to look for that asset relative to the __dirname + '/www' path, and thus locates the "stylus" folder and the CSS assets it contains. Hope this helps, and that I haven't ventured away from your intent!