Skip to content

Commit

Permalink
Merge branch 'master' of github.com:kartikk221/hyper-express
Browse files Browse the repository at this point in the history
  • Loading branch information
kartikk221 committed Nov 12, 2023
2 parents 270f22d + cd5c2ce commit 05f3750
Showing 1 changed file with 34 additions and 15 deletions.
49 changes: 34 additions & 15 deletions docs/LiveDirectory.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Below is a simple guide on implementing static serving functionality to HyperExp

#### Why LiveDirectory?
LiveDirectory loads files from the specified path into memory and watches them for updates allowing for instantaneous changes. This is desirable for both development and production environments as we do not have to wait on any I/O operation when serving assets. Each request will serve the most updated file content from memory allowing for high performance and throughput without any bottlenecks.
- See [`> [LiveDirectory]`](./docs/LiveDirectory.md) for all available properties, methods and documentation on this package.
- See [`> [LiveDirectory]`]([./docs/LiveDirectory.md](https://github.com/kartikk221/live-directory)) for all available properties, methods and documentation on this package.

#### Getting Started
Please install the [`live-directory`](https://github.com/kartikk221/live-directory) using the `npm` package manager.
Expand All @@ -18,14 +18,29 @@ const LiveDirectory = require('live-directory');
const Server = new HyperExpress.Server();

// Create a LiveDirectory instance to virtualize directory with our assets
const LiveAssets = new LiveDirectory({
path: '/var/www/website/files', // We want to provide the system path to the folder. Avoid using relative paths.
keep: {
extensions: ['.css', '.js', '.json', '.png', '.jpg', '.jpeg'] // We only want to serve files with these extensions
},
ignore: (path) => {
return path.startsWith('.'); // We want to ignore dotfiles for safety
// Specify the "path" of the directory we want to consume using this instance as the first argument
const LiveAssets = new LiveDirectory('/var/www/website/files', {
// Optional: Configure filters to ignore or include certain files, names, extensions etc etc.
filter: {
keep: {
// Something like below can be used to only serve images, css, js, json files aka. most common web assets ONLY
extensions: ['.css', '.js', '.json', '.png', '.jpg', '.jpeg']
},
ignore: (path) => {
// You can define a function to perform any kind of matching on the path of each file being considered by LiveDirectory
// For example, the below is a simple dot-file ignore match which will prevent any files starting with a dot from being loaded into live-directory
return path.startsWith('.');
},
}

// Optional: You can customize how LiveDirectory caches content under the hood
cache: {
// The parameters below can be tuned to control the total size of the cache and the type of files which will be cached based on file size
// For example, the below configuration (default) should cache most <1 MB assets but will not cache any larger assets that may use a lot of memory
// In the scenario that LiveDirectory encounters an uncached file, It will s
max_file_count: 250, // Files will only be cached up to 250 MB of memory usage
max_file_size: 1024 * 1024, // All files under 1 MB will be cached
},
});

// Create static serve route to serve frontend assets
Expand All @@ -37,9 +52,16 @@ Server.get('/assets/*', (request, response) => {

// Return a 404 if no asset/file exists on the derived path
if (file === undefined) return response.status(404).send();

// Set appropriate mime-type and serve file buffer as response body
return response.type(file.extension).send(file.buffer);

// Retrieve the file content and serve it depending on the type of content available for this file
const content = file.content;
if (content instanceof Buffer) {
// Set appropriate mime-type and serve file content Buffer as response body (This means that the file content was cached in memory)
return response.type(file.extension).send(content);
} else {
// Set the type and stream the content as the response body (This means that the file content was NOT cached in memory)
return response.type(file.extension).stream(content);
}
});

// Some examples of how the above route will map & serve requests:
Expand All @@ -48,7 +70,4 @@ Server.get('/assets/*', (request, response) => {
```

#### Is This Secure?
LiveDirectory will traverse through all sub-directories and files from your specified path and load its files into memory. Due to this, we do not perform any file system operations for lookups of files. This eliminates any path manipulation vulnerability that may allow a bad actor to access sensitive files on your hardware as only files that loaded into memory are served. To view which files have been loaded into memory by LiveDirectory simply view the `LiveDirectory.files` object.

#### What Are The Downsides?
Since LiveDirectory loads all files from your specified path into memory, this method of static serving is not suitable for serving large files automatically. It is strongly recommended to use read streams combined with the `Response.write` method to write large files in chunks to prevent exhaustion of your system's memory.
LiveDirectory will traverse through all sub-directories and files from your specified path ahead of time and load its files into memory during startup. Due to this, we do not perform any file system operations for any `get()` calls making things performant. This eliminates any path manipulation vulnerability that may allow a bad actor to access sensitive files on your hardware as only files that loaded into memory are served. You can inspect the `LiveDirectory.files` property at any time to confirm which file paths are being loaded by `LiveDirectory` to detect any unintended files.

0 comments on commit 05f3750

Please sign in to comment.