Domain name routing
Starting from 0.28.0, fibjs
the mq.Routing object supports the HOST method as domain name routing.
1
2
3
4
5
6
7
8
9
10
11
12const mq = require('mq')
const rt = new mq.Routing();
// support *.fibjs.org in Routing
rt.host('*.fibjs.org', ...)
// support api.fibjs.org in Routing
rt.host('api.fibjs.org', ...)
// support fibjs.org in Routing
rt.host('fibjs.org', ...)
rt.append('host', 'fibjs.org', ...)
Let's look at some examples.
Simple example
Simple fileHandlers
Assume that the domain name fibjs.org has been bound to the machine where our application is located (for testing purposes, you can also achieve this binding effect by modifying Hosts locally), and we hope to be file.fibjs.org
able to download file resources in the FILE_DIR directory on the machine , we can do this:
1
2
3
4
5
6const mq = require('mq')
const http = require('http')
const fileRoutes = new mq.Routing();
// support file.fibjs.org in Routing
fileRoutes.host('file.fibjs.org', http.fileHandler(FILE_DIR))
Front-end resource host
A typical scenario is that the compiled front-end application may be published to the machine, for example, saved in /home/frontend/assets/
the directory
1
2
3
4
5/home/frontend/assets/index.html
/home/frontend/assets/200.html
/home/frontend/assets/app.839ca9.js
/home/frontend/assets/common.537a50.js
/home/frontend/assets/chunk.d45858.js
And if we want to obtain these resources through festatic.fibjs.org, we can write like this:
1fileRoutes.host('festatic.fibjs.org', http.fileHandlers('/home/frontend/assets/'))
api server
Suppose there are API servers on your machine, and you want to unify them to api.fibjs.org
this domain name, but assign different paths, such as:
API Server | Usage | Path |
---|---|---|
http://127.0.0.1:3001 | User Service | /user |
http://127.0.0.1:8080 | Biz1 | /biz1 |
http://127.0.0.1:9007 | Biz2 | /biz2 |
Then you can:
1
2
3
4
5
6
7
8
9
10const mq = require('mq')
const apiRoutes = new mq.Routing();
// proxyTo 是代理请求到对应 origin 的函数
apiRoutes.host('api.fibjs.org', {
'/user': (req) => proxyTo(req, `http://127.0.0.1:3001`),
'/biz1': (req) => proxyTo(req, `http://127.0.0.1:8080`),
'/biz2': (req) => proxyTo(req, `http://127.0.0.1:9007`),
})
Furthermore, if you want the '/biz1' path to only accept http POST requests, you can:
1
2
3
4
5
6
7
8
9const mq = require('mq')
const apiRoutes = new mq.Routing();
apiRoutes.host('api.fibjs.org', {
'/user': (req) => proxyTo(req, `http://127.0.0.1:3001`),
'/biz1': apiRoutes.post((req) => proxyTo(req, `http://127.0.0.1:8080`)),
'/biz2': (req) => proxyTo(req, `http://127.0.0.1:9007`),
})
Note that api.fibjs.org must be bound to the current machine
Complex example
If there are no other declarations, in the following example, the following functions exist:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// 生成带特定 host 的请求
function getRequest({
path = '/',
host = 'www.fibjs.org'
}) {
const req = new http.Request()
req.value = path
req.addHeader('host', host)
return req
}
// 以 method 尝试对 routes 发起一个 header: host=host 的请求
function invokePathFromHost (path, host, method = 'GET') {
const req = getRequest({ path, host })
req.method = method
mq.invoke(routes, req)
const result = req.response.body.readAll()
return result ? result.toString() : result
}
Domain name diversion
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36const mq = require('mq')
const http = require('http')
const assert = require('assert')
const routes = new mq.Routing();
routes.host('api.fibjs.org', [
{
'/user/information': req => req.response.json({name: 'xicilion'}),
},
req => req.response.body.rewind()
])
// routes.host 方法可以多次调用
routes.host('*.fibjs.org', [
{
'/': req => req.response.json({message: 'I am in root'}),
'/index.html': req => req.response.body.write(`<html><body>hello fibjs</body></html>`),
'/index.js': req => req.response.body.write(`console.log('hello world')`),
'*': (req, domain) => {
req.response.json({message: 'I am fallback'})
}
},
req => req.response.body.rewind()
])
assert.equal( invokePathFromHost('/', 'www.fibjs.org'), `{"message":"I am in root"}` )
assert.equal( invokePathFromHost('/index.html', 'static.fibjs.org'), `<html><body>hello fibjs</body></html>` )
assert.equal( invokePathFromHost('/index.js', 'static.fibjs.org'), `console.log('hello world')` )
assert.equal( invokePathFromHost('/user/information', 'api.fibjs.org'), JSON.stringify({name: 'xicilion'}) )
try {
invokePathFromHost('/', 'fibjs.org')
} catch (error) {
assert.equal(error, 'Error: Routing: unknown routing: fibjs.org')
}
Next, you only need to mount the routes in the above example to an http(s)Server, and it can start working. If the server listens to the default port of the machine (usually 80), then a traffic distribution based on the domain name The gateway services for different routes have been set up - this means that to complete the same function, you can only use fibjs's mq.Routing without having to install traditional gateway services such as nginx/apache/tomcat/iis.