I have a directory structure on my server like:
site-a/app/index.html
site-a/app/main.js
site-a/app/vendor.js
site-b/app/index.html
site-b/app/main.js
site-b/app/vendor.js
And so on.
I'd like to be able to create a server that can respond to these like:
curl http://site-a/app/
curl http://site-a/app/vendor.js
For the index.html file, I have something like this and it works:
this.app.use((req, res) => {
res.sendFile(path.join(process.env['SOURCE'], req.subdomains[req.subdomains.length - 1], '/app/index.html'));
});
But I can't for the life of me figure out how to get express.static to work in a situation like this.
Bonus Credit: Any request that fails should load /app/index.html. It's an Angular application.
Anyone have any pointers?
Perhaps this is what you are looking for?
app.use('/app', function(req, res, next) {
let host = req.get('host'); // for some reason, subdomains wasn't working on localhost
let site = host.includes('site-b') ? 'site-b' : 'site-a'; // conditional logic because ^^^
let files = path.join(process.env['SOURCE'], site, 'app'); // file path to /app folder for that site
express.static(files)(req, res, function() {
res.sendFile(path.join(files, 'index.html')) // fallback to index.html
})
});
express.static needs to be given the directory, not index.html. It'll automatically use index.html as the root.
I specify next function to express.static that, if it fails to find a file, just sends index.html anyway.
Let me know if you have any questions!
/app/site-a = http://site-a.localhost:port/app
/app/site-b = http://site-b.localhost:port/app
Related
At the request of the SEO specialist, I need to implement the following functionality.
I have to redirect if the link contains a capital letter.
For example https//domain.com/#Contacts ==> https//domain.com/#contacts.
In Nuxt I implemented with by creating function on server.js file which located on middleware folder.
But it doesn't work if path contains hash(#)
export default function (req, res, next) {
const url = req.url;
if (url !== url.toLowerCase()) {
res.writeHead(301, { Location: url.toLowerCase() });
res.end()
} else {
next();
}
}
I would be grateful if you answer or help
The part after the hash (fragment identifier) is never going to be sent to the server by your browser, so what you're trying to do is impossible using redirects.
You can access them on the client-side, but I don't think that it would do any good in terms of SEO.
I have the following code:
const app = express();
app.use(express.static(path.resolve('../frontend/dist')));
const server = http.createServer(app);
app.get('/', (req, res) => {
console.log('received request');
res.sendFile(path.resolve('../frontend/dist/index.html'));
});
If I comment out the app.get handler, index.html is served at localhost:3000 anyway, apparently due to the second line. The get handler is not actually executing - received request is never printed in the console.
But without the second line, it can't serve static assets and JS & CSS fail to load. What am I doing wrong here? Why is the static asset config causing the route to be ignored?
express.static() is a generic route handler. It tries to match incoming requests to specific files at a target location in your file system. One of the special features it has is that if it gets a request for / it will look for index.html in the target directory.
You can see the feature described in the doc and, in fact, there's an option { index: false} that can turn the feature off if you don't want it to serve index.html automatically.
I am statically serving my site from one directory. I have one dynamic route for setting the URL parameter roomCode. I want all routes to this path to serve the root index page without changing the URL on the client (that way I can still use the roomCode in my JavaScript).
Here is what I currently have:
// direct rooms to the index page
app.use('/room/:roomCode([A-Z]{4})', (_, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'))
})
// serve from the dist build
app.use(express.static(path.join(__dirname, 'dist')))
Instead of manually sending the dist/index.html file, I would like to simply change the route path to / for the following middleware and let the static server send the file. Something like this:
// direct rooms to the index page
app.use('/room/:roomCode([A-Z]{4})', (_, res, next) => {
req.path = '/'
next()
})
// serve from the dist build
app.use(express.static(path.join(__dirname, 'dist')))
This way, when the static middleware is reached, it believes the path was /, so it will serve the index page at the root.
Is this possible?
To reroute a request, you must change req.originalUrl to the new route, and then send it to the router handler with app._router.handle(req, res, next).
// direct rooms to the index page
app.use('/room/:roomCode([A-Z]{4})', (req, res, next) => {
// this reroutes the request without a redirect
// so that the clients URL doesn't change
req.originalUrl = '/'
app._router.handle(req, res, next)
})
// serve from the dist build
app.use(express.static(path.join(__dirname, 'dist')))
The documentation for req.originalUrl is a little confusing. It says:
This property is much like req.url; however, it retains the original request URL, allowing you to rewrite req.url freely for internal routing purposes.
This sounds like if you change req.url, it will change how it is routed. However, it does not. It does allow you to change it and then manually check it in latter middleware. But the middleware will still be called based on the original URL. Therefore, we need to overwrite the original URL and send it back through the router.
Hi I am a newbie and started to learn about node recently. I took an Heroku tutorial on websockets (https://devcenter.heroku.com/articles/node-websockets) and adapted it for a specific project I was working on. In the example code there was a single index.html file with some embedded javascript. I moved this script out to a separate file and referenced it in the HTML. Everything worked fine locally but doesn't work when i deploy to Heroko. I chatted with the very helpful team at Heroku who informed me that my server side code is serving up all files as HTML and I need to change the code. They gave me some pointers and I tried as many things as I could over several days but to no avail. In the end they recommended coming to this forum as a way to solve the problem as it is beyond their scope. The existing code that serves up the index.html file is as follows:
const express = require('express');
const SocketServer = require('ws').Server;
const path = require('path');
const PORT = process.env.PORT || 3000;
const INDEX = path.join(__dirname, 'index.html');
const server = express()
.use((req, res) => res.sendFile(INDEX) )
.listen(PORT, () => console.log(Listening on ${ PORT }));
At first i edited this to include the line:
app.use(express.static('public'))
but this didn't work. I then amended as follows and it still doesn't work:
const INDEX = path.join(__dirname, 'index.html');
const JS = path.join(__dirname, 'client.js');
const server = express()
.use((req, res) => {
res.sendFile(INDEX);
res.sendFile(JS);
I have looked at other tutorials that work when i run them in isolation but when I try to adapt my above code it simply doesn't work. I would really appreciate if someone out there could point me in the right direction.
BTW this is what Heroku told me:
"To explain a bit further this error Uncaught SyntaxError: Unexpected token < is because the URL for http://thawing-journey-33085.herokuapp.com/client.js isn't serving a javascript file but is instead trying to serve the HTML for the homepage. This suggests you have an issue with the routing in your application which you'll need to review. This is probably because your server.js file doesn't check for any particular URL before sending the index.html file."
Thanks
I serve my static files like this:
// define the folder that will be used for static assets
app.use(Express.static(path.join(__dirname, '../public')));
// handle every other route with index.html, which will contain
// a script tag to your application's JavaScript file(s).
app.get('*', function (request, response){
response.sendFile(path.resolve(__dirname, '../public', 'index.html'));
});
This way i set the static folder in the express.static middleware so i can serve the files. And then i redirect all url request to the index.html
To know more: express static
I am using Express to serve static assets. Frontend is AngularJS 1.x and I have html5mode enabled. Trying to implement Recaptcha is where I noticed the following in Chrome dev tools:
Uncaught SyntaxError: Unexpected token <
api.js?onload=vcRecaptchaApiLoaded&render=explicit“:1
When I click on the function to initiate the Recaptcha process I receive:
Error: reCaptcha has not been loaded yet.
So far this makes sense to be bacause I noticed the string that the first error is reporting is part of the url path to load Recaptcha from Google.
When I click on the url (api.js?onload=vcRecaptchaApiLoaded&render=explicit“:1) in chrome tools it loads my index.html! Strange!
This has be believing it has something to do with my static asset serving. I have played around with my express server until the cows came home and cannot figure out how to remedy.
Live example:
http://ninjacape.herokuapp.com
Here is my code and thank you for taking a look!
index.html
<script src=“https://www.google.com/recaptcha/api.js?onload=vcRecaptchaApiLoaded&render=explicit“ async defer></script>
express.js
var express = require('express');
var compression = require('compression');
var app = module.exports.prod = exports.prod = express();
var devAPI = 'http://localhost:1337';
app.use(compression());
app.use(express.static('.tmp'));
app.get('/*', function(req, res) {
res.sendFile(__dirname + '/.tmp/index.html');
});
var proxy = require('express-http-proxy');
app.use('/api', proxy(devAPI));
var port = process.env.PORT || 8000;
app.listen(port);
Well... I wish I had a better answer however I am just happy I got it to work. Something in the way I am statically serving files is appending any url in index.html to http://localhost:8000. To work around this I took a look at the actual request coming into Express and found the url. Then added logic to redirect that request to the real url. See commented code below for more info:
// Any requests matching /*
app.get('/*', function(req, res, next) {
// Log the original url express is tying to go to
console.log(req.url);
// This is the url found from the step above (Where are the extra characters coming from?!)
var url ='/%E2%80%9Chttps://www.google.com/recaptcha/api.js?onload=vcRecaptchaApiLoaded&render=explicit%E2%80%9C'
// Self explanatory
if (req.url === url) {
// Respond by redirecting the request
res.redirect('https://www.google.com/recaptcha/api.js?onload=vcRecaptchaApiLoaded&render=explicit')
//End this block and continue
next();
} else {
// If it doesn't match the above url, proceed as normal
res.sendFile(__dirname + '/.tmp/index.html');
}
});