Skip to content

Commit 7249128

Browse files
committed
initial commit
1 parent 63078ac commit 7249128

File tree

5 files changed

+86
-24
lines changed

5 files changed

+86
-24
lines changed

demos/ws-proxy.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
const http = require('http')
2-
const WebSocket = require('faye-websocket')
1+
'use strict'
32

4-
const server = http.createServer()
3+
const gateway = require('./../index')
4+
const PORT = process.env.PORT || 8080
55

6-
server.on('upgrade', (request, socket, body) => {
7-
const client = new WebSocket(request, socket, body)
8-
const target = new WebSocket.Client('ws://ws.ifelse.io')
6+
gateway({
7+
routes: [{
8+
// ... other HTTP or WebSocket routes
9+
}, {
10+
proxyType: 'websocket',
11+
prefix: '/echo',
12+
target: 'ws://ws.ifelse.io',
13+
hooks: {
14+
onOpen: (ws, searchParams) => {
915

10-
client.pipe(target)
11-
target.pipe(client)
16+
}
17+
}
18+
}]
19+
}).start(PORT).then(server => {
20+
console.log(`API Gateway listening on ${PORT} port!`)
1221
})
13-
14-
server.listen(3000)

index.d.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@ declare namespace fastgateway {
3535

3636
interface WebSocketRoute {
3737
proxyType: 'websocket';
38-
proxyConfig?: {};
39-
proxyHandler?: Function;
38+
proxyConfig?: {}; // https://github.com/faye/faye-websocket-node#initialization-options
4039
prefix: string;
41-
prefixRewrite?: string;
4240
target: string;
43-
middlewares?: Function[];
41+
subProtocols?: []; // https://github.com/faye/faye-websocket-node#subprotocol-negotiation
42+
hooks?: WebSocketHooks;
43+
}
44+
45+
interface WebSocketHooks {
46+
onOpen?: Function;
4447
}
4548

4649
interface Hooks {

index.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const defaultProxyHandler = (req, res, url, proxy, proxyOpts) => proxy(req, res,
88
const DEFAULT_METHODS = require('restana/libs/methods').filter(method => method !== 'all')
99
const send = require('@polka/send-type')
1010
const PROXY_TYPES = ['http', 'lambda']
11+
const wsProxy = require('./lib/ws-proxy')
1112

1213
const gateway = (opts) => {
1314
const proxyFactory = opts.proxyFactory || defaultProxyFactory
@@ -17,24 +18,31 @@ const gateway = (opts) => {
1718
pathRegex: '/*'
1819
}, opts)
1920

20-
const server = opts.server || restana(opts.restana)
21+
const router = opts.server || restana(opts.restana)
2122

2223
// registering global middlewares
2324
opts.middlewares.forEach(middleware => {
24-
server.use(middleware)
25+
router.use(middleware)
2526
})
2627

2728
// registering services.json
2829
const services = opts.routes.map(route => ({
2930
prefix: route.prefix,
3031
docs: route.docs
3132
}))
32-
server.get('/services.json', (req, res) => {
33+
router.get('/services.json', (req, res) => {
3334
send(res, 200, services)
3435
})
3536

36-
// processing routes
37-
opts.routes.forEach(route => {
37+
// processing websocket routes
38+
const wsRoutes = opts.routes.filter(route => route.proxyType === 'websocket')
39+
wsProxy({
40+
routes: wsRoutes,
41+
server: router.getServer()
42+
})
43+
44+
// processing non-websocket routes
45+
opts.routes.filter(route => route.proxyType !== 'websocket').forEach(route => {
3846
if (undefined === route.prefixRewrite) {
3947
route.prefixRewrite = ''
4048
}
@@ -82,13 +90,13 @@ const gateway = (opts) => {
8290

8391
methods.forEach(method => {
8492
method = method.toLowerCase()
85-
if (server[method]) {
86-
server[method].apply(server, args)
93+
if (router[method]) {
94+
router[method].apply(router, args)
8795
}
8896
})
8997
})
9098

91-
return server
99+
return router
92100
}
93101

94102
const handler = (route, proxy, proxyHandler) => async (req, res, next) => {

lib/ws-proxy.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict'
2+
3+
const WebSocket = require('faye-websocket')
4+
5+
function onOpenNoOp () {}
6+
7+
module.exports = (config) => {
8+
const { routes, server } = config
9+
10+
const prefix2route = {}
11+
for (const route of routes) {
12+
prefix2route[route.prefix] = route
13+
}
14+
15+
server.on('upgrade', async (req, socket, body) => {
16+
if (WebSocket.isWebSocket(req)) {
17+
const url = new URL('http://dummy' + req.url)
18+
const route = prefix2route[url.pathname]
19+
20+
if (route) {
21+
const subProtocols = route.subProtocols || []
22+
const client = new WebSocket(req, socket, body, subProtocols)
23+
route.hooks = route.hooks || {}
24+
const onOpen = route.hooks.onOpen || onOpenNoOp
25+
26+
try {
27+
await onOpen(client, url.searchParams)
28+
29+
const target = route.target + '?' + url.searchParams.toString()
30+
const remote = new WebSocket.Client(target, subProtocols, route.proxyConfig)
31+
32+
client.pipe(remote)
33+
remote.pipe(client)
34+
} catch (err) {
35+
client.close(err.closeEventCode || 4000, err.message)
36+
}
37+
} else {
38+
socket.destroy()
39+
}
40+
} else {
41+
socket.destroy()
42+
}
43+
})
44+
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"homepage": "https://github.com/jkyberneees/fast-gateway#readme",
2929
"dependencies": {
3030
"@polka/send-type": "^0.5.2",
31-
"fast-proxy-lite": "^1.0.1",
31+
"fast-proxy-lite": "^1.0.2",
3232
"http-cache-middleware": "^1.3.8",
3333
"restana": "^4.9.2",
3434
"stream-to-array": "^2.3.0"
@@ -42,7 +42,7 @@
4242
],
4343
"devDependencies": {
4444
"@types/express": "^4.17.11",
45-
"aws-sdk": "^2.1023.0",
45+
"aws-sdk": "^2.1037.0",
4646
"chai": "^4.3.4",
4747
"cors": "^2.8.5",
4848
"express": "^4.17.1",

0 commit comments

Comments
 (0)