aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2021-07-24 23:40:18 +0200
committerHampusM <hampus@hampusmat.com>2021-07-24 23:40:18 +0200
commit0a10c326d9e56154686ec94bc53bbabe6cd54341 (patch)
tree9346fd177ddf5aaf635a8eb92294dbdb080c86f7
parent9c430da1dc28692bce3c3d1d2c1efa299a0791f3 (diff)
Cleaned up & improved the git http backend
-rw-r--r--packages/server/src/api/util.ts8
-rw-r--r--packages/server/src/git/http.ts84
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