/** * Общие роуты для JSON данных (servers, filters, billing и т.д.) */ const { s3, BUCKET_NAME, writeS3JsonObject } = require('../services/s3Service'); const { sendError, sendOk, checkIfNoneMatch } = require('../middleware/errorHandler'); const { GetObjectCommand, HeadObjectCommand } = require('@aws-sdk/client-s3'); const { streamToString } = require('../services/s3Service'); /** * Создать GET эндпоинт для JSON данных */ function createJsonDataGET(s3Key) { return async (req, res) => { try { const head = await s3.send(new HeadObjectCommand({ Bucket: BUCKET_NAME, Key: s3Key })).catch(() => null); const etag = head?.ETag || null; if (etag) res.set('ETag', String(etag)); if (head?.LastModified) res.set('Last-Modified', new Date(head.LastModified).toUTCString()); if (typeof head?.ContentLength === 'number') res.set('Content-Length-Source', String(head.ContentLength)); if (checkIfNoneMatch(req, res, etag)) return; const data = await s3.send(new GetObjectCommand({ Bucket: BUCKET_NAME, Key: s3Key })); const fileContent = await streamToString(data.Body); let items = []; try { items = JSON.parse(fileContent); if (!Array.isArray(items)) { items = []; } } catch (parseError) { console.error(`Error parsing ${s3Key}:`, parseError); items = []; } res.json(items); } catch (error) { if (error?.code === 'NoSuchKey' || error?.$metadata?.httpStatusCode === 404) { res.json([]); } else { console.error(error); return sendError(res, 500, 'Error reading from S3', 'E_S3'); } } }; } /** * Создать POST эндпоинт для JSON данных */ function createJsonDataPOST(s3Key, validateItem = null) { return async (req, res) => { const { domains: items } = req.body; // Используем 'domains' для обратной совместимости if (!Array.isArray(items)) { return sendError(res, 400, 'Data must be an array', 'E_BAD_REQUEST'); } // Валидация элементов, если предоставлена if (validateItem) { for (let i = 0; i < items.length; i++) { const error = validateItem(items[i], i); if (error) { return sendError(res, 400, error, 'E_SCHEMA'); } } } try { const meta = await writeS3JsonObject(s3Key, items); return sendOk(res, meta); } catch (error) { console.error(error); return sendError(res, 500, 'Error writing to S3', 'E_S3'); } }; } /** * Создать роуты для JSON данных (GET + POST) */ function createJsonDataRoutes(s3Key, validateItem = null) { return { get: createJsonDataGET(s3Key), post: createJsonDataPOST(s3Key, validateItem) }; } module.exports = { createJsonDataRoutes, createJsonDataGET, createJsonDataPOST, };