diff options
author | HampusM <hampus@hampusmat.com> | 2021-07-24 23:40:18 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2021-07-24 23:40:18 +0200 |
commit | 0a10c326d9e56154686ec94bc53bbabe6cd54341 (patch) | |
tree | 9346fd177ddf5aaf635a8eb92294dbdb080c86f7 /packages | |
parent | 9c430da1dc28692bce3c3d1d2c1efa299a0791f3 (diff) |
Cleaned up & improved the git http backend
Diffstat (limited to 'packages')
-rw-r--r-- | packages/server/src/api/util.ts | 8 | ||||
-rw-r--r-- | packages/server/src/git/http.ts | 84 |
2 files changed, 38 insertions, 54 deletions
diff --git a/packages/server/src/api/util.ts b/packages/server/src/api/util.ts index e7e7657..0314db7 100644 --- a/packages/server/src/api/util.ts +++ b/packages/server/src/api/util.ts @@ -1,7 +1,5 @@ import { Commit } from "../git/commit"; import { Repository } from "../git/repository"; -import { RequestInfo } from "../git/http"; -import { readdir } from "fs"; type VerificationResultType = "SUCCESS" | "NOT_FOUND" | "INVALID" | "ACCESS_DENIED"; @@ -44,12 +42,12 @@ export async function verifySHA(repository: Repository, sha: string): Promise<Ve return new VerificationResult("SUCCESS"); } -export function verifyGitRequest(request_info: RequestInfo): VerificationResult { - if((/\.\/|\.\./u).test(request_info.parsed_url.pathname)) { +export function verifyGitRequest(path_name: string, service: string): VerificationResult { + if((/\.\/|\.\./u).test(path_name)) { return new VerificationResult("INVALID", "path"); } - if(request_info.service !== "git-upload-pack") { + if(service !== "git-upload-pack") { return new VerificationResult("ACCESS_DENIED"); } diff --git a/packages/server/src/git/http.ts b/packages/server/src/git/http.ts index 66d296c..76a91d9 100644 --- a/packages/server/src/git/http.ts +++ b/packages/server/src/git/http.ts @@ -5,84 +5,70 @@ import { join } from "path"; import { spawn } from "child_process"; import { verifyGitRequest } from "../api/util"; -export type RequestInfo = { - url_path: string, - parsed_url: URL, - url_path_parts: string[], - is_discovery: boolean, - service: string, - content_type: string -} - export interface Request extends FastifyRequest { params: Route["Params"], } -function getRequestInfo(req: Request, repository_name: string): RequestInfo { - const url_path = req.url.replace(req.params.repo, repository_name); +function writeRefDiscoveryFirstLine(service: string, reply: FastifyReply) { + const s = "# service=" + service + "\n"; + const n = (4 + s.length).toString(16); + reply.raw.write(Buffer.from((Array(4 - n.length + 1).join("0") + n + s) + "0000")); +} - const parsed_url = new URL(`${req.protocol}://${req.hostname}${url_path}`); - const url_path_parts = parsed_url.pathname.split("/"); +export function connect(repository: Repository, req: Request, reply: FastifyReply): void { + const parsed_url = new URL(`${req.protocol}://${req.hostname}${req.url.replace(req.params.repo, repository.name.short)}`); const is_discovery = (/\/info\/refs$/u).test(parsed_url.pathname); - let service = is_discovery ? parsed_url.searchParams.get("service") : url_path_parts[url_path_parts.length - 1]; - - const content_type = `application/x-${service}-${is_discovery ? "advertisement" : "result"}`; - - service = service || ""; + const url_path_parts = parsed_url.pathname.split("/"); - return { - url_path, - parsed_url, - is_discovery, - url_path_parts, - service, - content_type - }; -} + const service = is_discovery + ? parsed_url.searchParams.get("service") || "" + : url_path_parts[url_path_parts.length - 1]; -export function connect(repository: Repository, req: Request, reply: FastifyReply): void { - const request_info = getRequestInfo(req, repository.name.short); + const content_type = `application/x-${service}-${is_discovery ? "advertisement" : "result"}`; - const valid_request = verifyGitRequest(request_info); + const valid_request = verifyGitRequest(parsed_url.pathname, service); if(valid_request.success === false && valid_request.code) { - reply.header("Content-Type", request_info.content_type); + reply.header("Content-Type", content_type); reply.code(valid_request.code).send(valid_request.message); return; } - reply.raw.writeHead(200, { "Content-Type": request_info.content_type }); + reply.raw.writeHead(200, { "Content-Type": content_type }); const spawn_args = [ "--stateless-rpc", join(repository.base_dir, repository.name.full) ]; - if(request_info.is_discovery) { + if(is_discovery) { spawn_args.push("--advertise-refs"); } - const git_pack = spawn(request_info.service, spawn_args); + const git_service = spawn(service, spawn_args); - if(request_info.is_discovery) { - const s = "# service=" + request_info.service + "\n"; - const n = (4 + s.length).toString(16); - reply.raw.write(Buffer.from((Array(4 - n.length + 1).join("0") + n + s) + "0000")); + if(is_discovery) { + writeRefDiscoveryFirstLine(service, reply); } else { - const request_body = req.raw; + req.raw.pipe(git_service.stdin); - request_body.on("data", data => { - git_pack.stdin.write(data); - }); - request_body.on("end", () => { - git_pack.stdin.end(); + // Request error + req.raw.on("error", err => { + console.log(err); + git_service.stdin.end(); + reply.raw.end(); }); } - git_pack.on("error", err => console.log(err)); + // Spawn error + git_service.on("error", err => { + console.log(err); + reply.raw.end(); + }); - git_pack.stderr.on("data", (stderr: Buffer) => console.log(stderr.toString())); - git_pack.stdout.on("data", data => { - reply.raw.write(data); + // Git service error + git_service.stderr.on("data", (stderr: Buffer) => { + console.log(stderr.toString()); + reply.raw.end(); }); - git_pack.stdout.on("end", () => reply.raw.end()); + git_service.stdout.pipe(reply.raw); }
\ No newline at end of file |