Let's say I want to host my 2 websites (cats.com and dogs.com) on the same server with a single IP address (ie with virtual hosts). I want to write them both with hapi.js and have them running as a single process.
The sites may have overlapping paths, for instance they might both have a /about
page.
How could I implement this with hapi?
A nice way of achieving that with hapi is by putting your different sites in to separate plugins and using the vhost
modifier when loading the plugin, ideally using Glue .
Here's an example:
sites/dogs.js
exports.register = function (server, options, next) {
// Put all your routes for the site in here
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('Dogs homepage');
}
});
next();
};
exports.register.attributes = { name: 'dogs' };
sites/cats.js
exports.register = function (server, options, next) {
// Put all your routes for the site in here
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('Cats homepage');
}
});
next();
};
exports.register.attributes = { name: 'cats' };
index.js
const Glue = require('glue');
const Hoek = require('hoek');
const manifest = {
connections: [{
port: 4000,
}],
registrations: [
{
plugin: {
register: './sites/cats'
},
options: {
routes: {
vhost: 'cats.com'
}
}
},
{
plugin: {
register: './sites/dogs'
},
options: {
routes: {
vhost: 'dogs.com'
}
}
}
]
};
const options = {
relativeTo: __dirname
};
Glue.compose(manifest, options, (err, server) => {
Hoek.assert(!err, err);
server.start((err) => {
Hoek.assert(!err, err);
console.log('server started');
});
});
You can then confirm that the routing works correctly with a couple of cURL commands:
$ curl -H "Host: cats.com" localhost:4000/
Cats homepage
$ curl -H "Host: dogs.com" localhost:4000/
Dogs homepage
A browser will set that Host header for you though so when you browse to http://cats.com or http://dogs.com hapi will serve you the correct content (provided your DNS is configured correctly).
If you are using a Hapi version >= 17, the details have changed slightly, though the idea is the same.
We will want to have a plugin for each site. Then, once we have each site extracted into a plugin ( cats
and dogs
below), we can compose the separate configurations using glue
and serve the site with hapi
.
In the example below, the plugins will not know or care which domain they are being served on.
This is the "server" that's meant to be used with cats.com
. It returns the text Hello Cats!
at the root path, /
. In real life it would do something more useful, and you would likely have many more routes and handlers in a real project, but the idea remains the same.
// ./sites/cats.js
exports.plugin = {
name: 'cats',
version: '1.0.0',
register: async function(server, options) {
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'Hello Cats!'
}
})
}
}
This is the server for the content appearing at dogs.com
. It is exactly the same as the cats
plugin, except it returns the text Hello Dogs!
. Again, this is not a useful plugin, it is for illustration only.
// ./sites/dogs.js
exports.plugin = {
name: 'dogs',
version: '1.0.0',
register: async function(server, options) {
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'Hello Dogs!'
}
})
}
}
This is where the vhost
is specified, assigning plugins to hosts cats.com
and dogs.com
.
// ./server.js
const Hapi = require('hapi')
const Glue = require('glue')
const manifest = {
server: {
host: process.env.HOST || '0.0.0.0',
port: process.env.PORT || 8080
},
register: {
plugins: [
{
plugin: './sites/cats',
routes: {
vhost: 'cats.com'
}
},
{
plugin: './sites/dogs',
routes: {
vhost: 'dogs.com'
}
}
]
}
}
const options = {
relativeTo: __dirname
}
const startServer = async function () {
try {
const server = await Glue.compose(manifest, options)
await server.start()
console.log('Hapi days for Cats and for Dogs!')
}
catch (err) {
console.error(err)
process.exit(1)
}
}
startServer()
$ node server.js
Hapi days for Cats and for Dogs!
$ curl -H "Host: cats.com" localhost:8080/
Hello Cats!
$ curl -H "Host: dogs.com" localhost:8080/
Hello Dogs!
$ curl localhost:8080/
{"statusCode":404,"error":"Not Found","message":"Not Found"}
$ curl -H "Host: platypus.com" localhost:8080/
{"statusCode":404,"error":"Not Found","message":"Not Found"}
Note that there are no routes for the default host, so not specifying a host will result in a 404
being returned.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.