Ural Bayhan Ural Bayhan - 4 months ago 20
Node.js Question

How to get files above the server directory in Node.js

I am trying to serve audio files with a node.js server. The problem is, I want to be able to get any audio file in my computer but I don't know how to make audio elements in html to work with directories above the server. There is this question I found but since the files I want to be able to get always change it didn't really help.

The project is basically a media player on the browser. It will be on LAN so serving everything in the computer isn't really a problem. I am already using express' static function for images, javascript and css. The application is keeping path, name and other informations using nedb.

Answer

First off, you have to understand that node.js doesn't serve any files by default. As such, you must either code each individual request manually so that the /foo request generates content from some specific file or code. Or you must create some set of mappings where /content/foo tells your server to read some corresponding directory on your server like /myservercontent/foo.

And, there are various tools to help you create this mapping for entire directory hierarchies of files (such as express.static()). But, any mapping like this has an explicit root where all requests are relative to some root. You can define where you want this root to be on your server. It can even be the root directory of your server (though that is never recommended for a variety of reasons). Usually, this root is set to some parent directory on your hard disk that ONLY contains public web content below that parent directory. This is so that you NEVER create a situation where some random web user can get access to files on your system that you do not intend to be public (such as your HTTPs certificates, databases, server code, password files, etc...).

All that said, node.js allows you to do pretty much anything you want. If you want to give access to some random file on your hard drive in any random location (something I would never recommend), you can easily code node.js to do that. There are several ways to achieve it. One simple one would be to just construct a route that accepts a query parameter where the query parameter specifies the path to the desired file and then have that route handle go read that file and return it. This is a gaping security hole big enough to drive a truck through so I would never, ever recommend this.

Instead, what you really should do is to gather up all the files that you wish to make available via your server and put them into one safe directory hierarchy and then allow access to files in that specific directory hierarchy, not anywhere else on your hard drive.


Now that you've explained a little more about what you're doing, here's one idea:

  1. Scan the local hard drive to identify all audio files that you think are safe to share. Be very, very careful what you decide to share as mistakes here could open big security holes. You will have to assess the security risks of what you're doing here since we don't understand the full context.

  2. As you gather this list of audio files, save the list to some sort of data store that your server is using so you can quickly get access to the list at any future time. I'd suggest that you create a unique ID for each audio file that may make it easier to refer to in the future.

  3. You can then offer your remote user a list of these audio files and they can pick one. The audio file they have picked can then be sent to the server as part of a request to play a specific audio file. I would suggest that files should be requested only by ID (for security reasons), though your user interface may choose to display the original path name if that is important or relevant.

  4. When your server receives a request to play an audio file with a specific ID, it can then consult its data store to find out which audio file is the one with specific ID. This is an important step because forcing the client to request the file by ID (not by path) makes it so the client can only request audio files that you've previously scanned and found it was safe to make public. There would be no vulnerabilities where a remote client could request some other file that you did not intend to share.

  5. Once your server looks in the data store and finds the audio file with that particular ID, it can then ge the local path from the data strore and can then read the audio file and can send/stream it to the remote client.


As an example, in step 3 and 4, then client may send a URL that looks like this:

http://someserver/play/5934902

That would be a request to play the audio file with an id of 5934902. Your server would then have a route handler for /play/:id that would use the id to then carry out steps 4 and 5.

Comments