Skip to content

Commit db498ae

Browse files
authored
Merge pull request #52 from jkyberneees/supporting-hostnames
Supporting hostnames
2 parents 444c89a + b122abd commit db498ae

File tree

5 files changed

+209
-0
lines changed

5 files changed

+209
-0
lines changed

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,56 @@ gateway({
240240
```
241241
> In this example we have used the [express-rate-limit](https://www.npmjs.com/package/express-rate-limit) module.
242242
243+
## Hostnames support
244+
We can also implement hostnames support with fast-gateway, basically we translate hostnames to prefixes:
245+
```js
246+
...
247+
248+
// binding hostnames to prefixes
249+
const hostnames2prefix = [{
250+
prefix: '/api',
251+
hostname: 'api.company.tld'
252+
}]
253+
// instantiate hostnames hook, this will prefix request urls according to data in hostnames2prefix
254+
const hostnamesHook = require('fast-gateway/lib/hostnames-hook')(hostnames2prefix)
255+
256+
// separately instantiate and configure restana application
257+
const app = restana()
258+
const server = http.createServer((req, res) => {
259+
hostnamesHook(req, res, () => {
260+
return app(req, res)
261+
})
262+
})
263+
264+
// gateway configuration
265+
gateway({
266+
server: app, // injecting existing restana application
267+
routes: [{
268+
prefix: '/api',
269+
target: 'http://localhost:3000'
270+
}]
271+
})
272+
273+
...
274+
```
275+
> Afterwards:
276+
> `curl --header "Host: api.company.tld:8080" http://127.0.0.1:8080/api-service-endpoint`
277+
278+
You can optionally `npm install micromatch` and benefit from patterns support:
279+
```js
280+
const hostnames2prefix = [{
281+
prefix: '/admin',
282+
hostname: '*.admin.company.tld'
283+
}, {
284+
prefix: '/services',
285+
hostname: [
286+
'services.company.tld',
287+
'*.services.company.tld'
288+
]
289+
}]
290+
```
291+
For more details, please checkout the `basic-hostnames.js` demo.
292+
243293
## Gateway level caching
244294
Caching support is provided by the `http-cache-middleware` module. https://www.npmjs.com/package/http-cache-middleware
245295

demos/basic-hostnames.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict'
2+
3+
const gateway = require('../index')
4+
const PORT = process.env.PORT || 8080
5+
const http = require('http')
6+
const restana = require('restana')
7+
8+
// binding hostnames to prefixes
9+
const hostnames2prefix = [{
10+
prefix: '/api',
11+
hostname: 'api.company.tld'
12+
}]
13+
// instantiate hostnames hook, this will prefix request urls according to data in hostnames2prefix
14+
const hostnamesHook = require('./../lib/hostnames-hook')(hostnames2prefix)
15+
16+
// separately instantiate and configure restana application
17+
const app = restana()
18+
const server = http.createServer((req, res) => {
19+
hostnamesHook(req, res, () => {
20+
return app(req, res)
21+
})
22+
})
23+
24+
// gateway configuration
25+
gateway({
26+
server: app, // injecting existing restana application
27+
middlewares: [
28+
],
29+
30+
routes: [{
31+
prefix: '/api',
32+
target: 'http://localhost:3000'
33+
}]
34+
})
35+
36+
server.listen(PORT)
37+
38+
const origin = require('restana')({})
39+
origin
40+
.get('/hi', (req, res) => res.send('Hello World!'))
41+
.start(3000)

lib/hostnames-hook.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict'
2+
3+
let micromatch
4+
try {
5+
micromatch = require('micromatch')
6+
} catch (e) {
7+
micromatch = {
8+
isMatch (value, pattern) {
9+
return value === pattern
10+
}
11+
}
12+
}
13+
14+
module.exports = hostname2prefix => {
15+
const matches = {}
16+
17+
return (req, res, cb) => {
18+
if (req.headers.host) {
19+
const hostHeader = req.headers.host.split(':')[0]
20+
let prefix = matches[hostHeader]
21+
22+
if (!prefix) {
23+
for (const e of hostname2prefix) {
24+
if (micromatch.isMatch(hostHeader, e.hostname)) {
25+
prefix = e.prefix
26+
matches[hostHeader] = prefix
27+
28+
break
29+
}
30+
}
31+
}
32+
33+
if (prefix) {
34+
req.url = prefix + req.url
35+
}
36+
}
37+
38+
return cb()
39+
}
40+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"fg-multiple-hooks": "^1.2.0",
5252
"helmet": "^4.1.1",
5353
"http-lambda-proxy": "^1.0.1",
54+
"micromatch": "^4.0.2",
5455
"mocha": "^8.1.3",
5556
"nyc": "^15.1.0",
5657
"opossum": "^5.0.1",

test/hostnames-hook.test.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
'use strict'
2+
3+
/* global describe, it */
4+
const expect = require('chai').expect
5+
6+
describe('hostnames-hook', () => {
7+
let hostnamesHook = null
8+
9+
it('initialize', async () => {
10+
hostnamesHook = require('./../lib/hostnames-hook')([{
11+
prefix: '/nodejs',
12+
hostname: 'nodejs.org'
13+
}, {
14+
prefix: '/github',
15+
hostname: 'github.com'
16+
}, {
17+
prefix: '/users',
18+
hostname: '*.company.tld'
19+
}])
20+
})
21+
22+
it('is match - nodejs.org', (cb) => {
23+
const req = {
24+
headers: {
25+
host: 'nodejs.org:443'
26+
},
27+
url: '/about'
28+
}
29+
30+
hostnamesHook(req, null, () => {
31+
expect(req.url).to.equal('/nodejs/about')
32+
cb()
33+
})
34+
})
35+
36+
it('is match - github.com', (cb) => {
37+
const req = {
38+
headers: {
39+
host: 'github.com:443'
40+
},
41+
url: '/about'
42+
}
43+
44+
hostnamesHook(req, null, () => {
45+
expect(req.url).to.equal('/github/about')
46+
cb()
47+
})
48+
})
49+
50+
it('is match - wildcard', (cb) => {
51+
const req = {
52+
headers: {
53+
host: 'kyberneees.company.tld:443'
54+
},
55+
url: '/about'
56+
}
57+
58+
hostnamesHook(req, null, () => {
59+
expect(req.url).to.equal('/users/about')
60+
cb()
61+
})
62+
})
63+
64+
it('is not match - 404', (cb) => {
65+
const req = {
66+
headers: {
67+
host: 'facebook.com:443'
68+
},
69+
url: '/about'
70+
}
71+
72+
hostnamesHook(req, null, () => {
73+
expect(req.url).to.equal('/about')
74+
cb()
75+
})
76+
})
77+
})

0 commit comments

Comments
 (0)