From 90af8fab02731da136e1db85507a4aba98360165 Mon Sep 17 00:00:00 2001 From: Jake Kasper Date: Tue, 2 Sep 2025 08:58:46 -0500 Subject: [PATCH] icons still --- backend/src/app.js | 3 +++ backend/src/routes/weatherPublic.js | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 backend/src/routes/weatherPublic.js diff --git a/backend/src/app.js b/backend/src/app.js index d3be2af..5b62819 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -16,6 +16,7 @@ const applicationRoutes = require('./routes/applications'); const spreaderSettingsRoutes = require('./routes/spreaderSettings'); const productSpreaderSettingsRoutes = require('./routes/productSpreaderSettings'); const weatherRoutes = require('./routes/weather'); +const weatherPublicRoutes = require('./routes/weatherPublic'); const adminRoutes = require('./routes/admin'); const { errorHandler } = require('./middleware/errorHandler'); @@ -90,6 +91,8 @@ app.get('/health', (req, res) => { }); // Routes +// Public icon proxy must be mounted before protected weather routes +app.use('/api/weather/icon', weatherPublicRoutes); app.use('/api/auth', authLimiter, authRoutes); app.use('/api/users', authenticateToken, userRoutes); app.use('/api/properties', authenticateToken, propertyRoutes); diff --git a/backend/src/routes/weatherPublic.js b/backend/src/routes/weatherPublic.js new file mode 100644 index 0000000..b3d9733 --- /dev/null +++ b/backend/src/routes/weatherPublic.js @@ -0,0 +1,26 @@ +const express = require('express'); +const axios = require('axios'); + +const router = express.Router(); + +// Public icon proxy so tags don't need auth headers +// GET /api/weather/icon/:code?size=2x +router.get('/:code', async (req, res) => { + try { + const { code } = req.params; + const size = req.query.size === '2x' ? '@2x' : ''; + if (!code || !/^[0-9]{2}[dn]$/.test(code)) { + return res.status(400).send('invalid icon code'); + } + const url = `https://openweathermap.org/img/wn/${code}${size}.png`; + const resp = await axios.get(url, { responseType: 'arraybuffer', timeout: 5000 }); + res.set('Content-Type', 'image/png'); + res.set('Cache-Control', 'public, max-age=21600'); // 6h + return res.status(200).send(Buffer.from(resp.data)); + } catch (e) { + return res.status(502).send('icon fetch failed'); + } +}); + +module.exports = router; +