# Serving Static Content from a Custom Node (Dynamically update httpStatic

**URL:** https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453
**Category:** Developing Nodes
**Created:** [20 September 2023 12:12 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453 "2023-09-20T12:12:43Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![gazoscalvertos](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gazoscalvertos/32/52838_2.png) [@gazoscalvertos](https://discourse.nodered.org/u/gazoscalvertos)
#### Post date: [20 September 2023 12:12 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/1 "2023-09-20T12:12:44Z")

</div>

Hi All,

Hopefully the title says it all but when developing custom nodes whats the recommended approach to serving static content in say ./docs? I know httpStatic can be used in settings.js but thats locally set right? Is there a recommended way to dynamically update this?

Thanks

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [20 September 2023 12:25 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/2 "2023-09-20T12:25:26Z")

</div>

Hi @gazoscalvertos

For this, you will use the `resources` directory I believe.

It's like `httpStatic`, but on a per node basis.

I use this to host my own JS files and various resources that is accessed via the browser

[https://nodered.org/docs/creating-nodes/resources](https://nodered.org/docs/creating-nodes/resources)

To access a file in your resources directory (example docs.html)  
`http://x.x.x.x:1880/resources/node-red-node-example/docs.html`

---

<div class="post-metadata">

### Author: ![gazoscalvertos](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gazoscalvertos/32/52838_2.png) [@gazoscalvertos](https://discourse.nodered.org/u/gazoscalvertos)
#### Post date: [20 September 2023 12:28 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/3 "2023-09-20T12:28:41Z")

</div>

Thanks, I'm using that for static content such as images etc, but thought there might have been a way to have a cleaner URL ie. [https://noderedurl/documentation](https://noderedurl/documentation)

I'll use the resources dir. 👍

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [20 September 2023 14:45 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/4 "2023-09-20T14:45:32Z")

</div>

You can attach your own routes to Node-RED's ExpressJS server if you want to. Just remember to remove them in the `close` callback otherwise you can end up with multiple instances.

---

<div class="post-metadata">

### Author: ![gazoscalvertos](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gazoscalvertos/32/52838_2.png) [@gazoscalvertos](https://discourse.nodered.org/u/gazoscalvertos)
#### Post date: [20 September 2023 18:24 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/5 "2023-09-20T18:24:13Z")

</div>

Thanks, with a bit of testing I've managed to figure this out, might not be the most elegant of solutions but here is what works for me:

```auto
// grab the node express instance
  const server = RED.httpNode;

  try {
    // set a route to /docs and handle subdirs
    server.get('/docs/:resourcePath(*)', function (req, res) {
      // handle default file ie index.html
      const resourcePath = req.params.resourcePath || 'index.html';
      const filePath = path.join(__dirname, '../docs', resourcePath); 

      // Determine the content type based on the file's extension
      const contentType = mime.lookup(filePath);

      // Read the data from the file 
      fs.readFile(filePath, (err, data) => {
        if (err) {
          // Handle errors, e.g., file not found
          res.status(404).send('File not found');
        } else {
          // Set the content type and send the data in the response
          res.set('Content-Type', contentType);
          res.send(data);
        }
      });
    });
  } catch (error) {
    console.log(error);
  }

```

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [20 September 2023 18:35 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/6 "2023-09-20T18:35:01Z")

</div>

You need to be extremely! careful going with this approach.

Once a resource handler has been set - it can't be re-used.

Therefore, someone else developing this method (with the same endpoint) - won't see any issues, until one of their users also has your node installed.

or your users, complaining that they can't get to /docs/ - surprise surprise another node is using this endpoint.

I strongly encourage you to make it unique or use the resources method that is built-in to facilitate this need 😀

---

<div class="post-metadata">

### Author: ![gazoscalvertos](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gazoscalvertos/32/52838_2.png) [@gazoscalvertos](https://discourse.nodered.org/u/gazoscalvertos)
#### Post date: [20 September 2023 18:51 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/7 "2023-09-20T18:51:11Z")

</div>

Thanks Marcus, that's a very good point! I'll probably stick to the resources method in that case.

I'll check I don't have anything else which could cause a clash (css etc)

---

<div class="post-metadata">

### Author: ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)
#### Post date: [20 September 2023 18:56 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/8 "2023-09-20T18:56:05Z")

</div>

I mean if you really needed to do it this way.  
Maybe use a prefix to the URI or something to partition it away from other things.

Example: before I started using `Resources` with my ZWave Node I used to do:  
`server.get('/zwjs/api/:call', function (req, res) {})`  
`server.get('/zwjs/docs/device/:part', function (req, res) {})`  
`server.get('/zwjs/docs/controller/:part', function (req, res) {})`

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [20 September 2023 19:17 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/9 "2023-09-20T19:17:40Z")

</div>

Absolutely you need to make sure that you use unique endpoints. Note how uibuilder goes to some length for example to make sure.

Also, you don't need to manually serve files. You can use Express Static. [Serving static files in Express (expressjs.com)](https://expressjs.com/en/starter/static-files.html)

---

<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: [19 November 2023 19:18 UTC](https://discourse.nodered.org/t/serving-static-content-from-a-custom-node-dynamically-update-httpstatic/81453/10 "2023-11-19T19:18:01Z")

</div>

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