feat: Disable auto-ETag in Express, enhance S3 interaction with improved error handling and response structure for ASNs, Domains, and IP Ranges APIs
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 4m39s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 4m39s
This commit is contained in:
+23
-20
@@ -13,6 +13,8 @@ const port = 3001;
|
|||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(compression());
|
app.use(compression());
|
||||||
|
// Disable Express auto-ETag to avoid weak ETags on JSON bodies
|
||||||
|
app.set('etag', false);
|
||||||
|
|
||||||
// Expose important headers to browser JS (for CORS)
|
// Expose important headers to browser JS (for CORS)
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
@@ -27,9 +29,13 @@ app.use(express.static(path.join(__dirname, 'public')));
|
|||||||
const s3 = new AWS.S3({
|
const s3 = new AWS.S3({
|
||||||
endpoint: 'https://storage.yandexcloud.net',
|
endpoint: 'https://storage.yandexcloud.net',
|
||||||
region: process.env.AWS_REGION,
|
region: process.env.AWS_REGION,
|
||||||
|
s3ForcePathStyle: true,
|
||||||
|
signatureVersion: 'v4',
|
||||||
|
httpOptions: { timeout: 15000 },
|
||||||
|
maxRetries: 3,
|
||||||
credentials: {
|
credentials: {
|
||||||
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID || process.env.S3_ACCESS_KEY_ID,
|
||||||
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || process.env.S3_SECRET_ACCESS_KEY,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -365,11 +371,10 @@ app.post('/api/asns', async (req, res) => {
|
|||||||
if (!validateAsns(asns || [])) {
|
if (!validateAsns(asns || [])) {
|
||||||
return res.status(400).json({ message: 'Invalid payload format for asns' });
|
return res.status(400).json({ message: 'Invalid payload format for asns' });
|
||||||
}
|
}
|
||||||
if (etag) {
|
let current = null;
|
||||||
const current = await headS3ObjectEtag('bgp_data/asns.txt').catch(() => undefined);
|
try { current = await headS3ObjectEtag('bgp_data/asns.txt'); } catch {}
|
||||||
if (current && current.replace(/\"/g, '"') !== String(etag)) {
|
if (current && etag && current !== String(etag)) {
|
||||||
return res.status(412).json({ message: 'Precondition Failed: ETag mismatch' });
|
return res.status(412).json({ message: 'Precondition Failed: ETag mismatch', currentEtag: current });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
@@ -388,7 +393,7 @@ app.post('/api/asns', async (req, res) => {
|
|||||||
if (head.LastModified) res.set('Last-Modified', new Date(head.LastModified).toUTCString());
|
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 (typeof head.ContentLength === 'number') res.set('Content-Length-Source', String(head.ContentLength));
|
||||||
} catch {}
|
} catch {}
|
||||||
res.send('File updated successfully');
|
res.json({ ok: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
res.status(500).send('Error writing to S3');
|
res.status(500).send('Error writing to S3');
|
||||||
@@ -453,11 +458,10 @@ app.post('/api/domains-new', async (req, res) => {
|
|||||||
if (!validateDomainsNew(domains || [])) {
|
if (!validateDomainsNew(domains || [])) {
|
||||||
return res.status(400).json({ message: 'Invalid payload format for domains-new' });
|
return res.status(400).json({ message: 'Invalid payload format for domains-new' });
|
||||||
}
|
}
|
||||||
if (etag) {
|
let current = null;
|
||||||
const current = await headS3ObjectEtag('bgp_data/domains_community.txt').catch(() => undefined);
|
try { current = await headS3ObjectEtag('bgp_data/domains_community.txt'); } catch {}
|
||||||
if (current && current.replace(/\"/g, '"') !== String(etag)) {
|
if (current && etag && current !== String(etag)) {
|
||||||
return res.status(412).json({ message: 'Precondition Failed: ETag mismatch' });
|
return res.status(412).json({ message: 'Precondition Failed: ETag mismatch', currentEtag: current });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
@@ -476,7 +480,7 @@ app.post('/api/domains-new', async (req, res) => {
|
|||||||
if (head.LastModified) res.set('Last-Modified', new Date(head.LastModified).toUTCString());
|
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 (typeof head.ContentLength === 'number') res.set('Content-Length-Source', String(head.ContentLength));
|
||||||
} catch {}
|
} catch {}
|
||||||
res.send('File updated successfully');
|
res.json({ ok: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
res.status(500).send('Error writing to S3');
|
res.status(500).send('Error writing to S3');
|
||||||
@@ -541,11 +545,10 @@ app.post('/api/ip-ranges', async (req, res) => {
|
|||||||
if (!validateIpRanges(ipRanges || [])) {
|
if (!validateIpRanges(ipRanges || [])) {
|
||||||
return res.status(400).json({ message: 'Invalid payload format for ip-ranges' });
|
return res.status(400).json({ message: 'Invalid payload format for ip-ranges' });
|
||||||
}
|
}
|
||||||
if (etag) {
|
let current = null;
|
||||||
const current = await headS3ObjectEtag('bgp_data/ips.txt').catch(() => undefined);
|
try { current = await headS3ObjectEtag('bgp_data/ips.txt'); } catch {}
|
||||||
if (current && current.replace(/\"/g, '"') !== String(etag)) {
|
if (current && etag && current !== String(etag)) {
|
||||||
return res.status(412).json({ message: 'Precondition Failed: ETag mismatch' });
|
return res.status(412).json({ message: 'Precondition Failed: ETag mismatch', currentEtag: current });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
@@ -564,7 +567,7 @@ app.post('/api/ip-ranges', async (req, res) => {
|
|||||||
if (head.LastModified) res.set('Last-Modified', new Date(head.LastModified).toUTCString());
|
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 (typeof head.ContentLength === 'number') res.set('Content-Length-Source', String(head.ContentLength));
|
||||||
} catch {}
|
} catch {}
|
||||||
res.send('File updated successfully');
|
res.json({ ok: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
res.status(500).send('Error writing to S3');
|
res.status(500).send('Error writing to S3');
|
||||||
|
|||||||
Reference in New Issue
Block a user