-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cd8d16d
commit 329e018
Showing
11 changed files
with
141 additions
and
225 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import * as fs from 'fs'; | ||
import path from 'path'; | ||
import { getIdPrefixes } from '../utils/strings.js'; | ||
import { isValidBlobId } from '../utils/validation.js'; | ||
// Test Blob Info | ||
// | ||
// MIME type: image/png | ||
// | ||
// Blob ID: 0nzvRVLeF0I5kbWO3s_VDa-ixYZ_nhkp4J2EubJUtjo | ||
// Unencoded size: 165 KiB | ||
// Encoded size (including metadata): 62.0 MiB | ||
// Sui object ID: 0x0ebad3b13ee9bc64f8d6370e71d3408a43febaa017a309d2367117afe144ae8c | ||
// Cache-Control value initialized once | ||
const metricsCacheControl = process.env.METRICS_CACHE_CONTROL || 'public, max-age=10'; | ||
export const getMetrics = async (req, res) => { | ||
const { id = '' } = req.params; | ||
// Request validation | ||
try { | ||
await isValidBlobId(id); | ||
} | ||
catch (error) { | ||
if (error instanceof Error) { | ||
res.status(400).send(error.message); | ||
} | ||
else { | ||
res.status(400).send('Unknown error'); | ||
} | ||
} | ||
const { prefix_1, prefix_2 } = getIdPrefixes(id); | ||
if (!prefix_1 || !prefix_2) { | ||
// Should never happen because id was validated. | ||
return res.status(500).send('Internal Server Error (prefix)'); | ||
} | ||
// Attempt reading metrics information | ||
// from ~/cache/prefix1/prefix2/<id>.metrics | ||
// | ||
// If it is not created yet, then there is no metrics. | ||
// Return empty metrics JSON: | ||
// { | ||
// "status": "no_metrics", | ||
// "message": "No metrics accumulated yet for this item. Metrics updated every ~24 hours.", | ||
// } | ||
// | ||
// If the .metrics file exists, return it as JSON. | ||
const homePath = process.env.HOME || ''; | ||
const jsonPath = path.resolve(homePath, 'cache', prefix_1, prefix_2, `${id}.metrics`); | ||
const options = { | ||
headers: { | ||
'Cache-Control': metricsCacheControl, | ||
'Content-Type': 'application/json', | ||
}, | ||
}; | ||
try { | ||
await fs.promises.access(jsonPath); | ||
// Stream the .metrics as response. | ||
res.sendFile(jsonPath, options, err => { | ||
if (err) { | ||
res.status(500).send('Error streaming metrics'); | ||
} | ||
}); | ||
} | ||
catch (err) { | ||
// File does not exist, return "no_metrics" JSON response | ||
res.json({ | ||
blobId: id, | ||
status: 'no_metrics', | ||
message: 'No metrics accumulated yet for this blob. Metrics updated every ~24 hours.', | ||
}); | ||
} | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import express from 'express'; | ||
import { getBlob } from '../controllers/blob.js'; | ||
export const blobRoutes = express.Router(); | ||
blobRoutes.get('/', (req, res) => { | ||
res.set('Cache-Control', 'public, max-age=86400'); | ||
res.send('Blob ID missing.<br><br> Useage: <b>https://cdn.suiftly.io/blob/<i><your_blob_id></i></b>'); | ||
}); | ||
blobRoutes.get('/:id', getBlob); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import express from 'express'; | ||
import { getMetrics } from '../controllers/metrics.js'; | ||
export const metricsRoutes = express.Router(); | ||
metricsRoutes.get('/', (req, res) => { | ||
res.set('Cache-Control', 'public, max-age=86400'); | ||
res.send('Blob ID missing.<br><br> Useage: <b>https://cdn.suiftly.io/metrics/<i><your_blob_id></i></b>'); | ||
}); | ||
metricsRoutes.get('/:id', getMetrics); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Simple string utilities | ||
export function getIdPrefixes(id) { | ||
// Extract two short prefix from the blob ID. | ||
// Used for file system partitioning | ||
if (!id || id.length < 4) { | ||
return { prefix_1: '', prefix_2: '' }; | ||
} | ||
const prefix_1 = id.slice(0, 2); | ||
const prefix_2 = id.slice(2, 4); | ||
return { prefix_1, prefix_2 }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
export function isValidBlobId(id) { | ||
return new Promise((resolve, reject) => { | ||
if (typeof id !== 'string' || id.trim().length === 0) { | ||
return reject(new Error('Blob ID is required')); | ||
} | ||
// Verify that the blob ID is a URL-safe base64 string | ||
const base64Pattern = /^[a-zA-Z0-9-_]+$/; | ||
if (!base64Pattern.test(id)) { | ||
reject(new Error('Blob ID invalid')); | ||
} | ||
// Fast sanity check (enough characters for u256). | ||
// TODO Calculate more precisely, this should be 44!? | ||
if (id.length < 42) { | ||
reject(new Error('Blob ID too short')); | ||
} | ||
resolve(); | ||
}); | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.