# Settings.js httpStatic feature to pass options to express.static (non-breaking)

**URL:** <https://discourse.nodered.org/t/settings-js-httpstatic-feature-to-pass-options-to-express-static-non-breaking/76688>\
**Category:** Feature Requests\
**Tags:** express, static, httpstatic\
**Created:** [18 March 2023 11:54 UTC](https://discourse.nodered.org/t/settings-js-httpstatic-feature-to-pass-options-to-express-static-non-breaking/76688 "2023-03-18T11:54:29Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![kevinGodell](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kevingodell/32/27040_2.png) [@kevinGodell](https://discourse.nodered.org/u/kevinGodell)\
**Post date:** [18 March 2023 11:54 UTC](https://discourse.nodered.org/t/settings-js-httpstatic-feature-to-pass-options-to-express-static-non-breaking/76688/1 "2023-03-18T11:54:29Z")

</div>

I would like to extend the functionality of `httpStatic` in `settings.js` to receive an options object and have that passed to `express.static(filePath, options)`.

The change would be non-breaking and give a finer control over how the files are served by express.static. The lines of code where the proposed changes are at [line 424 of red.js](https://github.com/node-red/node-red/blob/dev/packages/node_modules/node-red/red.js#L424).

I tested giving express.static bad data, such as a string or number. That will trigger an error stating that it wants an object or null, which is the reason for the mild sanitizing  
`const options = typeof sp.options === 'object' ? sp.options : null;`

before changes:

```auto
    if (settings.httpStatic) {
        let appUseMem = {};
        for (let si = 0; si < settings.httpStatic.length; si++) {
            const sp = settings.httpStatic[si];
            const filePath = sp.path;
            const thisRoot = sp.root || "/";
            if(appUseMem[filePath + "::" + thisRoot]) {
                continue;// this path and root already registered!
            }
            appUseMem[filePath + "::" + thisRoot] = true;
            if (settings.httpStaticAuth) {
                app.use(thisRoot, basicAuthMiddleware(settings.httpStaticAuth.user, settings.httpStaticAuth.pass));
            }
            app.use(thisRoot, express.static(filePath));
        }
    }

```

after changes:

```auto
    if (settings.httpStatic) {
        let appUseMem = {};
        for (let si = 0; si < settings.httpStatic.length; si++) {
            const sp = settings.httpStatic[si];
            const filePath = sp.path;
            const thisRoot = sp.root || "/";
            const options = typeof sp.options === 'object' ? sp.options : null;
            if(appUseMem[filePath + "::" + thisRoot]) {
                continue;// this path and root already registered!
            }
            appUseMem[filePath + "::" + thisRoot] = true;
            if (settings.httpStaticAuth) {
                app.use(thisRoot, basicAuthMiddleware(settings.httpStaticAuth.user, settings.httpStaticAuth.pass));
            }
            app.use(thisRoot, express.static(filePath, options));
        }
    }

```

I have had this running for about 1 week and have had no issues. This is an excerpt from my setting.js that I am using for better integration and control when using `nginx as a reverse proxy`.

```auto
    httpStatic: [
        {
            path: '/run/media/system/surveillance1/cctv/recordings/',
            root: '/recordings/',
            options : {
                setHeaders: (res, path, stat) => {
                    if (path.endsWith('.mp4')) {
                        if (Date.now() - stat.mtimeMs < 60000) {
                            res.header('Cache-Control', 'no-store');
                        } else {
                            res.header('Cache-Control', 'public');
                        }
                    }
                }
            }
        }
    ],

```

If this seems acceptable, I can make a PR to the dev branch.

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [18 March 2023 13:38 UTC](https://discourse.nodered.org/t/settings-js-httpstatic-feature-to-pass-options-to-express-static-non-breaking/76688/2 "2023-03-18T13:38:35Z")

</div>

A pr would be welcome. Much easier to review and comment that way.

---

<div class="post-metadata">

**Author:** ![kevinGodell](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kevingodell/32/27040_2.png) [@kevinGodell](https://discourse.nodered.org/u/kevinGodell)\
**Post date:** [8 April 2023 13:27 UTC](https://discourse.nodered.org/t/settings-js-httpstatic-feature-to-pass-options-to-express-static-non-breaking/76688/3 "2023-04-08T13:27:02Z")

</div>

For anybody that is interested in seeing this small code change, it can be found @ [httpStatic feature by kevinGodell · Pull Request #4109 · node-red/node-red · GitHub](https://github.com/node-red/node-red/pull/4109)

Hopefully, I didn't submit this to the wrong branch. 😅

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [7 June 2023 13:27 UTC](https://discourse.nodered.org/t/settings-js-httpstatic-feature-to-pass-options-to-express-static-non-breaking/76688/4 "2023-06-07T13:27:48Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
