I have one Node/Express server where I am serving both an Angular application and some static HTML. I serve the Angular application out of dist/angular and the static content out of static-content:
// This has to be in this order or else it doesnt work for some reason
app.use(express.static('./static-content'));
app.use(express.static('./dist/angular'));
app.use(parser.json());
// some other routes ...
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/static-content/index.html'));
});
app.get('/app/*', function (req, res) {
res.sendFile(path.join(__dirname, '/dist/angular/index.html'));
});
http.createServer(function (req, res) {
let httpsHost = req.headers.host.replace('8081', '8443');
res.writeHead(301, {"Location": "https://" + httpsHost + req.url});
res.end();
}).listen(8081);
https.createServer(httpsOptions, app).listen(8443)
If you change the order of the express.static at the top, it will not serve the static-content so I am wondering if this is the correct way to serve both an Angular application and HTML+CSS content out of one Node/Express server?
Related
In the example below, if I'm in localhost:5000/A and i want to go to localhost:5000/B, but from within localhost:5000/A, how can i do that via a button ?
var express = require('express');
var app = express();
// Our first route
app.get('/', function (req, res) {
res.send('Hello Index!');
});
// Our A route
app.get('/A', function (req, res) {
res.send('Hello A!');
});
// Our B route
app.get('/B', function (req, res) {
res.send('Hello B!');
});
// Listen to port 5000
app.listen(5000, function () {
console.log('Dev app listening on port 5000!');
});
Just try this :
app.get('/A', function (req, res) {
res.send('Hello A! <button>Click me</button>');
});
Or you could serve an HTML page containing this code.
Hope this answers your question. If not please reach back to me.
I have a Express REST API at /api and a frontend that I want to show at /ui. I have this:
api.js
const STATIC_FILES_PATH = path.resolve(__dirname, '..', 'frontend', 'build');
app.use(express.static(STATIC_FILES_PATH));
app.get('/ui', (_, res) => {
res.sendFile(path.resolve(STATIC_FILES_PATH, 'index.html'));
});
app.get('/api/stuff', (req, res) => {
//do stuff
});
When I navigate to /api/stuff, I still see the frontend instead of the API response. No matter the URI, it always show the frontend webpage.
What am I doing wrong?
EDIT
This is my project structure:
/api
api.js
/frontend
/build
index.html
When I navigate to /api/stuff, in my Chrome console, I see a HTTP 304! It's redirecting me to the frontend (cached) instead of showing me the JSON result (API response).
After adding this middleware:
app.get('/*', (req, res, next) => {
res.setHeader('Last-Modified', (new Date()).toUTCString());
next();
});
it's working fine. It seems Express is caching stuff. Thanks to all!
change your code with this snippet, it tested and will work correctly.
api.js
const express = require('express');
const app = express();
const path = require('path');
const STATIC_FILES_PATH = path.resolve(__dirname, 'frontend', 'build');
app.use(express.static(STATIC_FILES_PATH));
app.get('/ui', (req, res, next) => {
res.sendFile(path.resolve(STATIC_FILES_PATH, 'index.html'));
});
app.get('/api/stuff', (req, res, next) => {
res.json({title: 'staff'});
});
app.listen(3000);
I have an existing express app I'm using for an API but I also want to deliver a folder with an HTML file and some images/css/js. I can get it to serve the HTML page but it does so at / while I only want it served at /manual. Here is my stripped down code with just express.static, my / route and the catch all redirect to /
const app = express();
app.use(express.static('manual'));
app.get('/', (req, res) => {
res.status(403);
res.send('Access denied.');
return;
});
app.get('*', (req, res) => {
res.redirect(301, '/');
return;
});
What currently happens: Going to mysite.com/manual redirects to mysite.com/ which serves the index.html in the manual folder.
What I want to happen: Going to mysite.com/manual serves the index.html in the manual folder. And going to mysite.com/ throws a 403 status code.
Middleware/handlers are applied in the order you declare them, so you just need to change the order
const app = express();
app.get('/', (req, res) => {
res.status(403);
res.send('Access denied.');
return;
});
// adding a first parameter lets you apply the middleware to a route
app.use('/manual', express.static('manual'));
app.get('*', (req, res) => {
res.redirect(301, '/');
return;
});
I have an application built with reactjs with node js backend by using Create React App library.
in Nodejs-server.js I have the following code structure.
import express from 'express';
import path from 'path';
import bodyParser from 'body-parser';
import cors from 'cors';
import visitors from './routes/visitors';
import { cronNotification } from './cron/cron.js';
let app = express();
app.use(bodyParser.json({ limit: '15mb' }))
app.use(cors())
app.use('/api/visitors', visitors)
app.use('/docs/visitorTickets', express.static(path.join(__dirname, '../docs/visitorTickets')));
app.use('/images', express.static(path.join(__dirname, '../assets/images')));
app.use(express.static(path.join(__dirname, '../../build')));
app.get('/*', function (req, res, next) {
res.sendFile(path.join(__dirname, '../../build', 'index.html'));
});
app.use((req, res) => {
res.status(404).json({
errors: {
global: "Page Not Found."
}
})
});
let port = 8080
app.listen(port, () => console.log('Running on port:'+port));
cronNotification();
In Visitor file I have following code
import express from 'express';
import QRCode from 'qrcode';
import pdf from 'html-pdf';
let router = express.Router();
router.get('/test', (req, res) => {
res.json({ success: "test success page." })
});
router.get('/pdf', (req, res) => {
let html = '<div>test value</div>';
pdf.create(html).toStream((err, pdfStream) => {
if (err) {
return res.sendStatus(500)
} else {
res.statusCode = 200
pdfStream.on('end', () => {
return res.end()
})
pdfStream.pipe(res)
}
});
});
export default router;
This code working perfect with front end react app by using http://localhost:3000/test.
It gets the result via API from axios library from react action page.
In developr tool network -> result shows: success: "test success page."
Now the issues is:
When I access
http://localhost:8080/api/visitors/pdf OR
http://localhost:8080/api/visitors/test
Directly in browser, It shows blank page (directly frot end source is appearing from console)
While access it from private window, It shows the result.
It tried it with diffrent browsers and diffrent computers but issue remain the same.
I am suspecting something wrong in this code
app.use(express.static(path.join(__dirname, '../../build')));
app.get('/*', function (req, res, next) {
res.sendFile(path.join(__dirname, '../../build', 'index.html'));
});
It is neglecting app.use path (app.use('/api/visitors', visitors))
Kindly help me out why this is working only in private browser?
After a long battle, I have fixed that issue by unregister react's registerServiceWorker
import { unregister } from './registerServiceWorker';
unregister();
So, why you need to res.sendFile to send an html page ? Let try to use ejs or jade view engine and then :
app.get('/*', function (req, res) {
return res.render('../path_to_ejs_view_file');
});
Or in your case maybe call next() function can solve problem:
app.get('/*', function (req, res, next) {
res.sendFile(path.join(__dirname, '../../build', 'index.html'));
next();
});
By the way, I have an project like you. Use Nodejs for api and Reacjs for SPA here: https://github.com/dangminhtruong/havana hope it useful
I want to structure my public folder like this:
- public
- frontend
- backend
- assets # to serve common css, and js static files for backend/frontend
if the request is prefixed by /admin then I want to serve backend folder, else then the frontend folder
this is what I've tried
app.use(function(req, res, next) {
if (req.url.match('^\/admin')) {
express.static(__dirname + '/public/admin')(req, res, next);
} else {
express.static(__dirname + '/public/frontend')(req, res, next);
}
});
app.use(express.static(__dirname + '/public/assets'));
app.get('*', function(req, res, next) {
if (req.url.match('^\/admin')) {
res.sendFile(__dirname + '/public/admin/app/views/index.html');
} else {
res.sendFile(__dirname + '/public/frontend/app/views/index.html');
}
});
but I can't get the static files from the assets folder, it keeps giving me index.html instead.
what is the right approach to make it works ? thx alot
If I understood your question correctly, I think something like this would be more the way to go.
app.use('/admin', express.static('public/backend'));
app.use('/', express.static('public/frontend'));
You can do this way
app.get('/*', function(req, res) {
if(req.path.indexOf('/admin/')!==-1)
res.sendFile(path.join(__dirname, 'public/admin', 'index.html'));
}else {
res.sendFile(path.join(__dirname, 'public/frontend', 'index.html'));
}
});
You can similarly add other urls as well.