diff --git a/lib/api/legacy-routes.cjs b/lib/api/legacy-routes.cjs index f654a8fa..912a20e0 100644 --- a/lib/api/legacy-routes.cjs +++ b/lib/api/legacy-routes.cjs @@ -32,6 +32,7 @@ const { ADMIN_TOKEN = '', API_IDFIX_URL = 'https://plateforme.adresse.data.gouv.fr/api-idfix', API_IDFIX_TOKEN = '', + BAN_API_URL = '', } = process.env const prepareMethode = { @@ -56,10 +57,25 @@ const getLegacyTypeFromId = id => { } } -let sendToTracker = () => console.warn('Legacy-routes: sendToTracker not yet implemented') -import('../util/analytics-tracker.js').then(s => { - sendToTracker = s.sendToTracker -}) +const sendToTracker = async ({url: paramUrl, download: paramDownload, ...params} = {}, ...args) => { + const module = await import('../util/analytics-tracker.js') + if (!module.sendToTracker) { + console.warn('Legacy-routes: sendToTracker not found') + return + } + + const url = paramUrl && `${BAN_API_URL}${paramUrl}` + const download = paramDownload && `${BAN_API_URL}${paramDownload}` + + return module.sendToTracker( + { + ...(url ? {url} : {}), + ...(download ? {download} : {}), + ...params + }, + ...args) +} + const trackEventDefault = { category: 'API Legacy', value: 1, @@ -133,12 +149,13 @@ const analyticsMiddleware = { next?.() }, downloadCommuneData(req, res, next) { - const {url} = req + const {url, commune = {}} = req const {codeCommune, downloadFormat, downloadType} = req.params + const nomCommune = commune?.nomCommune const trackEvent = { - category: 'Download Commune DATA API (From Legacy)', - action: `Download ${downloadType} (Format ${downloadFormat})`, - name: codeCommune, + category: 'Download', + action: `Download Commune ${downloadType} (Format ${downloadFormat})`, + name: `${codeCommune}${nomCommune ? ` - ${nomCommune}` : ''}`, value: 1, } sendToTracker({url, download: url, trackEvent}) @@ -186,6 +203,7 @@ app.param( }) ) +// API Download Commune Data app.get( '/ban/communes/:codeCommune/download/:downloadFormat/:downloadType', analyticsMiddleware.downloadCommuneData, @@ -213,6 +231,7 @@ app.get( }) ) +// API-Legacy app.post( '/ban/communes/:codeCommune/compose', ensureIsAdmin, @@ -367,6 +386,7 @@ app.get( }) ) +// BAN Stats app.get( '/ban/stats', w(async (req, res) => { @@ -375,23 +395,26 @@ app.get( }) ) -app.post('/ban/stats', w(async (req, res) => { - const {codesCommune} = req.body - if (!codesCommune || codesCommune.length === 0) { - return res - .status(404) - .send({code: 404, message: 'Paramètre codesCommune manquant ou invalide'}) - } +app.post( + '/ban/stats', + w(async (req, res) => { + const {codesCommune} = req.body + if (!codesCommune || codesCommune.length === 0) { + return res + .status(404) + .send({code: 404, message: 'Paramètre codesCommune manquant ou invalide'}) + } - try { - const stats = await computeFilteredStats(codesCommune) - res.send(stats) - } catch (error) { - console.error(error) - res.status(500).send({code: 500, message: 'Une erreur est survenu lors du calcul des statistiques'}) - } -})) + try { + const stats = await computeFilteredStats(codesCommune) + res.send(stats) + } catch (error) { + console.error(error) + res.status(500).send({code: 500, message: 'Une erreur est survenu lors du calcul des statistiques'}) + } + })) +// BAN Carto Tiles app.get( '/tiles/ban/:z/:x/:y.pbf', w(async (req, res) => { diff --git a/lib/util/analytics-tracker.js b/lib/util/analytics-tracker.js index b625954d..31ce8679 100644 --- a/lib/util/analytics-tracker.js +++ b/lib/util/analytics-tracker.js @@ -1,51 +1,66 @@ /* eslint-disable camelcase */ -import os from 'node:os' -import MatomoTracker from 'matomo-tracker' - -const {MATOMO_URL, MATOMO_SITE_ID, NODE_ENV} = process.env - -let MATOMO_ERROR = false +// CF. Tracking HTTP API documentation : +// https://developer.matomo.org/api-reference/tracking-api -let matomo +import os from 'node:os' +import fetch from '../util/fetch.cjs' -const isDevMode = () => NODE_ENV !== 'production' +const { + MATOMO_URL, + MATOMO_SITE_ID, + MATOMO_TOKEN_AUTH, + NODE_ENV +} = process.env +const isDevMode = NODE_ENV !== 'production' +const matomoUrl = `${MATOMO_URL}/matomo.php` const logMatomoError = err => { - MATOMO_ERROR = true - console.warn('[WARNING] tracking request:', err) + console.log('error tracking request:', err) } -const matomoUrl = `${MATOMO_URL}/matomo.php` +const encodeParams = params => Object.fromEntries( + Object + .entries(params || {}) + .map(([key, value]) => [key, typeof value === 'string' ? encodeURIComponent(value) : value]), +) -try { - const matomo = new MatomoTracker(MATOMO_SITE_ID, matomoUrl) - matomo.on('error', logMatomoError) -} catch (error) { - logMatomoError(error) -} +export const getTrackEvent = ({category, action, name, value = 1}) => ({ + e_c: encodeURIComponent(`${isDevMode ? 'DEVMODE - ' : ''}${category}`), // Category name + e_a: encodeURIComponent(action), // Action name + e_n: encodeURIComponent(name), // Name + e_v: value, // Value +}) -export const getTrackEvent = ({category, action, name, value}) => { - const DEVMODE = isDevMode() +export const sendToTracker = async (params = {}) => { + const {url, ua, download, trackEvent, ...otherParams} = params + const safeOtherParams = encodeParams(otherParams) + const requiredParams = { + idsite: MATOMO_SITE_ID, + rec: 1, + ua: ua || encodeURIComponent(`${os.hostname()} / Node.JS ${process.version} / ${os.version()}`), + ...(MATOMO_TOKEN_AUTH ? {token_auth: MATOMO_TOKEN_AUTH} : {}), + } + const urlSearchParams = new URLSearchParams({ + ...requiredParams, + ...safeOtherParams, + ...(url ? {url: encodeURIComponent(url)} : {}), + ...(download ? {download: encodeURIComponent(download)} : {}), + ...(trackEvent ? getTrackEvent(trackEvent) : {}), + }) - // CF. Tracking HTTP API documentation : - // https://developer.matomo.org/api-reference/tracking-api + try { + const sentToMatomoWithHTTP = await fetch(matomoUrl, { + method: 'POST', + body: urlSearchParams, + }) - return { - e_c: `${DEVMODE ? 'DEVMODE - ' : ''}${category}`, // Category name - e_a: action, // Action name - e_n: name, // Name - ...(value ? {e_v: value} : {}), // Value + if (sentToMatomoWithHTTP.status !== 200) { + throw new Error(`Matomo HTTP API returned ${sentToMatomoWithHTTP.status}`) + } + } catch (error) { + logMatomoError(error) } } -export const sendToTracker = ({url, download, trackEvent}) => - !MATOMO_ERROR - && matomo?.track({ - ua: `${os.hostname()} / Node.JS ${process.version} / ${os.version()}`, - ...(url ? {url} : {}), - ...(download ? {download} : {}), - ...(trackEvent ? getTrackEvent(trackEvent) : {}) - }) - export default sendToTracker