144 lines
4.6 KiB
JavaScript
144 lines
4.6 KiB
JavaScript
require('dotenv').config();
|
|
const express = require('express');
|
|
const https = require('https');
|
|
const fs = require('fs');
|
|
const axios = require('axios');
|
|
const { createHash } = require('crypto');
|
|
const archiver = require('archiver');
|
|
const rateLimit = require('express-rate-limit');
|
|
|
|
const app = express();
|
|
const port = process.env.PORT || 3000;
|
|
|
|
// Middleware to parse JSON requests
|
|
app.use(express.json());
|
|
|
|
// Set up the allowed domains (replace with your specific domains)
|
|
const allowedDomains = process.env.ALLOWED_DOMAINS.split(',');
|
|
|
|
// Middleware to allow requests only from specified domains
|
|
app.use((req, res, next) => {
|
|
const { origin } = req.headers;
|
|
|
|
// Check if the requesting origin is in the allowedDomains array
|
|
if (allowedDomains.includes(origin)) {
|
|
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
}
|
|
|
|
// Other headers for handling preflight requests and allowing credentials if needed
|
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
|
|
// Continue to the next middleware or route handler
|
|
next();
|
|
});
|
|
|
|
app.use(
|
|
rateLimit({
|
|
windowMs: 1 * 60 * 1000, // 1 minute
|
|
max: 1, // limit each IP to 1 request per windowMs
|
|
})
|
|
);
|
|
|
|
// hashContent function to hash the content of a file
|
|
async function hashContent(content) {
|
|
const hash = createHash('sha256');
|
|
hash.update(content);
|
|
return hash.digest('hex');
|
|
}
|
|
|
|
// API endpoint to start the recursive download and hashing
|
|
app.post('/hash', async (req, res) => {
|
|
try {
|
|
console.log('Request:', req.body);
|
|
let { url } = req.body;
|
|
if (!url) {
|
|
return res.status(400).json({ error: 'Missing URL in the request parameters' });
|
|
}
|
|
if (!Array.isArray(url))
|
|
url = [url];
|
|
|
|
const promises = url.map(async (url) => {
|
|
const response = await axios.get(url, { responseType: 'arraybuffer', timeout: 10000 });
|
|
const fileHash = await hashContent(response.data);
|
|
return { url, fileHash };
|
|
})
|
|
let results = await Promise.all(promises);
|
|
results = results.reduce((acc, { url, fileHash }) => {
|
|
acc[url] = fileHash;
|
|
return acc;
|
|
}, {});
|
|
res.json(results);
|
|
} catch (error) {
|
|
console.error('Error:', error.message);
|
|
res.status(500).json({ error: 'Internal Server Error' });
|
|
}
|
|
});
|
|
// Function to download a GitHub repo as a zip file
|
|
async function downloadGitHubRepo(owner, repo) {
|
|
if (!owner || !repo) {
|
|
throw new Error('Missing owner or repo');
|
|
}
|
|
const zipUrl = `https://github.com/${owner}/${repo}/archive/refs/heads/master.zip`;
|
|
const response = await axios.get(zipUrl, { responseType: 'arraybuffer' });
|
|
return response.data;
|
|
}
|
|
|
|
// Endpoint to download and zip GitHub repositories
|
|
app.post('/download-repos', async (req, res) => {
|
|
try {
|
|
let { urls } = req.body;
|
|
|
|
if (!urls) {
|
|
return res.status(400).json({ error: 'Missing urls in the request parameters' });
|
|
}
|
|
if (!Array.isArray(urls)) {
|
|
urls = [urls];
|
|
}
|
|
|
|
const archive = archiver('zip');
|
|
res.attachment('repos.zip');
|
|
|
|
// Create an array of promises for each repository download
|
|
const downloadPromises = urls.map(async (url) => {
|
|
const [owner, name] = url.split('/').slice(-2);
|
|
|
|
if (!owner || !name) {
|
|
console.error(`Invalid url format: ${url}`);
|
|
return;
|
|
}
|
|
|
|
const zipBuffer = await downloadGitHubRepo(owner, name);
|
|
// Add the zip file to the archiver
|
|
archive.append(zipBuffer, { name: `${owner}-${name}.zip` });
|
|
});
|
|
|
|
// Wait for all promises to complete
|
|
await Promise.all(downloadPromises);
|
|
|
|
// Finalize the zip file
|
|
archive.finalize();
|
|
|
|
// Pipe the zip file to the response
|
|
archive.pipe(res);
|
|
} catch (error) {
|
|
console.error('Error:', error.message);
|
|
res.status(500).json({ error: 'Internal Server Error' });
|
|
}
|
|
});
|
|
// HTTPS options (provide the paths to your SSL/TLS certificate and private key)
|
|
const httpsOptions = {
|
|
key: fs.readFileSync('./server-key.pem'),
|
|
cert: fs.readFileSync('./server-cert.pem'),
|
|
};
|
|
|
|
// Create HTTPS server
|
|
const server = https.createServer(httpsOptions, app);
|
|
|
|
// Start the server
|
|
server.listen(port, () => {
|
|
console.log(`Server is running at https://localhost:${port}`);
|
|
});
|
|
// Export the Express API
|
|
module.exports = app |