adding hashing and downloading endpoints
This commit is contained in:
parent
cf6be7f314
commit
a13295434f
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
config.env
|
||||
node_modules
|
||||
test.rest
|
||||
147
index.js
147
index.js
@ -1,25 +1,142 @@
|
||||
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 options = {
|
||||
key: fs.readFileSync('server-key.pem'),
|
||||
cert: fs.readFileSync('server-cert.pem'),
|
||||
};
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const server = https.createServer(options, (req, res) => {
|
||||
// Middleware to parse JSON requests
|
||||
app.use(express.json());
|
||||
|
||||
// Handle your request logic here
|
||||
if (req.method === 'GET' && req.url === '/') {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.end('Hello, HTTPS Server!');
|
||||
} else {
|
||||
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
||||
res.end('Not Found');
|
||||
// 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;
|
||||
}
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
// Endpoint to download and zip GitHub repositories
|
||||
app.post('/download-repos', async (req, res) => {
|
||||
try {
|
||||
let { urls } = req.body;
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`Server is running at https://localhost:${PORT}/`);
|
||||
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}`);
|
||||
});
|
||||
|
||||
2
index.min.js
vendored
2
index.min.js
vendored
@ -1 +1 @@
|
||||
const https=require("https"),fs=require("fs"),options={key:fs.readFileSync("server-key.pem"),cert:fs.readFileSync("server-cert.pem")},server=https.createServer(options,((req,res)=>{"GET"===req.method&&"/"===req.url?(res.writeHead(200,{"Content-Type":"text/plain"}),res.end("Hello, HTTPS Server!")):(res.writeHead(404,{"Content-Type":"text/plain"}),res.end("Not Found"))})),PORT=process.env.PORT||3e3;server.listen(PORT,(()=>{console.log(`Server is running at https://localhost:${PORT}/`)}));
|
||||
require("dotenv").config();const express=require("express"),https=require("https"),fs=require("fs"),axios=require("axios"),{createHash:createHash}=require("crypto"),archiver=require("archiver"),rateLimit=require("express-rate-limit"),app=express(),port=process.env.PORT||3e3;app.use(express.json());const allowedDomains=process.env.ALLOWED_DOMAINS.split(",");async function hashContent(content){const hash=createHash("sha256");return hash.update(content),hash.digest("hex")}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`;return(await axios.get(zipUrl,{responseType:"arraybuffer"})).data}app.use(((req,res,next)=>{const{origin:origin}=req.headers;allowedDomains.includes(origin)&&res.setHeader("Access-Control-Allow-Origin",origin),res.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),res.setHeader("Access-Control-Allow-Headers","Content-Type"),res.setHeader("Access-Control-Allow-Credentials","true"),next()})),app.use(rateLimit({windowMs:6e4,max:1})),app.post("/hash",(async(req,res)=>{try{console.log("Request:",req.body);let{url:url}=req.body;if(!url)return res.status(400).json({error:"Missing URL in the request parameters"});Array.isArray(url)||(url=[url]);const promises=url.map((async url=>{const response=await axios.get(url,{responseType:"arraybuffer",timeout:1e4});return{url:url,fileHash:await hashContent(response.data)}}));let results=await Promise.all(promises);results=results.reduce(((acc,{url:url,fileHash:fileHash})=>(acc[url]=fileHash,acc)),{}),res.json(results)}catch(error){console.error("Error:",error.message),res.status(500).json({error:"Internal Server Error"})}})),app.post("/download-repos",(async(req,res)=>{try{let{urls:urls}=req.body;if(!urls)return res.status(400).json({error:"Missing urls in the request parameters"});Array.isArray(urls)||(urls=[urls]);const archive=archiver("zip");res.attachment("repos.zip");const downloadPromises=urls.map((async url=>{const[owner,name]=url.split("/").slice(-2);if(!owner||!name)return void console.error(`Invalid url format: ${url}`);const zipBuffer=await downloadGitHubRepo(owner,name);archive.append(zipBuffer,{name:`${owner}-${name}.zip`})}));await Promise.all(downloadPromises),archive.finalize(),archive.pipe(res)}catch(error){console.error("Error:",error.message),res.status(500).json({error:"Internal Server Error"})}}));const httpsOptions={key:fs.readFileSync("./server-key.pem"),cert:fs.readFileSync("./server-cert.pem")},server=https.createServer(httpsOptions,app);server.listen(port,(()=>{console.log(`Server is running at https://localhost:${port}`)}));
|
||||
1464
package-lock.json
generated
Normal file
1464
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@ -4,8 +4,19 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"devStart": "nodemon index.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"archiver": "^6.0.1",
|
||||
"axios": "^1.6.2",
|
||||
"crypto": "^1.0.1",
|
||||
"express": "^4.18.2",
|
||||
"express-rate-limit": "^7.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dotenv": "^16.3.1",
|
||||
"nodemon": "^3.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user