I'm trying to serve a given, clone repository using NodeJS & ExpressJS. I was able to clone it locally, but I am not able to send it to the frontend. This is my code:
const express = require("express");
const app = express();
const port = 3000;
const path = require("path");
const { execSync } = require("child_process");
// function to download the repo
const downloadRepo = (repoURL) =>
execSync(`git clone ${repoURL}`, {
stdio: [0, 1, 2],
cwd: path.resolve(__dirname, ""),
});
// route to clone the repo
app.get("/:repoOwner/:repoName", async (req, res) => {
const { repoOwner, repoName } = req.params;
// composing the repo URL to be downloaded
const fullRepoURL = `https://github.com/${repoOwner}/${repoName}.git`;
// downloading the repo in the root folder
await downloadRepo(fullRepoURL);
// returns the FULL URL of the repo in the frontend
res.send(fullRepoURL);
// trying to return the repo's content in the the frontend
// I get status 304 (not modified)
res.sendFile(path.resolve(__dirname, repoName));
});
app.listen(port, () => {
console.log(`App listening at http://localhost:${port}`);
});
CodePudding user response:
Not a straight answer, but a couple of remarks and suggestions:
A Git repository is not a single file, thus
sendFile
will not work.Your code executes both
send
andsendFile
in one handler. This will not work because you can only send one single response per request.A Git clone is a long running operation (multiple seconds to minutes or even hours) which should not run within a request handler. With the current version it would even block further requests due to the
execSync
.If you want to “return” the repository, you could ZIP it and send the entire repo in a single ZIP archive (however, this is a functionality which is covered by GitHub themselves, thus this code would not even be needed).
Additional suggestions based on the information given:
Have a “clone repo” endpoint which kicks off cloning within a background job (have e.g. a look at agenda or similar job scheduling tools for Node) and which writes the result into a ZIP file.
Have another endpoint where you can continuously check the status or progress of the clone, and which finally returns a download URL (i.e. the produced ZIP file which you can serve with the
express.static
middleware).Alternatively, do not ZIP the data, but serve the clone through the file system (also e.g. using
express.static
).