This is an automated email from the ASF dual-hosted git repository. colegreer pushed a commit to branch js-interceptors in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 1093638a8dcf39120e36fc1a1ec6909e874adcde Author: Cole Greer <[email protected]> AuthorDate: Sat Mar 21 20:08:11 2026 -0700 Remove mimeType configuration in favour of reader and writer options, make writer optional. --- CHANGELOG.asciidoc | 1 + gremlin-javascript/examples/node/connections.js | 1 - .../gremlin-javascript/lib/driver/client.ts | 1 - .../gremlin-javascript/lib/driver/connection.ts | 48 +++++++++------------- .../lib/driver/driver-remote-connection.ts | 1 - .../io/binary/internals/GraphBinaryReader.js | 4 ++ .../io/binary/internals/GraphBinaryWriter.js | 8 +++- .../javascript/gremlin-javascript/test/helper.js | 40 ++---------------- .../gremlin-javascript/test/unit/auth-test.js | 2 - .../gremlin-javascript/test/unit/client-test.js | 10 ----- 10 files changed, 33 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 76b6cfd1a0..20b91b08eb 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -37,6 +37,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima * Added `RequestInterceptor` to `gremlin-go` with `auth` reference implementations to replace `authInfo`. * Refactored GraphBinary serializers to use `io.Writer` and `io.Reader` instead of `*bytes.Buffer` for streaming capacities. * Refactored `httpProtocol` and `httpTransport` in `gremlin-go` into single `connection.go` that handles HTTP request and response. +* Removed `mimeType` connection option in `gremlin-javascript` in favor of direct use of `reader` and `writer` options. * Bumped ANTLR to 4.13.2 * Bumped SLF4j to 2.0.16. * Bumped GMavenPlus to 4.1.1. diff --git a/gremlin-javascript/examples/node/connections.js b/gremlin-javascript/examples/node/connections.js index a61431478f..e8d8841214 100644 --- a/gremlin-javascript/examples/node/connections.js +++ b/gremlin-javascript/examples/node/connections.js @@ -46,7 +46,6 @@ async function withRemote() { async function withConfigs() { // Connecting and customizing configurations const dc = new DriverRemoteConnection(serverUrl, { - mimeType: 'application/vnd.graphbinary-v4.0', rejectUnauthorized: false, traversalSource: 'g', }); diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.ts b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.ts index a74c0081c9..e44dc345b8 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.ts +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.ts @@ -47,7 +47,6 @@ export default class Client { * @param {Object} [options] The connection options. * @param {Array} [options.ca] Trusted certificates. * @param {String|Array|Buffer} [options.cert] The certificate key. - * @param {String} [options.mimeType] The mime type to use. * @param {String|Buffer} [options.pfx] The private key, certificate, and CA certs. * @param {GraphBinaryReader} [options.reader] The reader to use. * @param {Boolean} [options.rejectUnauthorized] Determines whether to verify or not the server certificate. diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.ts b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.ts index 1e2b1d1560..1afb320a3f 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.ts +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.ts @@ -42,16 +42,11 @@ const responseStatusCode = { authenticationChallenge: 407, }; -const defaultMimeType = 'application/vnd.graphbinary-v4.0'; -const graphBinaryMimeType = 'application/vnd.graphbinary-v4.0'; - -type MimeType = typeof defaultMimeType | typeof graphBinaryMimeType; - export type HttpRequest = { url: string; method: string; headers: Record<string, string>; - body: Uint8Array; + body: any; }; export type RequestInterceptor = (request: HttpRequest) => HttpRequest | Promise<HttpRequest>; @@ -59,12 +54,11 @@ export type RequestInterceptor = (request: HttpRequest) => HttpRequest | Promise export type ConnectionOptions = { ca?: string[]; cert?: string | string[] | Buffer; - mimeType?: MimeType; //TODO:: Revisit if MimeType should remain configurable pfx?: string | Buffer; reader?: any; rejectUnauthorized?: boolean; traversalSource?: string; - writer?: any; + writer?: any | null; headers?: Record<string, string | string[]>; enableUserAgentOnConnect?: boolean; agent?: Agent; @@ -75,10 +69,8 @@ export type ConnectionOptions = { * Represents a single connection to a Gremlin Server. */ export default class Connection extends EventEmitter { - readonly mimeType: MimeType; - private readonly _reader: any; - private readonly _writer: any; + private readonly _writer: any | null; isOpen = true; traversalSource: string; @@ -92,12 +84,11 @@ export default class Connection extends EventEmitter { * @param {Object} [options] The connection options. * @param {Array} [options.ca] Trusted certificates. * @param {String|Array|Buffer} [options.cert] The certificate key. - * @param {String} [options.mimeType] The mime type to use. * @param {String|Buffer} [options.pfx] The private key, certificate, and CA certs. * @param {GraphBinaryReader} [options.reader] The reader to use. * @param {Boolean} [options.rejectUnauthorized] Determines whether to verify or not the server certificate. * @param {String} [options.traversalSource] The traversal source. Defaults to: 'g'. - * @param {GraphBinaryWriter} [options.writer] The writer to use. + * @param {GraphBinaryWriter} [options.writer] The writer to use. Set to null to skip serialization. * @param {Object} [options.headers] An associative array containing the additional header key/values for the initial request. * @param {Boolean} [options.enableUserAgentOnConnect] Determines if a user agent will be sent during connection handshake. Defaults to: true * @param {http.Agent} [options.agent] The http.Agent implementation to use. @@ -110,13 +101,8 @@ export default class Connection extends EventEmitter { ) { super(); - /** - * Gets the MIME type. - * @type {String} - */ - this.mimeType = options.mimeType || defaultMimeType; this._reader = options.reader || graphBinaryReader; - this._writer = options.writer || graphBinaryWriter; + this._writer = 'writer' in options ? options.writer : graphBinaryWriter; this.traversalSource = options.traversalSource || 'g'; this._enableUserAgentOnConnect = options.enableUserAgentOnConnect !== false; @@ -143,9 +129,10 @@ export default class Connection extends EventEmitter { /** @override */ submit(request: RequestMessage) { - const request_buf: Buffer = this._writer.writeRequest(request); + // The user may not want the body to be serialized if they are using an interceptor. + const body = this._writer ? this._writer.writeRequest(request) : request; - return this.#makeHttpRequest(request_buf) + return this.#makeHttpRequest(body) .then((response) => { return this.#handleResponse(response); }); @@ -161,19 +148,22 @@ export default class Connection extends EventEmitter { return this._reader; } - if (contentType === graphBinaryMimeType) { - return graphBinaryReader; + if (contentType === this._reader.mimeType) { + return this._reader; } return null; } - async #makeHttpRequest(request_buf: Buffer): Promise<Response> { + async #makeHttpRequest(body: any): Promise<Response> { const headers: Record<string, string> = { - 'Content-Type': this.mimeType, - 'Accept': this.mimeType + 'Accept': this._reader.mimeType }; + if (this._writer) { + headers['Content-Type'] = this._writer.mimeType; + } + if (this._enableUserAgentOnConnect) { const userAgent = await utils.getUserAgent(); if (userAgent !== undefined) { @@ -190,7 +180,7 @@ export default class Connection extends EventEmitter { url: this.url, method: 'POST', headers, - body: new Uint8Array(request_buf), + body, }; for (const interceptor of this._interceptors) { @@ -200,7 +190,7 @@ export default class Connection extends EventEmitter { return fetch(httpRequest.url, { method: httpRequest.method, headers: httpRequest.headers, - body: httpRequest.body as BodyInit, + body: httpRequest.body, }); } @@ -247,7 +237,7 @@ export default class Connection extends EventEmitter { } if (!reader) { - throw new Error(`Unsupported Content-Type: ${contentType}`); + throw new Error(`Response Content-Type '${contentType}' does not match the configured reader (expected '${this._reader.mimeType}')`); } const deserialized = reader.readResponse(buffer); diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.ts b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.ts index ad9dd8b4cf..c59c010834 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.ts +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.ts @@ -41,7 +41,6 @@ export default class DriverRemoteConnection extends RemoteConnection { * @param {ConnectionOptions} [options] The connection options. * @param {Array} [options.ca] Trusted certificates. * @param {String|Array|Buffer} [options.cert] The certificate key. - * @param {String} [options.mimeType] The mime type to use. * @param {String|Buffer} [options.pfx] The private key, certificate, and CA certs. * @param {GraphBinaryReader} [options.reader] The reader to use. * @param {Boolean} [options.rejectUnauthorized] Determines whether to verify or not the server certificate. diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryReader.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryReader.js index 83c6352ca3..d75bf13635 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryReader.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryReader.js @@ -31,6 +31,10 @@ export default class GraphBinaryReader { this.ioc = ioc; } + get mimeType() { + return 'application/vnd.graphbinary-v4.0'; + } + readResponse(buffer) { if (buffer === undefined || buffer === null) { throw new Error('Buffer is missing.'); diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryWriter.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryWriter.js index 87ba1f5e21..f0ca979a72 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryWriter.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryWriter.js @@ -31,6 +31,10 @@ export default class GraphBinaryWriter { this.ioc = ioc; } + get mimeType() { + return 'application/vnd.graphbinary-v4.0'; + } + writeRequest(requestMessage) { const fields = new Map(); @@ -73,7 +77,7 @@ export default class GraphBinaryWriter { this.ioc.mapSerializer.serialize(fields, false), this.ioc.stringSerializer.serialize(gremlin, false), ]; - return Buffer.concat(bufs); + return new Uint8Array(Buffer.concat(bufs)); } // Legacy path: plain object with { gremlin, fields } @@ -82,6 +86,6 @@ export default class GraphBinaryWriter { this.ioc.mapSerializer.serialize(requestMessage.fields || new Map(), false), this.ioc.stringSerializer.serialize(requestMessage.gremlin, false), ]; - return Buffer.concat(bufs); + return new Uint8Array(Buffer.concat(bufs)); } } diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js index a030de4eff..42926b323d 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js @@ -24,42 +24,32 @@ import DriverRemoteConnection from '../lib/driver/driver-remote-connection.js'; import Client from '../lib/driver/client.js'; -import jsYaml from 'js-yaml'; -import fs from 'fs'; - let serverUrl; let serverAuthUrl; -let socketServerUrl; -let sockerServerConfigPath; if (process.env.DOCKER_ENVIRONMENT === 'true') { serverUrl = 'http://gremlin-server-test-js:45940/gremlin'; serverAuthUrl = 'https://gremlin-server-test-js:45941/gremlin'; - socketServerUrl = 'http://gremlin-socket-server-js:'; - sockerServerConfigPath = '/js_app/gremlin-socket-server/conf/test-ws-gremlin.yaml'; } else { serverUrl = 'http://localhost:45940/gremlin'; serverAuthUrl = 'https://localhost:45941/gremlin'; - socketServerUrl = 'http://localhost:'; - sockerServerConfigPath = '../../../../../gremlin-tools/gremlin-socket-server/conf/test-ws-gremlin.yaml'; } /** @returns {DriverRemoteConnection} */ export function getConnection(traversalSource) { - return new DriverRemoteConnection(serverUrl, { traversalSource, mimeType: process.env.CLIENT_MIMETYPE }); + return new DriverRemoteConnection(serverUrl, { traversalSource }); } export function getDriverRemoteConnection(url, options) { - return new DriverRemoteConnection(url, { ...options, mimeType: process.env.CLIENT_MIMETYPE }); + return new DriverRemoteConnection(url, { ...options }); } export function getClient(traversalSource) { - return new Client(serverUrl, { traversalSource, mimeType: process.env.CLIENT_MIMETYPE }); + return new Client(serverUrl, { traversalSource }); } export function getAuthenticatedClient(traversalSource, interceptors) { return new Client(serverAuthUrl, { traversalSource, - mimeType: process.env.CLIENT_MIMETYPE, rejectUnauthorized: false, interceptors, }); @@ -68,31 +58,7 @@ export function getAuthenticatedClient(traversalSource, interceptors) { export function getAuthenticatedConnection(traversalSource, interceptors) { return new DriverRemoteConnection(serverAuthUrl, { traversalSource, - mimeType: process.env.CLIENT_MIMETYPE, rejectUnauthorized: false, interceptors, }); } - -function getMimeTypeFromSocketServerSettings(socketServerSettings) { - return 'application/vnd.graphbinary-v4.0'; -} - -export function getGremlinSocketServerClient(traversalSource) { - const settings = getGremlinSocketServerSettings(); - const url = socketServerUrl + settings.PORT + '/gremlin'; - let mimeType = getMimeTypeFromSocketServerSettings(settings) - return new Client(url, { traversalSource, mimeType }); -} - -export const getGremlinSocketServerClientNoUserAgent = function getGremlinSocketServerClient(traversalSource) { - const settings = getGremlinSocketServerSettings(); - const url = socketServerUrl + settings.PORT + '/gremlin'; - let mimeType = getMimeTypeFromSocketServerSettings(settings) - return new Client(url, { traversalSource, mimeType, enableUserAgentOnConnect:false }); -}; - -export function getGremlinSocketServerSettings() { - const settings = jsYaml.load(fs.readFileSync(sockerServerConfigPath, 'utf8')); - return settings; -} diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/auth-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/auth-test.js index 2d112ce4de..cab2a5d24f 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/auth-test.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/auth-test.js @@ -28,7 +28,6 @@ describe('auth', function () { url: 'https://localhost:8182/gremlin', method: 'POST', headers: { - 'content-type': 'application/vnd.graphbinary-v4.0', 'accept': 'application/vnd.graphbinary-v4.0', }, body: new Uint8Array(0), @@ -70,7 +69,6 @@ describe('auth', function () { url: 'https://localhost:8182/gremlin', method: 'POST', headers: { - 'content-type': 'application/vnd.graphbinary-v4.0', 'accept': 'application/vnd.graphbinary-v4.0', }, body: new Uint8Array(Buffer.from('{"gremlin":"g.V()"}')), diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/client-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/client-test.js index 4f28f0f5ef..38342a3a9f 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/client-test.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/client-test.js @@ -51,14 +51,4 @@ describe('Client', function () { customClient._connection = connectionMock; customClient.submit(query) }); - - it('should use default mimeType', function () { - const customClient = new Client('http://localhost:9321', {traversalSource: 'g', connectOnStartup: false}); - assert.strictEqual(customClient._connection.mimeType, 'application/vnd.graphbinary-v4.0') - }); - - it('should use given mimeType', function () { - const customClient = new Client('http://localhost:9321', {traversalSource: 'g', connectOnStartup: false, mimeType: 'application/vnd.gremlin-v2.0+json'}); - assert.strictEqual(customClient._connection.mimeType, 'application/vnd.gremlin-v2.0+json') - }); });
