From 7e61d2abae5115dea80ab5d8333153f88a1aeda0 Mon Sep 17 00:00:00 2001 From: Ludovic Muller Date: Mon, 9 Dec 2024 10:16:37 +0100 Subject: [PATCH] sparql-proxy: check if the URL is valid before replacing the default endpoint --- .changeset/stale-hairs-own.md | 5 +++ packages/sparql-proxy/index.js | 12 ++++--- packages/sparql-proxy/lib/utils.js | 16 +++++++++ packages/sparql-proxy/test/utils.test.js | 44 +++++++++++++++++++++++- 4 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 .changeset/stale-hairs-own.md diff --git a/.changeset/stale-hairs-own.md b/.changeset/stale-hairs-own.md new file mode 100644 index 00000000..de853ffa --- /dev/null +++ b/.changeset/stale-hairs-own.md @@ -0,0 +1,5 @@ +--- +"@zazuko/trifid-plugin-sparql-proxy": patch +--- + +Check if a URL is valid, during the replacement of the default endpoint diff --git a/packages/sparql-proxy/index.js b/packages/sparql-proxy/index.js index 6b79ef1a..436b6342 100644 --- a/packages/sparql-proxy/index.js +++ b/packages/sparql-proxy/index.js @@ -8,7 +8,7 @@ import { Worker } from 'node:worker_threads' import { sparqlGetRewriteConfiguration } from 'trifid-core' import rdf from '@zazuko/env-node' import ReplaceStream from './lib/ReplaceStream.js' -import { authBasicHeader, objectLength } from './lib/utils.js' +import { authBasicHeader, objectLength, isValidUrl } from './lib/utils.js' const defaultConfiguration = { endpointUrl: '', @@ -45,10 +45,12 @@ const factory = async (trifid) => { throw Error('Missing default endpoint in the endpoints configuration') } - // Override default values with the default endpoint values - options.endpointUrl = options.endpoints.default.url || '' - options.username = options.endpoints.default.username || '' - options.password = options.endpoints.default.password || '' + // Override default values with the default endpoint values (in case it's a valid URL ; else it might be the default /query) + if (isValidUrl(options.endpoints.default)) { + options.endpointUrl = options.endpoints.default.url || '' + options.username = options.endpoints.default.username || '' + options.password = options.endpoints.default.password || '' + } // Support for multiple endpoints dynamicEndpoints = true diff --git a/packages/sparql-proxy/lib/utils.js b/packages/sparql-proxy/lib/utils.js index 215d0ead..abf45806 100644 --- a/packages/sparql-proxy/lib/utils.js +++ b/packages/sparql-proxy/lib/utils.js @@ -35,3 +35,19 @@ export const objectLength = (obj) => { } return Object.keys(obj).length } + +/** + * Check if a string is a valid URL. + * + * @param {string} url The URL to check. + * @returns {boolean} True if the URL is valid, false otherwise. + */ +export const isValidUrl = (url) => { + try { + // eslint-disable-next-line no-new + new URL(url) + return true + } catch { + return false + } +} diff --git a/packages/sparql-proxy/test/utils.test.js b/packages/sparql-proxy/test/utils.test.js index aa673091..395ebd7e 100644 --- a/packages/sparql-proxy/test/utils.test.js +++ b/packages/sparql-proxy/test/utils.test.js @@ -1,7 +1,7 @@ import { describe, it } from 'node:test' import { equal, deepEqual } from 'node:assert' -import { authBasicHeader, assertObject, objectLength } from '../lib/utils.js' +import { authBasicHeader, assertObject, objectLength, isValidUrl } from '../lib/utils.js' describe('utils', () => { describe('authBasicHeader', () => { @@ -93,4 +93,46 @@ describe('utils', () => { equal(objectLength({ one: '1', two: '2', three: '2' }), 3) }) }) + + describe('isValidUrl', () => { + it('should return true for a valid URL', () => { + equal(isValidUrl('http://example.com/'), true) + }) + + it('should return false for an invalid URL', () => { + equal(isValidUrl('not a URL'), false) + }) + + it('should return false for an empty string', () => { + equal(isValidUrl(''), false) + }) + + it('should return false for undefined', () => { + equal(isValidUrl(undefined), false) + }) + + it('should return false for null', () => { + equal(isValidUrl(null), false) + }) + + it('should return false for a number', () => { + equal(isValidUrl(42), false) + }) + + it('should return false for an object', () => { + equal(isValidUrl({}), false) + }) + + it('should return false for an array', () => { + equal(isValidUrl([]), false) + }) + + it('should return false for a boolean', () => { + equal(isValidUrl(true), false) + }) + + it('should return false for a function', () => { + equal(isValidUrl(() => { }), false) + }) + }) })