grenache-nodejs-http 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -11
- package/test/before-after.js +56 -15
- package/test/peer-rpc-server-buffered.js +129 -156
- package/test/peer-rpc-server-secure-buffered.js +128 -176
- package/test/peer-rpc-server-secure-streaming.js +84 -127
- package/test/peer-rpc-server-secure.js +30 -78
- package/test/peer-rpc-server-streaming.js +84 -111
- package/test/peer-rpc-server.js +27 -57
- package/test/rpc-server-manual-request-handling.js +22 -53
- package/test/rpc-server-readstream-size.js +20 -48
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grenache-nodejs-http",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Grenache Node.js HTTP implementation",
|
|
6
6
|
"author": "prdn <paolo@bitfinex.com> (https://bitfinex.com/)",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"grenache",
|
|
@@ -11,27 +11,27 @@
|
|
|
11
11
|
"micro-services"
|
|
12
12
|
],
|
|
13
13
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
14
|
+
"node": ">=22.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"async": "3.2.6",
|
|
18
18
|
"duplexify": "4.1.3",
|
|
19
|
-
"grenache-nodejs-base": "
|
|
20
|
-
"grenache-nodejs-link": "
|
|
19
|
+
"grenache-nodejs-base": "2.0.0",
|
|
20
|
+
"grenache-nodejs-link": "2.0.0",
|
|
21
21
|
"node-fetch": "2.7.0",
|
|
22
22
|
"pump": "3.0.2"
|
|
23
23
|
},
|
|
24
24
|
"main": "index.js",
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
26
|
+
"@bitfinex/lint-js": "^1.1.0",
|
|
27
|
+
"brittle": "^4.5.0",
|
|
28
|
+
"grenache-grape": "^2.0.0"
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"test": "npm run lint && npm run unit",
|
|
32
|
-
"unit": "
|
|
33
|
-
"lint": "
|
|
34
|
-
"lint:fix": "
|
|
32
|
+
"unit": "brittle-node test/*.js",
|
|
33
|
+
"lint": "bfx-lint-js",
|
|
34
|
+
"lint:fix": "bfx-lint-js --fix"
|
|
35
35
|
},
|
|
36
36
|
"license": "Apache-2.0",
|
|
37
37
|
"repository": {
|
package/test/before-after.js
CHANGED
|
@@ -1,28 +1,69 @@
|
|
|
1
|
-
/* eslint-env mocha */
|
|
2
|
-
|
|
3
1
|
'use strict'
|
|
4
2
|
|
|
5
3
|
const { startGrapes, stopGrapes } = require('./helper')
|
|
4
|
+
const Link = require('grenache-nodejs-link')
|
|
5
|
+
const { PeerRPCClient, PeerRPCServer } = require('../index')
|
|
6
|
+
const fs = require('fs')
|
|
7
|
+
const path = require('path')
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
function setupHooks (cb) {
|
|
9
|
-
beforeEach(async function () {
|
|
10
|
-
this.timeout(20000)
|
|
9
|
+
const SERVICE_PORT = 1337
|
|
11
10
|
|
|
11
|
+
const rpcTestCase = ({ transport, isSecure, disableBuffered }) => (testBlock) => async (t) => {
|
|
12
|
+
let grapes, peer, link, service
|
|
13
|
+
try {
|
|
12
14
|
grapes = await startGrapes()
|
|
13
|
-
cb()
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
const announceTask = new Promise((resolve) => {
|
|
16
17
|
grapes[0].once('announce', () => resolve())
|
|
17
18
|
})
|
|
18
|
-
|
|
19
|
+
link = new Link({
|
|
20
|
+
grape: 'http://127.0.0.1:30001'
|
|
21
|
+
})
|
|
22
|
+
link.start()
|
|
23
|
+
|
|
24
|
+
const peerOpts = {}
|
|
25
|
+
if (isSecure) {
|
|
26
|
+
peerOpts.secure = {
|
|
27
|
+
key: fs.readFileSync(path.join(__dirname, './certs/client1-key.pem')),
|
|
28
|
+
cert: fs.readFileSync(path.join(__dirname, './certs/client1-crt.pem')),
|
|
29
|
+
ca: fs.readFileSync(path.join(__dirname, './certs/ca-crt.pem')),
|
|
30
|
+
rejectUnauthorized: false // take care, can be dangerous in production!
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
peer = new PeerRPCClient(link, peerOpts)
|
|
34
|
+
peer.init()
|
|
19
35
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
36
|
+
const peerSrvOpts = {
|
|
37
|
+
timeout: 300000
|
|
38
|
+
}
|
|
39
|
+
if (isSecure) {
|
|
40
|
+
peerSrvOpts.secure = {
|
|
41
|
+
key: fs.readFileSync(path.join(__dirname, './certs/server-key.pem')),
|
|
42
|
+
cert: fs.readFileSync(path.join(__dirname, './certs/server-crt.pem')),
|
|
43
|
+
ca: fs.readFileSync(path.join(__dirname, './certs/ca-crt.pem')),
|
|
44
|
+
requestCert: true,
|
|
45
|
+
rejectUnauthorized: false // take care, can be dangerous in production!
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (disableBuffered) { peerSrvOpts.disableBuffered = true }
|
|
49
|
+
const peerSrv = new PeerRPCServer(link, peerSrvOpts)
|
|
50
|
+
|
|
51
|
+
peerSrv.init()
|
|
52
|
+
service = peerSrv.transport(transport)
|
|
53
|
+
service.listen(SERVICE_PORT)
|
|
54
|
+
|
|
55
|
+
link.announce('rpc_test', service.port, {}, (err) => {
|
|
56
|
+
if (err) throw Error('error in announce, setup')
|
|
57
|
+
})
|
|
58
|
+
await announceTask
|
|
24
59
|
|
|
25
|
-
|
|
60
|
+
await testBlock({ t, service, peer })
|
|
61
|
+
} finally {
|
|
62
|
+
if (peer) peer.stop()
|
|
63
|
+
if (link) link.stop()
|
|
64
|
+
if (service) service.stop()
|
|
65
|
+
if (grapes) await stopGrapes(grapes)
|
|
66
|
+
}
|
|
26
67
|
}
|
|
27
68
|
|
|
28
|
-
module.exports =
|
|
69
|
+
module.exports = { rpcTestCase }
|
|
@@ -1,221 +1,195 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const test = require('brittle')
|
|
4
4
|
const { PassThrough } = require('stream')
|
|
5
5
|
const fs = require('fs')
|
|
6
6
|
const path = require('path')
|
|
7
|
-
const {
|
|
8
|
-
const Link = require('grenache-nodejs-link')
|
|
9
|
-
const setupHooks = require('./before-after.js')
|
|
7
|
+
const { rpcTestCase } = require('./before-after')
|
|
10
8
|
|
|
11
|
-
const
|
|
12
|
-
let link, peer, peerSrvBuf, serviceBuf, stop
|
|
13
|
-
describe('RPC integration', () => {
|
|
14
|
-
setupHooks((grapes) => {
|
|
15
|
-
link = new Link({
|
|
16
|
-
grape: 'http://127.0.0.1:30001'
|
|
17
|
-
})
|
|
18
|
-
link.start()
|
|
19
|
-
|
|
20
|
-
peer = new PeerRPCClient(link, {})
|
|
21
|
-
peer.init()
|
|
22
|
-
|
|
23
|
-
peerSrvBuf = new PeerRPCServer(link, {
|
|
24
|
-
timeout: 300000
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
peerSrvBuf.init()
|
|
28
|
-
serviceBuf = peerSrvBuf.transport('buffered')
|
|
29
|
-
serviceBuf.listen(PORT)
|
|
30
|
-
|
|
31
|
-
link.announce('rpc_buf', serviceBuf.port, {}, (err, res) => {
|
|
32
|
-
if (err) throw Error('error in announce, setup')
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
stop = () => {
|
|
36
|
-
peer.stop()
|
|
37
|
-
link.stop()
|
|
38
|
-
serviceBuf.stop()
|
|
39
|
-
}
|
|
40
|
-
})
|
|
9
|
+
const rpcTest = rpcTestCase({ transport: 'buffered' })
|
|
41
10
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
11
|
+
test('RPC integration', async (t) => {
|
|
12
|
+
await t.test('buffered parsing works, objects', { timeout: 7000 }, rpcTest(async ({ t, service, peer }) => {
|
|
13
|
+
service.on('request', (rid, key, payload, handler, cert, meta) => {
|
|
14
|
+
t.ok(typeof rid === 'string')
|
|
15
|
+
t.is(key, 'rpc_test')
|
|
16
|
+
t.alike(payload, { hello: 'world' })
|
|
47
17
|
|
|
48
|
-
|
|
18
|
+
t.is(meta.isStream, false)
|
|
49
19
|
|
|
50
20
|
handler.reply(null, { hello: 'helloworld' })
|
|
51
21
|
})
|
|
52
22
|
|
|
53
23
|
const opts = { timeout: 100000 }
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
done()
|
|
24
|
+
await new Promise(resolve => {
|
|
25
|
+
peer.request('rpc_test', { hello: 'world' }, opts, (err, result) => {
|
|
26
|
+
if (err) throw err
|
|
27
|
+
t.alike(result, { hello: 'helloworld' })
|
|
28
|
+
resolve()
|
|
29
|
+
})
|
|
61
30
|
})
|
|
62
|
-
})
|
|
31
|
+
}))
|
|
63
32
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
33
|
+
await t.test('buffered parsing works, strings', { timeout: 7000 }, rpcTest(async ({ t, service, peer }) => {
|
|
34
|
+
service.on('request', (rid, key, payload, handler, cert, meta) => {
|
|
35
|
+
t.ok(typeof rid === 'string')
|
|
36
|
+
t.is(key, 'rpc_test')
|
|
37
|
+
t.is(payload, 'hello')
|
|
69
38
|
|
|
70
|
-
|
|
39
|
+
t.is(meta.isStream, false)
|
|
71
40
|
|
|
72
41
|
handler.reply(null, 'world')
|
|
73
42
|
})
|
|
74
43
|
|
|
75
44
|
const opts = { timeout: 100000 }
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
done()
|
|
45
|
+
await new Promise(resolve => {
|
|
46
|
+
peer.request('rpc_test', 'hello', opts, (err, result) => {
|
|
47
|
+
if (err) throw err
|
|
48
|
+
t.is(result, 'world')
|
|
49
|
+
resolve()
|
|
50
|
+
})
|
|
83
51
|
})
|
|
84
|
-
})
|
|
52
|
+
}))
|
|
85
53
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
54
|
+
await t.test('buffered parsing works, compressed strings', { timeout: 7000 }, rpcTest(async ({ t, service, peer }) => {
|
|
55
|
+
service.on('request', (rid, key, payload, handler, cert, meta) => {
|
|
56
|
+
t.ok(typeof rid === 'string')
|
|
57
|
+
t.is(key, 'rpc_test')
|
|
58
|
+
t.is(payload, 'hello')
|
|
91
59
|
|
|
92
|
-
|
|
93
|
-
|
|
60
|
+
t.is(meta.isStream, false)
|
|
61
|
+
t.is(meta.compress, true)
|
|
94
62
|
|
|
95
63
|
handler.reply(null, 'world')
|
|
96
64
|
})
|
|
97
65
|
|
|
98
66
|
const opts = { timeout: 100000, compress: true }
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
done()
|
|
67
|
+
await new Promise(resolve => {
|
|
68
|
+
peer.request('rpc_test', 'hello', opts, (err, result) => {
|
|
69
|
+
if (err) throw err
|
|
70
|
+
t.is(result, 'world')
|
|
71
|
+
resolve()
|
|
72
|
+
})
|
|
106
73
|
})
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it('buffered parsing works, strings from streaming client', (done) => {
|
|
110
|
-
serviceBuf.on('request', (rid, key, payload, handler, cert, meta) => {
|
|
111
|
-
assert.ok(typeof rid === 'string')
|
|
112
|
-
assert.strictEqual(key, 'rpc_buf')
|
|
113
|
-
assert.strictEqual(payload, 'hello')
|
|
114
|
-
|
|
115
|
-
assert.strictEqual(meta.isStream, true)
|
|
74
|
+
}))
|
|
116
75
|
|
|
76
|
+
await t.test('buffered parsing works, strings from streaming client', { timeout: 7000 }, rpcTest(async ({ t, service, peer }) => {
|
|
77
|
+
service.on('request', (rid, key, payload, handler, cert, meta) => {
|
|
78
|
+
t.ok(typeof rid === 'string')
|
|
79
|
+
t.is(key, 'rpc_test')
|
|
80
|
+
t.is(payload, 'hello')
|
|
81
|
+
t.is(meta.isStream, true)
|
|
117
82
|
handler.reply(null, 'world')
|
|
118
83
|
})
|
|
119
84
|
|
|
120
|
-
const req = peer.stream('
|
|
85
|
+
const req = peer.stream('rpc_test', {
|
|
121
86
|
timeout: 10000
|
|
122
87
|
})
|
|
123
88
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
89
|
+
const p = new Promise(resolve => {
|
|
90
|
+
req
|
|
91
|
+
.on('data', (data) => {
|
|
92
|
+
const d = JSON.parse(data.toString())
|
|
93
|
+
// ["65c5737f-bbce-40f9-b48a-af8bd8869d66",null,"world"]
|
|
94
|
+
t.is(d[1], null)
|
|
95
|
+
t.is(d[2], 'world')
|
|
96
|
+
resolve()
|
|
97
|
+
})
|
|
98
|
+
.on('end', () => {})
|
|
99
|
+
.on('error', (e) => { console.error(e) })
|
|
100
|
+
})
|
|
135
101
|
|
|
136
102
|
const writable = new PassThrough()
|
|
137
|
-
writable.write('["UUID", "
|
|
103
|
+
writable.write('["UUID", "rpc_test", "hello"]')
|
|
138
104
|
writable.end()
|
|
139
105
|
writable.pipe(req)
|
|
140
|
-
}).timeout(7000)
|
|
141
106
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
assert.ok(typeof rid === 'string')
|
|
145
|
-
assert.strictEqual(key, 'rpc_buf')
|
|
146
|
-
assert.deepStrictEqual(payload, { hello: 'world' })
|
|
107
|
+
await p
|
|
108
|
+
}))
|
|
147
109
|
|
|
148
|
-
|
|
110
|
+
await t.test('buffered parsing works, objects from streaming client', { timeout: 7000 }, rpcTest(async ({ t, service, peer }) => {
|
|
111
|
+
service.on('request', (rid, key, payload, handler, cert, meta) => {
|
|
112
|
+
t.ok(typeof rid === 'string')
|
|
113
|
+
t.is(key, 'rpc_test')
|
|
114
|
+
t.alike(payload, { hello: 'world' })
|
|
115
|
+
|
|
116
|
+
t.is(meta.isStream, true)
|
|
149
117
|
|
|
150
118
|
handler.reply(null, { hello: 'helloworld' })
|
|
151
119
|
})
|
|
152
120
|
|
|
153
|
-
const req = peer.stream('
|
|
121
|
+
const req = peer.stream('rpc_test', {
|
|
154
122
|
timeout: 10000
|
|
155
123
|
})
|
|
156
124
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
125
|
+
const p = new Promise(resolve => {
|
|
126
|
+
req
|
|
127
|
+
.on('data', (data) => {
|
|
128
|
+
const d = JSON.parse(data.toString())
|
|
129
|
+
t.is(d[1], null)
|
|
130
|
+
t.alike(d[2], { hello: 'helloworld' })
|
|
131
|
+
resolve()
|
|
132
|
+
})
|
|
133
|
+
.on('end', () => {})
|
|
134
|
+
.on('error', (e) => { console.error(e) })
|
|
135
|
+
})
|
|
167
136
|
|
|
168
137
|
const writable = new PassThrough()
|
|
169
|
-
writable.write('["UUID", "
|
|
138
|
+
writable.write('["UUID", "rpc_test", { "hello": "world" }]')
|
|
170
139
|
writable.end()
|
|
171
140
|
writable.pipe(req)
|
|
172
|
-
}).timeout(7000)
|
|
173
141
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
142
|
+
await p
|
|
143
|
+
}))
|
|
144
|
+
|
|
145
|
+
await t.test('buffered parsing works, extra headers', { timeout: 7000 }, rpcTest(async ({ t, service, peer }) => {
|
|
146
|
+
service.on('request', (rid, key, payload, handler, cert, meta) => {
|
|
147
|
+
t.ok(typeof rid === 'string')
|
|
148
|
+
t.is(key, 'rpc_test')
|
|
149
|
+
t.alike(payload, { hello: 'world' })
|
|
179
150
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
151
|
+
t.is(meta.action, 'uploadPublic')
|
|
152
|
+
t.alike(meta.args, { foo: 'bar' })
|
|
153
|
+
t.is(meta.isStream, true)
|
|
183
154
|
|
|
184
155
|
handler.reply(null, { hello: 'helloworld' })
|
|
185
156
|
})
|
|
186
157
|
|
|
187
|
-
const req = peer.stream('
|
|
158
|
+
const req = peer.stream('rpc_test', {
|
|
188
159
|
timeout: 10000,
|
|
189
160
|
headers: { _a: 'uploadPublic', _ar: { foo: 'bar' } }
|
|
190
161
|
})
|
|
191
162
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
163
|
+
const p = new Promise(resolve => {
|
|
164
|
+
req
|
|
165
|
+
.on('data', (data) => {
|
|
166
|
+
const d = JSON.parse(data.toString())
|
|
167
|
+
t.is(d[1], null)
|
|
168
|
+
t.alike(d[2], { hello: 'helloworld' })
|
|
169
|
+
resolve()
|
|
170
|
+
})
|
|
171
|
+
.on('end', () => {})
|
|
172
|
+
.on('error', (e) => { console.error(e) })
|
|
173
|
+
})
|
|
202
174
|
|
|
203
175
|
const writable = new PassThrough()
|
|
204
|
-
writable.write('["UUID", "
|
|
176
|
+
writable.write('["UUID", "rpc_test", { "hello": "world" }]')
|
|
205
177
|
writable.end()
|
|
206
178
|
writable.pipe(req)
|
|
207
|
-
}).timeout(7000)
|
|
208
179
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
assert.ok(typeof rid === 'string')
|
|
212
|
-
assert.strictEqual(key, 'rpc_buf')
|
|
180
|
+
await p
|
|
181
|
+
}))
|
|
213
182
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
183
|
+
await t.test('buf/buf: serialized files work', { timeout: 7000 }, rpcTest(async ({ t, service, peer }) => {
|
|
184
|
+
service.on('request', (rid, key, payload, handler, cert, meta) => {
|
|
185
|
+
t.ok(typeof rid === 'string')
|
|
186
|
+
t.is(key, 'rpc_test')
|
|
217
187
|
|
|
218
|
-
|
|
188
|
+
t.is(payload.action, 'uploadPublic')
|
|
189
|
+
t.is(payload.args[1].key, 'example-amazon-dynamo-sosp2007-4.pdf')
|
|
190
|
+
t.is(typeof payload.args[0], 'string')
|
|
191
|
+
|
|
192
|
+
t.is(meta.isStream, false)
|
|
219
193
|
|
|
220
194
|
handler.reply(null, 'ok')
|
|
221
195
|
})
|
|
@@ -236,13 +210,12 @@ describe('RPC integration', () => {
|
|
|
236
210
|
action: 'uploadPublic',
|
|
237
211
|
args: [buf.toString('hex'), optsPdf]
|
|
238
212
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
done()
|
|
213
|
+
await new Promise(resolve => {
|
|
214
|
+
peer.request('rpc_test', queryUploadPublicPdf, opts, (err, result) => {
|
|
215
|
+
if (err) throw err
|
|
216
|
+
t.alike(result, 'ok')
|
|
217
|
+
resolve()
|
|
218
|
+
})
|
|
246
219
|
})
|
|
247
|
-
})
|
|
220
|
+
}))
|
|
248
221
|
})
|