I've been Googling for some time, but can't find any useful answers. I'm trying to get a subdomain for an api on my website api.example.com
. However, all answers said that I needed to change my DNS to redirect api.example.com
to example.com/api
, which I don't want. Is it possible to just serve api.
instead of redirect to /api
? How would I go about doing that?
const path = require('path'),
http = require('http'),
https = require('https'),
helmet = require('helmet'),
express = require('express'),
app = express();
const mainRouter = require('./routers/mainRouter.js');
// security improvements
app.use(helmet());
// main pages
app.use('/', mainRouter);
// route the public directory
app.use(express.static('public'));
app.use(/* API subdomain router... */)
// 404s
app.use((req, res) => {
res.status(404).sendFile(path.join(__dirname, "views/404.html"));
})
I recommend You to use nginx and separate api service.
But because of some reasons You cannot avoid it (or You don't want it, cause You just want show prototype to customer ASAP).
You can write middleware that will catch host from header and forward to some custom router:
1) /middlewares/forwardForSubdomain.js
:
module.exports =
(subdomainHosts, customRouter) => {
return (req, res, next) => {
let host = req.headers.host ? req.headers.host : ''; // requested hostname is provided in headers
host = host.split(':')[0]; // removing port part
// checks if requested host exist in array of custom hostnames
const isSubdomain = (host && subdomainHosts.includes(host));
if (isSubdomain) { // yes, requested host exists in provided host list
// call router and return to avoid calling next below
// yes, router is middleware and can be called
return customRouter(req, res, next);
}
// default behavior
next();
}
};
2) api router as an example /routers/apiRouter.js
:
const express = require('express');
const router = express.Router();
router.get('/users', (req, res) => {
// some operations here
});
module.exports = router;
3) attach middleware before /
handler:
const path = require('path'),
http = require('http'),
https = require('https'),
helmet = require('helmet'),
express = require('express'),
app = express();
const mainRouter = require('./routers/mainRouter');
// security improvements
app.use(helmet());
// ATTACH BEFORE ROUTING
const forwardForSubdomain = require('./middlewares/forwardForSubdomain');
const apiRouter = require('./routers/apiRouter');
app.use(
forwardForSubdomain(
[
'api.example.com',
'api.something.com'
],
apiRouter
)
);
// main pages
app.use('/', mainRouter);
// route the public directory
app.use(express.static('public'));
// 404s
app.use((req, res) => {
res.status(404).sendFile(path.join(__dirname, "views/404.html"));
})
P.S. It does the same that in express-vhost package, look at the code