diff --git a/packages/dd-trace/src/aiguard/sdk.js b/packages/dd-trace/src/aiguard/sdk.js index 2ca68eb18a..b9c87c2b19 100644 --- a/packages/dd-trace/src/aiguard/sdk.js +++ b/packages/dd-trace/src/aiguard/sdk.js @@ -63,6 +63,18 @@ class AIGuardClientError extends Error { } } +/** + * Resolves the AI Guard host for a given Datadog site. Sites with a single subdomain level + * (e.g. `datadoghq.com`, `ddog-gov.com`) are served from the `app.` subdomain, while regional + * sites (e.g. `us3.datadoghq.com`, `ap1.datadoghq.com`) are used as-is. + * + * @param {string} site - Datadog site (e.g. `datadoghq.com`, `us3.datadoghq.com`) + * @returns {string} The host to use for the AI Guard endpoint + */ +function aiGuardHost (site) { + return site.split('.').length === 2 ? `app.${site}` : site +} + class AIGuard extends NoopAIGuard { #initialized #tracer @@ -94,7 +106,7 @@ class AIGuard extends NoopAIGuard { 'DD-AI-GUARD-SOURCE': 'SDK', 'DD-AI-GUARD-LANGUAGE': 'nodejs', } - const endpoint = config.experimental.aiguard.endpoint || `https://app.${config.site}/api/v2/ai-guard` + const endpoint = config.experimental.aiguard.endpoint || `https://${aiGuardHost(config.site)}/api/v2/ai-guard` this.#evaluateUrl = `${endpoint}/evaluate` this.#timeout = config.experimental.aiguard.timeout this.#maxMessagesLength = config.experimental.aiguard.maxMessagesLength diff --git a/packages/dd-trace/test/aiguard/index.spec.js b/packages/dd-trace/test/aiguard/index.spec.js index 3df963b689..d2dfaa5061 100644 --- a/packages/dd-trace/test/aiguard/index.spec.js +++ b/packages/dd-trace/test/aiguard/index.spec.js @@ -523,11 +523,14 @@ describe('AIGuard SDK', () => { const sites = [ { site: 'datad0g.com', endpoint: 'https://app.datad0g.com/api/v2/ai-guard' }, { site: 'datadoghq.com', endpoint: 'https://app.datadoghq.com/api/v2/ai-guard' }, + { site: 'ddog-gov.com', endpoint: 'https://app.ddog-gov.com/api/v2/ai-guard' }, + { site: 'us3.datadoghq.com', endpoint: 'https://us3.datadoghq.com/api/v2/ai-guard' }, + { site: 'ap1.datadoghq.com', endpoint: 'https://ap1.datadoghq.com/api/v2/ai-guard' }, ] for (const { site, endpoint } of sites) { it(`test endpoint discovery: ${site}`, async () => { - const newConfig = { site, ...config } - delete newConfig.experimental.aiguard.endpoint + const { endpoint: _discardedEndpoint, ...aiguard } = config.experimental.aiguard + const newConfig = { ...config, site, experimental: { ...config.experimental, aiguard } } const client = new AIGuard(tracer, newConfig) mockFetch({ body: { data: { attributes: { action: 'ALLOW', reason: 'OK', is_blocking_enabled: false } } },