Improve Git protocol request and header handling
Expanded detection of Git requests by checking for Git-specific content types and improved user agent checks. Updated header handling to copy all headers for Git operations, ensuring better protocol compliance, and preserved all upstream response headers for Git requests. Also fixed parsing of platform from URL and improved body handling for POST requests.
This commit is contained in:
1 parent
ef54e4e6cc
commit
6ca96490c3
1 file changed
+56
-41
+56
-41
@@ -51,9 +51,9 @@ function isGitRequest(request, url) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for Git user agents
|
||||
// Check for Git user agents (more comprehensive check)
|
||||
const userAgent = request.headers.get("User-Agent") || "";
|
||||
if (userAgent.includes("git/")) {
|
||||
if (userAgent.includes("git/") || userAgent.startsWith("git/")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,15 @@ function isGitRequest(request, url) {
|
||||
return service === "git-upload-pack" || service === "git-receive-pack";
|
||||
}
|
||||
|
||||
// Check for Git-specific content types
|
||||
const contentType = request.headers.get("Content-Type") || "";
|
||||
if (
|
||||
contentType.includes("git-upload-pack") ||
|
||||
contentType.includes("git-receive-pack")
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -147,7 +156,7 @@ async function handleRequest(request, env, ctx) {
|
||||
}
|
||||
|
||||
// Parse platform and path
|
||||
const [_, platform, ...pathParts] = url.pathname.split("/");
|
||||
const [_, platform] = url.pathname.split("/");
|
||||
if (!platform || !CONFIG.PLATFORMS[platform]) {
|
||||
return new Response("Invalid or missing platform", {
|
||||
status: 400,
|
||||
@@ -182,43 +191,54 @@ async function handleRequest(request, env, ctx) {
|
||||
|
||||
// Add body for POST requests (Git operations)
|
||||
if (request.method === "POST" && isGit) {
|
||||
fetchOptions.body = await request.arrayBuffer();
|
||||
// For Git operations, we need to preserve the original body stream
|
||||
fetchOptions.body = request.body;
|
||||
}
|
||||
|
||||
// Set appropriate headers for Git vs regular requests
|
||||
if (isGit) {
|
||||
// Copy important headers for Git operations
|
||||
const gitHeaders = [
|
||||
"Content-Type",
|
||||
"Content-Length",
|
||||
"Authorization",
|
||||
"User-Agent",
|
||||
"Accept",
|
||||
"Accept-Encoding",
|
||||
"Git-Protocol",
|
||||
];
|
||||
|
||||
gitHeaders.forEach((header) => {
|
||||
const value = request.headers.get(header);
|
||||
if (value) {
|
||||
fetchOptions.headers.set(header, value);
|
||||
// For Git operations, copy all headers from the original request
|
||||
// This ensures Git protocol compliance
|
||||
for (const [key, value] of request.headers.entries()) {
|
||||
// Skip headers that might cause issues with proxying
|
||||
if (
|
||||
!["host", "connection", "upgrade", "proxy-connection"].includes(
|
||||
key.toLowerCase()
|
||||
)
|
||||
) {
|
||||
fetchOptions.headers.set(key, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Set Git-specific headers if not present
|
||||
if (!fetchOptions.headers.has("User-Agent")) {
|
||||
fetchOptions.headers.set("User-Agent", "git/2.34.1");
|
||||
}
|
||||
|
||||
// Ensure proper content type for Git operations
|
||||
// For Git upload-pack requests, ensure proper content type
|
||||
if (
|
||||
request.method === "POST" &&
|
||||
!fetchOptions.headers.has("Content-Type")
|
||||
url.pathname.endsWith("/git-upload-pack")
|
||||
) {
|
||||
fetchOptions.headers.set(
|
||||
"Content-Type",
|
||||
"application/x-git-upload-pack-request"
|
||||
);
|
||||
if (!fetchOptions.headers.has("Content-Type")) {
|
||||
fetchOptions.headers.set(
|
||||
"Content-Type",
|
||||
"application/x-git-upload-pack-request"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// For Git receive-pack requests, ensure proper content type
|
||||
if (
|
||||
request.method === "POST" &&
|
||||
url.pathname.endsWith("/git-receive-pack")
|
||||
) {
|
||||
if (!fetchOptions.headers.has("Content-Type")) {
|
||||
fetchOptions.headers.set(
|
||||
"Content-Type",
|
||||
"application/x-git-receive-pack-request"
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Regular file download headers
|
||||
@@ -261,10 +281,12 @@ async function handleRequest(request, env, ctx) {
|
||||
CONFIG.TIMEOUT_SECONDS * 1000
|
||||
);
|
||||
|
||||
response = await fetch(targetUrl, {
|
||||
...fetchOptions,
|
||||
signal: controller.signal,
|
||||
});
|
||||
// For Git operations, don't use Cloudflare-specific options
|
||||
const finalFetchOptions = isGit
|
||||
? { ...fetchOptions, signal: controller.signal }
|
||||
: { ...fetchOptions, signal: controller.signal };
|
||||
|
||||
response = await fetch(targetUrl, finalFetchOptions);
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
@@ -333,17 +355,10 @@ async function handleRequest(request, env, ctx) {
|
||||
const headers = new Headers(response.headers);
|
||||
|
||||
if (isGit) {
|
||||
// For Git operations, preserve important headers
|
||||
const preserveHeaders = [
|
||||
"Content-Type",
|
||||
"Content-Length",
|
||||
"Transfer-Encoding",
|
||||
"Content-Encoding",
|
||||
"Cache-Control",
|
||||
];
|
||||
|
||||
// Don't add security headers that might interfere with Git
|
||||
headers.set("X-Content-Type-Options", "nosniff");
|
||||
// For Git operations, preserve all headers from the upstream response
|
||||
// Git protocol is very sensitive to header changes
|
||||
// Don't add any additional headers that might interfere with Git protocol
|
||||
// The response headers from GitHub/GitLab should be passed through as-is
|
||||
} else {
|
||||
// Regular file download headers
|
||||
headers.set("Cache-Control", `public, max-age=${CONFIG.CACHE_DURATION}`);
|
||||
|
||||
Reference in new issue
Block a user