-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathservice-class-example.js
114 lines (95 loc) · 3.03 KB
/
service-class-example.js
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
'use strict'
const http = require('http')
const { RpcWrapper, RpcServiceBase } = require('../index')
class ProductService extends RpcServiceBase {
constructor (products = []) {
super()
this.methods.push('create', 'remove', 'find')
this.products = products
}
async create (item) {
await Promise.resolve()
this.products.push(item)
}
remove (id) {
this.products = this.products.filter(p => p.id !== id)
}
async find (id) {
await Promise.resolve()
return this.products.find(p => p.id === id)
}
async areParamsValid (method, params) {
switch (method) {
case 'create':
if (typeof params !== 'object') return false
if (!Object.keys(params).every(key => ['id', 'name'].includes(key))) return false
if (!params.id || typeof params.id !== 'number') return false
if (!params.name || typeof params.name !== 'string') return false
return true
case 'find':
case 'remove':
return params[0] && typeof params[0] === 'number'
default: return false
}
}
}
// config
const PORT = parseInt(process.env.PORT || '7078')
const HOST = process.env.HOST || '127.0.0.1'
// service that will be proxied
const myService = new ProductService([
{ id: 1, name: 'Product 1' },
{ id: 2, name: 'Product 2' },
{ id: 3, name: 'Product 3' }
])
const rpcProxy = new RpcWrapper(myService)
const server = http.createServer((req, res) => {
// e.g. allow POST only in server
if (req.method.toUpperCase() !== 'POST') {
res.writeHead(405, 'Method Not Allowed')
return res.end()
}
if (req.url.replace(/\/$/, '') !== '/rpc') {
res.writeHead(403, 'Forbidden')
return res.end()
}
const chunks = []
req.on('data', (data) => {
chunks.push(data.toString('utf-8'))
})
req.on('end', async () => {
const payload = chunks.join('')
const rpcRes = await rpcProxy.callReq(payload)
if (!rpcRes || (Array.isArray(rpcRes) && rpcRes.length === 0)) {
res.writeHead(204, 'No Content')
res.end()
return
}
res.setHeader('Content-Type', 'application/json')
res.write(JSON.stringify(rpcRes))
res.end()
})
})
server.listen(PORT, HOST, () => {
console.log(`HTTP server is listening on ${HOST}:${PORT}`)
})
/**
Request example:
curl -X POST \
http://localhost:7078/rpc \
-H 'Content-Type: application/json' \
-d '[
{ "jsonrpc": "2.0", "method": "create", "params": { "id": 4, "name": "Product 4" }, "id": "1" },
{ "jsonrpc": "2.0", "method": "remove", "params": [ 2 ], "id": "2" },
{ "jsonrpc": "2.0", "method": "find", "params": [ 1 ], "id": "3" },
{ "jsonrpc": "2.0", "method": "create", "params": { "id": 5, "name": "Product 4" } },
{ "jsonrpc": "2.0", "method": "find", "params": [ "abc" ], "id": 4 }
]' | jq '.'
Response example:
[
{ "jsonrpc": "2.0", "id": "1", "result": null },
{ "jsonrpc": "2.0", "id": "2", "result": null },
{ "jsonrpc": "2.0", "id": "3", "result": { "id": 1, "name": "Product 1" } },
{ "jsonrpc": "2.0", "id": 4, "error": { "code": -32602, "message": "Invalid params" } }
]
*/