How to have Express.js server file using router path as root?

Viewed 162

I have a directory structure like this

root
  private
    js
    css
    index.html
  app.js
  privateRouter.js
  ...

In my index.html I reference the js and css files using relative path like this:

<link rel="stylesheet" href="css/index.css"/>
<script src="js/index.js"></script>

On the server side I have a private router checks for authentication before serving these files:

In app.js:

app.use("/private", privateRouter);

in privateRouter.js:

router.use((req, res, next) => {
    isAuthenticated(req) ? next() : res.redirect("/");
});

router.get('/', function(req, res, next) {
    res.sendFile(require('path').join(__dirname + "/private/index.html"));
});

So now if I visit http://mywebsite.com/private I will get the the index.html, but the request of js/css files from the browser comes back to the server as http://mywebsite.com/js instead of http://mywebsite.com/private/js, thus returns file not found.

Alternatively if I serve files statically, the browser knows to request from /private/js:

app.use("/private", express.static(path.join(__dirname, 'private')));

But I can't server statically because I need to authenticate specific files and not serve all files publicly. And I don't want to have to append private/ before all file references on client side. I don't understand why when serving statically the server knows to use /private as root but when using a router it uses / as root.

How can I keep the url as http://mywebsite.com/private while not having to append private/ in all file references on the client side?

I'm new to express.js and it was also difficult for me to formulate the question. I think I'm fundamentally misunderstanding something about express.js works. Thanks for your help!

1 Answers

You can modify a request's URL using middleware for internal routing:

app.use((req,res,next)=>{
  req.url = "/private" + req.url; // prepend "/private" to the url
  next();
});

You can also set the base URL using the base tag, which means you only need to specify the base URL once per page.

<html>
  <head>
    <base href="private">
    <link rel="stylesheet" href="css/index.css"/>
    <script src="js/index.js"></script>
  </head>
</html>

This should then send the requests to:

  • /private/css/index.css

  • /private/js/index.js

However, you will still need code to handle these paths, otherwise, you will still get the 404 not found error.

Related