Xget Git 协议支持详解


Xget Git 协议支持详解

概述

本文档详细介绍了 Xget 对 Git 协议的全面支持,包括 HTTP/HTTPS、SSH、Git 协议等各种 Git 传输协议的加速方案。通过 Xget,开发者可以显著提升 Git 操作的速度和稳定性。

Git 协议基础

Git 传输协议

Git 支持多种传输协议:

  1. HTTP/HTTPS 协议

    • 最常用的协议
    • 支持代理和缓存
    • 适合防火墙环境
  2. SSH 协议

    • 加密传输
    • 支持认证
    • 适合安全要求高的场景
  3. Git 协议

    • 最快的协议
    • 无加密
    • 适合内网环境
  4. Git 协议 (SSH)

    • 结合了 Git 协议和 SSH
    • 速度快且安全

Git 操作类型

Git 操作主要分为以下类型:

  1. Clone

    • 克隆完整仓库
    • 浅克隆(shallow clone)
    • 单分支克隆
  2. Fetch

    • 获取远程更新
    • 获取特定分支
    • 获取特定标签
  3. Pull

    • 拉取并合并
    • 拉取并变基
  4. Push

    • 推送提交
    • 推送标签
    • 强制推送
  5. 其他操作

    • LFS 操作
    • Submodule 操作
    • Archive 操作

HTTP/HTTPS 协议支持

基本原理

Xget 通过 HTTP/HTTPS 协议代理 Git 操作,实现以下功能:

  1. URL 转换

    • 将原始 Git URL 转换为 Xget 加速 URL
    • 自动识别 Git 仓库地址
  2. 请求代理

    • 代理 Git HTTP 请求
    • 处理 Git 特定的请求头
  3. 响应缓存

    • 缓存 Git 对象
    • 减少重复请求

URL 转换规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// GitHub URL 转换
function convertGitHubUrl(url) {
// 原始 URL: https://github.com/user/repo.git
// 加速 URL: https://xget.xi-xu.me/gh/user/repo.git

const pattern = /^https?:\/\/github\.com\/(.+?)\/(.+?)(\.git)?$/;
const match = url.match(pattern);

if (match) {
const [, user, repo] = match;
return `https://xget.xi-xu.me/gh/${user}/${repo}.git`;
}

return url;
}

// GitLab URL 转换
function convertGitLabUrl(url) {
// 原始 URL: https://gitlab.com/user/repo.git
// 加速 URL: https://xget.xi-xu.me/gl/user/repo.git

const pattern = /^https?:\/\/gitlab\.com\/(.+?)\/(.+?)(\.git)?$/;
const match = url.match(pattern);

if (match) {
const [, user, repo] = match;
return `https://xget.xi-xu.me/gl/${user}/${repo}.git`;
}

return url;
}

// 通用 URL 转换
function convertGitUrl(url) {
const converters = [
convertGitHubUrl,
convertGitLabUrl,
// 添加其他平台的转换函数
];

for (const converter of converters) {
const converted = converter(url);
if (converted !== url) {
return converted;
}
}

return url;
}

Git HTTP 请求处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Git HTTP 请求处理器
async function handleGitHttpRequest(request) {
const url = new URL(request.url);
const path = url.pathname;

// Git 智能协议请求
if (path.endsWith('/info/refs')) {
return await handleInfoRefs(request);
}

// Git 对象请求
if (path.includes('/objects/')) {
return await handleGitObject(request);
}

// Git 上传包请求
if (path.includes('/git-upload-pack')) {
return await handleUploadPack(request);
}

// Git 接收包请求
if (path.includes('/git-receive-pack')) {
return await handleReceivePack(request);
}

// 默认处理
return await fetch(request);
}

// 处理 info/refs 请求
async function handleInfoRefs(request) {
const url = new URL(request.url);
const service = url.searchParams.get('service');

// 构建目标 URL
const targetUrl = buildTargetUrl(url);

// 添加 Git 特定的请求头
const headers = new Headers(request.headers);
headers.set('Git-Protocol', 'version=2');

// 发送请求
const response = await fetch(targetUrl, {
method: request.method,
headers: headers
});

return response;
}

// 处理 Git 对象请求
async function handleGitObject(request) {
const url = new URL(request.url);
const targetUrl = buildTargetUrl(url);

// 检查缓存
const cacheKey = `git-object:${url.pathname}`;
const cached = await CACHE.get(cacheKey);

if (cached) {
return new Response(cached, {
headers: {
'X-Cache': 'HIT',
'Content-Type': 'application/x-git-loose-object'
}
});
}

// 发送请求
const response = await fetch(targetUrl, {
method: request.method,
headers: request.headers
});

// 缓存响应
if (response.ok) {
const clonedResponse = response.clone();
const buffer = await clonedResponse.arrayBuffer();
await CACHE.put(cacheKey, buffer, {
expirationTtl: 86400 // 缓存 24 小时
});
}

return response;
}

// 处理 git-upload-pack 请求
async function handleUploadPack(request) {
const url = new URL(request.url);
const targetUrl = buildTargetUrl(url);

// 处理 POST 请求体
const body = await request.arrayBuffer();

// 发送请求
const response = await fetch(targetUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-git-upload-pack-request',
'Accept': 'application/x-git-upload-pack-result'
},
body: body
});

return response;
}

// 处理 git-receive-pack 请求
async function handleReceivePack(request) {
const url = new URL(request.url);
const targetUrl = buildTargetUrl(url);

// 处理 POST 请求体
const body = await request.arrayBuffer();

// 发送请求
const response = await fetch(targetUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-git-receive-pack-request',
'Accept': 'application/x-git-receive-pack-result'
},
body: body
});

// 失效相关缓存
await invalidateGitCache(url.pathname);

return response;
}

// 构建目标 URL
function buildTargetUrl(url) {
// 移除 Xget 前缀
const path = url.pathname.replace(/^\/(gh|gl|gitea)\//, '');

// 构建目标 URL
const platform = url.pathname.split('/')[1];
const baseUrl = getPlatformBaseUrl(platform);

return `${baseUrl}/${path}`;
}

// 获取平台基础 URL
function getPlatformBaseUrl(platform) {
const platforms = {
'gh': 'https://github.com',
'gl': 'https://gitlab.com',
'gitea': 'https://gitea.com'
};

return platforms[platform] || 'https://github.com';
}

Git LFS 支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Git LFS 请求处理
async function handleGitLfsRequest(request) {
const url = new URL(request.url);
const path = url.pathname;

// LFS 对象下载
if (path.includes('/objects/')) {
return await handleLFSObject(request);
}

// LFS 批量操作
if (path.includes('/objects/batch')) {
return await handleLFSBatch(request);
}

return await fetch(request);
}

// 处理 LFS 对象请求
async function handleLFSObject(request) {
const url = new URL(request.url);
const targetUrl = buildTargetUrl(url);

// 检查缓存
const cacheKey = `lfs-object:${url.pathname}`;
const cached = await CACHE.get(cacheKey);

if (cached) {
return new Response(cached, {
headers: {
'X-Cache': 'HIT',
'Content-Type': 'application/vnd.git-lfs'
}
});
}

// 发送请求
const response = await fetch(targetUrl, {
method: request.method,
headers: request.headers
});

// 缓存响应
if (response.ok) {
const clonedResponse = response.clone();
const buffer = await clonedResponse.arrayBuffer();
await CACHE.put(cacheKey, buffer, {
expirationTtl: 604800 // 缓存 7 天
});
}

return response;
}

// 处理 LFS 批量操作
async function handleLFSBatch(request) {
const url = new URL(request.url);
const targetUrl = buildTargetUrl(url);

// 处理 POST 请求体
const body = await request.json();

// 发送请求
const response = await fetch(targetUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/vnd.git-lfs+json',
'Accept': 'application/vnd.git-lfs+json'
},
body: JSON.stringify(body)
});

return response;
}

SSH 协议支持

SSH 代理原理

Xget 通过 SSH 代理实现 Git SSH 协议的加速:

  1. SSH 连接代理

    • 代理 SSH 连接
    • 处理 SSH 认证
  2. 数据传输优化

    • 压缩传输数据
    • 缓存传输内容
  3. 连接复用

    • 复用 SSH 连接
    • 减少连接开销

SSH URL 转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// SSH URL 转换
function convertSSHUrl(url) {
// 原始 URL: [email protected]:user/repo.git
// 加速 URL: ssh://[email protected]:22/gh/user/repo.git

const sshPattern = /^git@([^:]+):(.+)$/;
const match = url.match(sshPattern);

if (match) {
const [, host, repoPath] = match;
const platform = getPlatformFromHost(host);

return `ssh://[email protected]:22/${platform}/${repoPath}`;
}

return url;
}

// 从主机名获取平台
function getPlatformFromHost(host) {
const platforms = {
'github.com': 'gh',
'gitlab.com': 'gl',
'gitea.com': 'gitea'
};

return platforms[host] || 'gh';
}

SSH 配置

~/.ssh/config 中配置 Xget SSH 代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# GitHub
Host github.com
HostName xget.xi-xu.me
Port 22
User git
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh -W %h:%p [email protected]

# GitLab
Host gitlab.com
HostName xget.xi-xu.me
Port 22
User git
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh -W %h:%p [email protected]

SSH 密钥管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// SSH 密钥验证
async function verifySSHKey(publicKey) {
// 验证 SSH 密钥格式
const keyPattern = /^(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521) /;

if (!keyPattern.test(publicKey)) {
throw new Error('Invalid SSH key format');
}

// 验证密钥长度
const keyParts = publicKey.split(' ');
if (keyParts.length < 2) {
throw new Error('Invalid SSH key format');
}

return true;
}

// SSH 密钥存储
async function storeSSHKey(userId, publicKey) {
const key = `ssh-key:${userId}`;

await KV.put(key, publicKey, {
expirationTtl: 2592000 // 30 天
});
}

// SSH 密钥获取
async function getSSHKey(userId) {
const key = `ssh-key:${userId}`;

return await KV.get(key);
}

Git 协议支持

Git 协议原理

Git 协议是 Git 专用的传输协议,特点:

  1. 高效传输

    • 二进制协议
    • 最小化数据传输
  2. 无加密

    • 速度快
    • 不适合公网
  3. 简单实现

    • 协议简单
    • 易于实现

Git 协议 URL 转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Git 协议 URL 转换
function convertGitProtocolUrl(url) {
// 原始 URL: git://github.com/user/repo.git
// 加速 URL: git://xget.xi-xu.me/gh/user/repo.git

const gitPattern = /^git:\/\/([^\/]+)\/(.+)$/;
const match = url.match(gitPattern);

if (match) {
const [, host, repoPath] = match;
const platform = getPlatformFromHost(host);

return `git://xget.xi-xu.me/${platform}/${repoPath}`;
}

return url;
}

Git 协议处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Git 协议请求处理
async function handleGitProtocolRequest(request) {
const url = new URL(request.url);
const path = url.pathname;

// Git 协议请求
if (url.protocol === 'git:') {
return await handleGitProtocol(request);
}

return await fetch(request);
}

// 处理 Git 协议
async function handleGitProtocol(request) {
const url = new URL(request.url);
const targetUrl = buildTargetUrl(url);

// 创建 Git 协议连接
const connection = await createGitConnection(targetUrl);

// 处理 Git 协议握手
await handleGitHandshake(connection);

// 处理 Git 协议数据传输
return await handleGitDataTransfer(connection, request);
}

// 创建 Git 协议连接
async function createGitConnection(url) {
// 实现 Git 协议连接
const connection = {
url: url,
socket: null,
state: 'connected'
};

return connection;
}

// 处理 Git 协议握手
async function handleGitHandshake(connection) {
// 实现 Git 协议握手
const handshake = `git-upload-pack ${connection.url.pathname}\0host=${connection.url.hostname}\0`;

connection.socket.send(handshake);

const response = await connection.socket.receive();

return response;
}

// 处理 Git 协议数据传输
async function handleGitDataTransfer(connection, request) {
// 实现 Git 协议数据传输
const data = await request.arrayBuffer();

connection.socket.send(data);

const response = await connection.socket.receive();

return new Response(response, {
headers: {
'Content-Type': 'application/x-git-upload-pack-result'
}
});
}

Git 操作优化

Clone 操作优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Clone 操作优化
async function optimizeClone(url, options = {}) {
const { depth = 0, singleBranch = false, branch = null } = options;

// 构建优化后的 URL
let optimizedUrl = convertGitUrl(url);

// 添加查询参数
const searchParams = new URLSearchParams();

if (depth > 0) {
searchParams.set('depth', depth.toString());
}

if (singleBranch) {
searchParams.set('single-branch', 'true');
}

if (branch) {
searchParams.set('branch', branch);
}

if (searchParams.toString()) {
optimizedUrl += `?${searchParams.toString()}`;
}

return optimizedUrl;
}

// 使用示例
const optimizedUrl = await optimizeClone('https://github.com/user/repo.git', {
depth: 1,
singleBranch: true,
branch: 'main'
});

Fetch 操作优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Fetch 操作优化
async function optimizeFetch(url, options = {}) {
const { depth = 0, prune = false, tags = true } = options;

// 构建优化后的 URL
let optimizedUrl = convertGitUrl(url);

// 添加查询参数
const searchParams = new URLSearchParams();

if (depth > 0) {
searchParams.set('depth', depth.toString());
}

if (prune) {
searchParams.set('prune', 'true');
}

if (!tags) {
searchParams.set('no-tags', 'true');
}

if (searchParams.toString()) {
optimizedUrl += `?${searchParams.toString()}`;
}

return optimizedUrl;
}

// 使用示例
const optimizedUrl = await optimizeFetch('https://github.com/user/repo.git', {
depth: 1,
prune: true,
tags: false
});

Push 操作优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Push 操作优化
async function optimizePush(url, options = {}) {
const { force = false, forceWithLease = false, tags = false } = options;

// 构建优化后的 URL
let optimizedUrl = convertGitUrl(url);

// 添加查询参数
const searchParams = new URLSearchParams();

if (force) {
searchParams.set('force', 'true');
}

if (forceWithLease) {
searchParams.set('force-with-lease', 'true');
}

if (tags) {
searchParams.set('tags', 'true');
}

if (searchParams.toString()) {
optimizedUrl += `?${searchParams.toString()}`;
}

return optimizedUrl;
}

// 使用示例
const optimizedUrl = await optimizePush('https://github.com/user/repo.git', {
force: false,
tags: true
});

Git 配置优化

全局配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 配置 Git 使用 Xget
git config --global url."https://xget.xi-xu.me/gh/".insteadOf "https://github.com/"
git config --global url."https://xget.xi-xu.me/gl/".insteadOf "https://gitlab.com/"
git config --global url."https://xget.xi-xu.me/gitea/".insteadOf "https://gitea.com/"

# 配置 Git 协议
git config --global http.proxy http://xget.xi-xu.me:8080
git config --global https.proxy https://xget.xi-xu.me:8443

# 配置缓存
git config --global http.cache 3600
git config --global https.cache 3600

# 配置压缩
git config --global core.compression 9
git config --global http.compression 9
git config --global https.com 9

仓库配置

1
2
3
4
5
6
7
8
9
10
# 进入仓库目录
cd your-repo

# 配置仓库使用 Xget
git config url."https://xget.xi-xu.me/gh/".insteadOf "https://github.com/"

# 配置 LFS
git config lfs.url https://xget.xi-xu.me/gh/user/repo.git/info/lfs
git config lfs.basictransfersonly true
git config lfs.concurrenttransfers 8

性能配置

1
2
3
4
5
6
7
8
9
10
11
12
13
# 配置并发
git config --global http.postBuffer 524288000
git config --global http.lowSpeedLimit 0
git config --global http.lowSpeedTime 999999

# 配置超时
git config --global http.timeout 600
git config --global http.connectTimeout 30
git config --global http.readTimeout 600

# 配置重试
git config --global http.maxRetries 3
git config --global http.retryDelay 1000

常见问题

Q1: 如何验证 Git 加速是否生效?

A: 使用 time 命令测量操作时间:

1
2
3
4
5
# 测试 clone 速度
time git clone https://xget.xi-xu.me/gh/user/repo.git

# 测试 fetch 速度
time git fetch origin

Q2: Git LFS 如何使用 Xget 加速?

A: 配置 LFS 使用 Xget:

1
2
git config lfs.url https://xget.xi-xu.me/gh/user/repo.git/info/lfs
git lfs fetch

Q3: 如何处理 Git 认证问题?

A: 使用 Git 凭据存储:

1
2
3
4
5
# 配置凭据存储
git config --global credential.helper store

# 输入凭据
git push

Q4: Xget 支持哪些 Git 操作?

A: Xget 支持所有 Git 操作,包括 clone、fetch、pull、push、LFS 等。

Q5: 如何切换回原始 Git URL?

A: 移除 Git 配置:

1
git config --global --unset url."https://xget.xi-xu.me/gh/".insteadOf

总结

Xget 提供了全面的 Git 协议支持,包括 HTTP/HTTPS、SSH、Git 协议等各种传输协议。通过 URL 转换、请求代理、响应缓存等技术,Xget 显著提升了 Git 操作的速度和稳定性。

同时,Xget 对 Git LFS、Submodule 等高级功能也提供了完善的支持,确保开发者能够享受到完整的 Git 加速体验。


文章作者: ZeroXin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ZeroXin !
评论
  目录