Skip to content

Commit 88ec702

Browse files
authored
Bolt agent added to hello metadata (#1076)
1 parent 1d15ccb commit 88ec702

File tree

98 files changed

+3000
-251
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+3000
-251
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"build::notci": "lerna bootstrap",
4545
"docs": "lerna run docs --stream --concurrency 1",
4646
"test::unit": "lerna run test::unit --stream",
47+
"test::deno": "lerna run test::deno --stream",
4748
"test::integration": "lerna run test::integration --stream",
4849
"test::browser": "lerna run test::browser --stream",
4950
"test::stress": "lerna run test::stress --stream",

packages/bolt-connection/src/bolt/bolt-protocol-v1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export default class BoltProtocol {
175175
* @param {function()} param.onComplete the callback to invoke on completion.
176176
* @returns {StreamObserver} the stream observer that monitors the corresponding server response.
177177
*/
178-
initialize ({ userAgent, authToken, notificationFilter, onError, onComplete } = {}) {
178+
initialize ({ userAgent, boltAgent, authToken, notificationFilter, onError, onComplete } = {}) {
179179
const observer = new LoginObserver({
180180
onError: error => this._onLoginError(error, onError),
181181
onCompleted: metadata => this._onLoginCompleted(metadata, onComplete)

packages/bolt-connection/src/bolt/bolt-protocol-v3.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export default class BoltProtocol extends BoltProtocolV2 {
6969
return metadata
7070
}
7171

72-
initialize ({ userAgent, authToken, notificationFilter, onError, onComplete } = {}) {
72+
initialize ({ userAgent, boltAgent, authToken, notificationFilter, onError, onComplete } = {}) {
7373
const observer = new LoginObserver({
7474
onError: error => this._onLoginError(error, onError),
7575
onCompleted: metadata => this._onLoginCompleted(metadata, authToken, onComplete)

packages/bolt-connection/src/bolt/bolt-protocol-v4x1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export default class BoltProtocol extends BoltProtocolV4 {
7373
return this._transformer
7474
}
7575

76-
initialize ({ userAgent, authToken, notificationFilter, onError, onComplete } = {}) {
76+
initialize ({ userAgent, boltAgent, authToken, notificationFilter, onError, onComplete } = {}) {
7777
const observer = new LoginObserver({
7878
onError: error => this._onLoginError(error, onError),
7979
onCompleted: metadata => this._onLoginCompleted(metadata, authToken, onComplete)

packages/bolt-connection/src/bolt/bolt-protocol-v4x3.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export default class BoltProtocol extends BoltProtocolV42 {
8989
* @param {function(onComplte)} args.onComplete On complete callback
9090
* @returns {LoginObserver} The Login observer
9191
*/
92-
initialize ({ userAgent, authToken, notificationFilter, onError, onComplete } = {}) {
92+
initialize ({ userAgent, boltAgent, authToken, notificationFilter, onError, onComplete } = {}) {
9393
const observer = new LoginObserver({
9494
onError: error => this._onLoginError(error, onError),
9595
onCompleted: metadata => {

packages/bolt-connection/src/bolt/bolt-protocol-v5x0.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export default class BoltProtocol extends BoltProtocolV44 {
5353
* @param {function(onComplte)} args.onComplete On complete callback
5454
* @returns {LoginObserver} The Login observer
5555
*/
56-
initialize ({ userAgent, authToken, notificationFilter, onError, onComplete } = {}) {
56+
initialize ({ userAgent, boltAgent, authToken, notificationFilter, onError, onComplete } = {}) {
5757
const observer = new LoginObserver({
5858
onError: error => this._onLoginError(error, onError),
5959
onCompleted: metadata => this._onLoginCompleted(metadata, authToken, onComplete)

packages/bolt-connection/src/bolt/bolt-protocol-v5x1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default class BoltProtocol extends BoltProtocolV5x0 {
5757
* @param {function(onComplete)} args.onComplete On complete callback
5858
* @returns {LoginObserver} The Login observer
5959
*/
60-
initialize ({ userAgent, authToken, notificationFilter, onError, onComplete } = {}) {
60+
initialize ({ userAgent, boltAgent, authToken, notificationFilter, onError, onComplete } = {}) {
6161
const state = {}
6262
const observer = new LoginObserver({
6363
onError: error => this._onLoginError(error, onError),

packages/bolt-connection/src/bolt/bolt-protocol-v5x2.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,14 @@ export default class BoltProtocol extends BoltProtocolV5x1 {
5050
*
5151
* @param {Object} args The params
5252
* @param {string} args.userAgent The user agent
53+
* @param {string} args.boltAgent The bolt agent
5354
* @param {any} args.authToken The auth token
5455
* @param {NotificationFilter} args.notificationFilter The notification filters.
5556
* @param {function(error)} args.onError On error callback
5657
* @param {function(onComplete)} args.onComplete On complete callback
5758
* @returns {LoginObserver} The Login observer
5859
*/
59-
initialize ({ userAgent, authToken, notificationFilter, onError, onComplete } = {}) {
60+
initialize ({ userAgent, boltAgent, authToken, notificationFilter, onError, onComplete } = {}) {
6061
const state = {}
6162
const observer = new LoginObserver({
6263
onError: error => this._onLoginError(error, onError),
@@ -67,6 +68,7 @@ export default class BoltProtocol extends BoltProtocolV5x1 {
6768
})
6869

6970
this.write(
71+
// if useragent is null then for all versions before 5.3 it should be bolt agent by default
7072
RequestMessage.hello5x2(userAgent, notificationFilter, this._serversideRouting),
7173
observer,
7274
false
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
import BoltProtocolV5x2 from './bolt-protocol-v5x2'
20+
21+
import transformersFactories from './bolt-protocol-v5x3.transformer'
22+
import Transformer from './transformer'
23+
import RequestMessage from './request-message'
24+
import { LoginObserver } from './stream-observers'
25+
26+
import { internal } from 'neo4j-driver-core'
27+
28+
const {
29+
constants: { BOLT_PROTOCOL_V5_3 }
30+
} = internal
31+
32+
export default class BoltProtocol extends BoltProtocolV5x2 {
33+
get version () {
34+
return BOLT_PROTOCOL_V5_3
35+
}
36+
37+
get transformer () {
38+
if (this._transformer === undefined) {
39+
this._transformer = new Transformer(Object.values(transformersFactories).map(create => create(this._config, this._log)))
40+
}
41+
return this._transformer
42+
}
43+
44+
/**
45+
* Initialize a connection with the server
46+
*
47+
* @param {Object} args The params
48+
* @param {string} args.userAgent The user agent
49+
* @param {any} args.authToken The auth token
50+
* @param {NotificationFilter} args.notificationFilter The notification filters.
51+
* @param {function(error)} args.onError On error callback
52+
* @param {function(onComplete)} args.onComplete On complete callback
53+
* @returns {LoginObserver} The Login observer
54+
*/
55+
initialize ({ userAgent, boltAgent, authToken, notificationFilter, onError, onComplete } = {}) {
56+
const state = {}
57+
const observer = new LoginObserver({
58+
onError: error => this._onLoginError(error, onError),
59+
onCompleted: metadata => {
60+
state.metadata = metadata
61+
return this._onLoginCompleted(metadata)
62+
}
63+
})
64+
65+
this.write(
66+
RequestMessage.hello5x3(userAgent, boltAgent, notificationFilter, this._serversideRouting),
67+
observer,
68+
false
69+
)
70+
71+
return this.logon({
72+
authToken,
73+
onComplete: metadata => onComplete({ ...metadata, ...state.metadata }),
74+
onError,
75+
flush: true
76+
})
77+
}
78+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
import v5x2 from './bolt-protocol-v5x2.transformer'
21+
22+
export default {
23+
...v5x2
24+
}

packages/bolt-connection/src/bolt/create.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import BoltProtocolV4x4 from './bolt-protocol-v4x4'
2929
import BoltProtocolV5x0 from './bolt-protocol-v5x0'
3030
import BoltProtocolV5x1 from './bolt-protocol-v5x1'
3131
import BoltProtocolV5x2 from './bolt-protocol-v5x2'
32+
import BoltProtocolV5x3 from './bolt-protocol-v5x3'
3233
// eslint-disable-next-line no-unused-vars
3334
import { Chunker, Dechunker } from '../channel'
3435
import ResponseHandler from './response-handler'
@@ -213,6 +214,14 @@ function createProtocol (
213214
onProtocolError,
214215
serversideRouting
215216
)
217+
case 5.3:
218+
return new BoltProtocolV5x3(server,
219+
chunker,
220+
packingConfig,
221+
createResponseHandler,
222+
log,
223+
onProtocolError,
224+
serversideRouting)
216225
default:
217226
throw newError('Unknown Bolt protocol version: ' + version)
218227
}

packages/bolt-connection/src/bolt/handshake.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ function parseNegotiatedResponse (buffer) {
7676
*/
7777
function newHandshakeBuffer () {
7878
return createHandshakeMessage([
79-
[version(5, 2), version(5, 0)],
79+
[version(5, 3), version(5, 0)],
8080
[version(4, 4), version(4, 2)],
8181
version(4, 1),
8282
version(3, 0)

packages/bolt-connection/src/bolt/request-message.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,51 @@ export default class RequestMessage {
191191
)
192192
}
193193

194+
/**
195+
* Create a new HELLO message.
196+
* @param {string} userAgent the user agent.
197+
* @param {string} boltAgent the bolt agent.
198+
* @param {NotificationFilter} notificationFilter the notification filter configured
199+
* @param {Object} routing server side routing, set to routing context to turn on server side routing (> 4.1)
200+
* @return {RequestMessage} new HELLO message.
201+
*/
202+
static hello5x3 (userAgent, boltAgent, notificationFilter = null, routing = null) {
203+
const metadata = { }
204+
205+
if (userAgent) {
206+
metadata.user_agent = userAgent
207+
}
208+
209+
if (boltAgent) {
210+
metadata.bolt_agent = {
211+
product: boltAgent.product,
212+
platform: boltAgent.platform,
213+
language: boltAgent.language,
214+
language_details: boltAgent.languageDetails
215+
}
216+
}
217+
218+
if (notificationFilter) {
219+
if (notificationFilter.minimumSeverityLevel) {
220+
metadata.notifications_minimum_severity = notificationFilter.minimumSeverityLevel
221+
}
222+
223+
if (notificationFilter.disabledCategories) {
224+
metadata.notifications_disabled_categories = notificationFilter.disabledCategories
225+
}
226+
}
227+
228+
if (routing) {
229+
metadata.routing = routing
230+
}
231+
232+
return new RequestMessage(
233+
HELLO,
234+
[metadata],
235+
() => `HELLO ${json.stringify(metadata)}`
236+
)
237+
}
238+
194239
/**
195240
* Create a new LOGON message.
196241
*

packages/bolt-connection/src/channel/browser/browser-channel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ export default class WebSocketChannel {
166166
*/
167167
close () {
168168
return new Promise((resolve, reject) => {
169+
this._clearConnectionTimeout()
169170
if (this._ws && this._ws.readyState !== WS_CLOSED) {
170171
this._open = false
171172
this.stopReceiveTimeout()
172-
this._clearConnectionTimeout()
173173
this._ws.onclose = () => resolve()
174174
this._ws.close()
175175
} else {

packages/bolt-connection/src/connection-provider/authentication-provider.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ import { object } from '../lang'
2424
* Class which provides Authorization for {@link Connection}
2525
*/
2626
export default class AuthenticationProvider {
27-
constructor ({ authTokenManager, userAgent }) {
27+
constructor ({ authTokenManager, userAgent, boltAgent }) {
2828
this._authTokenManager = authTokenManager || expirationBasedAuthTokenManager({
2929
tokenProvider: () => {}
3030
})
3131
this._userAgent = userAgent
32+
this._boltAgent = boltAgent
3233
}
3334

3435
async authenticate ({ connection, auth, skipReAuth, waitReAuth, forceReAuth }) {
@@ -38,15 +39,15 @@ export default class AuthenticationProvider {
3839
forceReAuth === true
3940
)
4041
if (connection.authToken == null || shouldReAuth) {
41-
return await connection.connect(this._userAgent, auth, waitReAuth || false)
42+
return await connection.connect(this._userAgent, this._boltAgent, auth, waitReAuth || false)
4243
}
4344
return connection
4445
}
4546

4647
const authToken = await this._authTokenManager.getToken()
4748

4849
if (!object.equals(authToken, connection.authToken)) {
49-
return await connection.connect(this._userAgent, authToken)
50+
return await connection.connect(this._userAgent, this._boltAgent, authToken, false)
5051
}
5152

5253
return connection

packages/bolt-connection/src/connection-provider/connection-provider-direct.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ const {
3737
const { SERVICE_UNAVAILABLE } = error
3838

3939
export default class DirectConnectionProvider extends PooledConnectionProvider {
40-
constructor ({ id, config, log, address, userAgent, authTokenManager, newPool }) {
41-
super({ id, config, log, userAgent, authTokenManager, newPool })
40+
constructor ({ id, config, log, address, userAgent, boltAgent, authTokenManager, newPool }) {
41+
super({ id, config, log, userAgent, boltAgent, authTokenManager, newPool })
4242

4343
this._address = address
4444
}

packages/bolt-connection/src/connection-provider/connection-provider-pooled.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const AUTHENTICATION_ERRORS = [
3333

3434
export default class PooledConnectionProvider extends ConnectionProvider {
3535
constructor (
36-
{ id, config, log, userAgent, authTokenManager, newPool = (...args) => new Pool(...args) },
36+
{ id, config, log, userAgent, boltAgent, authTokenManager, newPool = (...args) => new Pool(...args) },
3737
createChannelConnectionHook = null
3838
) {
3939
super()
@@ -42,7 +42,9 @@ export default class PooledConnectionProvider extends ConnectionProvider {
4242
this._config = config
4343
this._log = log
4444
this._authTokenManager = authTokenManager
45-
this._authenticationProvider = new AuthenticationProvider({ authTokenManager, userAgent })
45+
this._authenticationProvider = new AuthenticationProvider({ authTokenManager, userAgent, boltAgent })
46+
this._userAgent = userAgent
47+
this._boltAgent = boltAgent
4648
this._createChannelConnection =
4749
createChannelConnectionHook ||
4850
(address => {
@@ -67,7 +69,6 @@ export default class PooledConnectionProvider extends ConnectionProvider {
6769
config: PoolConfig.fromDriverConfig(config),
6870
log: this._log
6971
})
70-
this._userAgent = userAgent
7172
this._openConnections = {}
7273
}
7374

@@ -86,6 +87,7 @@ export default class PooledConnectionProvider extends ConnectionProvider {
8687
return release(address, connection)
8788
}
8889
this._openConnections[connection.id] = connection
90+
8991
return this._authenticationProvider.authenticate({ connection, auth })
9092
.catch(error => {
9193
// let's destroy this connection

packages/bolt-connection/src/connection-provider/connection-provider-routing.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,12 @@ export default class RoutingConnectionProvider extends PooledConnectionProvider
6767
config,
6868
log,
6969
userAgent,
70+
boltAgent,
7071
authTokenManager,
7172
routingTablePurgeDelay,
7273
newPool
7374
}) {
74-
super({ id, config, log, userAgent, authTokenManager, newPool }, address => {
75+
super({ id, config, log, userAgent, boltAgent, authTokenManager, newPool }, address => {
7576
return createChannelConnection(
7677
address,
7778
this._config,

0 commit comments

Comments
 (0)