CatPtain commited on
Commit
4f43bf9
·
verified ·
1 Parent(s): 557d451

Upload 4 files

Browse files
Files changed (2) hide show
  1. hf-test.html +473 -0
  2. test-hf-api.sh +191 -0
hf-test.html ADDED
@@ -0,0 +1,473 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>HF Spaces Screenshot API 测试</title>
7
+ <style>
8
+ body {
9
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
10
+ max-width: 1000px;
11
+ margin: 0 auto;
12
+ padding: 20px;
13
+ background: #f5f5f5;
14
+ }
15
+ .container {
16
+ background: white;
17
+ padding: 30px;
18
+ border-radius: 12px;
19
+ box-shadow: 0 2px 20px rgba(0,0,0,0.1);
20
+ }
21
+ h1 {
22
+ color: #2c3e50;
23
+ text-align: center;
24
+ margin-bottom: 30px;
25
+ }
26
+ .form-group {
27
+ margin: 20px 0;
28
+ }
29
+ label {
30
+ display: block;
31
+ margin-bottom: 8px;
32
+ font-weight: 600;
33
+ color: #333;
34
+ }
35
+ input, textarea, select {
36
+ width: 100%;
37
+ padding: 12px;
38
+ border: 2px solid #e1e8ed;
39
+ border-radius: 8px;
40
+ font-size: 14px;
41
+ transition: border-color 0.3s;
42
+ }
43
+ input:focus, textarea:focus, select:focus {
44
+ outline: none;
45
+ border-color: #3498db;
46
+ }
47
+ .input-row {
48
+ display: grid;
49
+ grid-template-columns: 1fr 1fr 1fr;
50
+ gap: 15px;
51
+ }
52
+ button {
53
+ background: linear-gradient(135deg, #3498db, #2980b9);
54
+ color: white;
55
+ border: none;
56
+ padding: 15px 30px;
57
+ border-radius: 8px;
58
+ cursor: pointer;
59
+ font-size: 16px;
60
+ font-weight: 600;
61
+ margin: 10px 5px;
62
+ transition: all 0.3s;
63
+ }
64
+ button:hover {
65
+ transform: translateY(-2px);
66
+ box-shadow: 0 5px 15px rgba(52, 152, 219, 0.4);
67
+ }
68
+ button:disabled {
69
+ background: #bdc3c7;
70
+ cursor: not-allowed;
71
+ transform: none;
72
+ box-shadow: none;
73
+ }
74
+ .test-btn {
75
+ background: linear-gradient(135deg, #27ae60, #229954);
76
+ }
77
+ .health-btn {
78
+ background: linear-gradient(135deg, #e74c3c, #c0392b);
79
+ }
80
+ #result {
81
+ margin-top: 30px;
82
+ padding: 20px;
83
+ border-radius: 8px;
84
+ border-left: 4px solid #3498db;
85
+ background: #f8f9fa;
86
+ }
87
+ .loading {
88
+ color: #f39c12;
89
+ font-style: italic;
90
+ }
91
+ .error {
92
+ color: #e74c3c;
93
+ background: #fdf2f2;
94
+ border-left-color: #e74c3c;
95
+ }
96
+ .success {
97
+ color: #27ae60;
98
+ background: #f0f9f4;
99
+ border-left-color: #27ae60;
100
+ }
101
+ .screenshot-result img {
102
+ max-width: 100%;
103
+ border: 2px solid #e1e8ed;
104
+ border-radius: 8px;
105
+ margin-top: 15px;
106
+ }
107
+ .stats {
108
+ display: grid;
109
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
110
+ gap: 15px;
111
+ margin: 20px 0;
112
+ }
113
+ .stat-card {
114
+ background: white;
115
+ padding: 15px;
116
+ border-radius: 8px;
117
+ border: 1px solid #e1e8ed;
118
+ text-align: center;
119
+ }
120
+ .stat-value {
121
+ font-size: 24px;
122
+ font-weight: bold;
123
+ color: #2c3e50;
124
+ }
125
+ .stat-label {
126
+ color: #7f8c8d;
127
+ font-size: 12px;
128
+ margin-top: 5px;
129
+ }
130
+ pre {
131
+ background: #2c3e50;
132
+ color: #ecf0f1;
133
+ padding: 15px;
134
+ border-radius: 8px;
135
+ overflow-x: auto;
136
+ font-size: 12px;
137
+ }
138
+ .example-urls {
139
+ display: grid;
140
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
141
+ gap: 10px;
142
+ margin: 15px 0;
143
+ }
144
+ .example-url {
145
+ background: #ecf0f1;
146
+ padding: 8px 12px;
147
+ border-radius: 6px;
148
+ cursor: pointer;
149
+ font-size: 12px;
150
+ text-align: center;
151
+ transition: background 0.3s;
152
+ }
153
+ .example-url:hover {
154
+ background: #d5dbdb;
155
+ }
156
+ </style>
157
+ </head>
158
+ <body>
159
+ <div class="container">
160
+ <h1>📸 Hugging Face Spaces Screenshot API 测试工具</h1>
161
+
162
+ <div class="form-group">
163
+ <label for="spaceUrl">🚀 Hugging Face Space URL:</label>
164
+ <input type="text" id="spaceUrl"
165
+ placeholder="https://your-username-your-space-name.hf.space"
166
+ value="">
167
+ <small style="color: #7f8c8d;">请输入你的 HF Space 完整地址</small>
168
+ </div>
169
+
170
+ <div class="form-group">
171
+ <label for="authToken">🔐 认证 Token (可选):</label>
172
+ <input type="password" id="authToken"
173
+ placeholder="hf_your_token_here 或自定义 API key">
174
+ <small style="color: #7f8c8d;">私有 Space 需要 HF token,或使用自定义 API key</small>
175
+ </div>
176
+
177
+ <div class="form-group">
178
+ <label for="targetUrl">🌐 要截图的网址:</label>
179
+ <input type="text" id="targetUrl" value="https://www.baidu.com">
180
+
181
+ <div class="example-urls">
182
+ <div class="example-url" onclick="setUrl('https://www.baidu.com')">百度</div>
183
+ <div class="example-url" onclick="setUrl('https://www.google.com')">Google</div>
184
+ <div class="example-url" onclick="setUrl('https://github.com')">GitHub</div>
185
+ <div class="example-url" onclick="setUrl('https://huggingface.co')">HuggingFace</div>
186
+ <div class="example-url" onclick="setUrl('https://www.wikipedia.org')">Wikipedia</div>
187
+ <div class="example-url" onclick="setUrl('https://stackoverflow.com')">Stack Overflow</div>
188
+ </div>
189
+ </div>
190
+
191
+ <div class="input-row">
192
+ <div class="form-group">
193
+ <label for="width">📐 宽度 (px):</label>
194
+ <input type="number" id="width" value="1280" min="100" max="1600">
195
+ </div>
196
+ <div class="form-group">
197
+ <label for="height">📏 高度 (px):</label>
198
+ <input type="number" id="height" value="720" min="100" max="1200">
199
+ </div>
200
+ <div class="form-group">
201
+ <label for="quality">🎯 质量 (%):</label>
202
+ <input type="number" id="quality" value="75" min="10" max="100">
203
+ </div>
204
+ </div>
205
+
206
+ <div style="text-align: center; margin: 30px 0;">
207
+ <button onclick="testHealth()" class="health-btn">🔍 健康检查</button>
208
+ <button onclick="testStatus()" class="test-btn">📊 状态检查</button>
209
+ <button onclick="takeScreenshot()" id="screenshotBtn">📸 截图测试</button>
210
+ </div>
211
+
212
+ <div id="result"></div>
213
+ </div>
214
+
215
+ <script>
216
+ function setUrl(url) {
217
+ document.getElementById('targetUrl').value = url;
218
+ }
219
+
220
+ function getHeaders() {
221
+ const token = document.getElementById('authToken').value.trim();
222
+ const headers = {
223
+ 'Content-Type': 'application/json'
224
+ };
225
+
226
+ if (token) {
227
+ if (token.startsWith('hf_')) {
228
+ headers['Authorization'] = `Bearer ${token}`;
229
+ } else {
230
+ headers['X-API-Key'] = token;
231
+ }
232
+ }
233
+
234
+ return headers;
235
+ }
236
+
237
+ function getBaseUrl() {
238
+ const spaceUrl = document.getElementById('spaceUrl').value.trim();
239
+ if (!spaceUrl) {
240
+ alert('请先输入 Hugging Face Space URL');
241
+ return null;
242
+ }
243
+ return spaceUrl.endsWith('/') ? spaceUrl.slice(0, -1) : spaceUrl;
244
+ }
245
+
246
+ async function testHealth() {
247
+ const baseUrl = getBaseUrl();
248
+ if (!baseUrl) return;
249
+
250
+ document.getElementById('result').innerHTML = '<p class="loading">🔍 正在检查健康状态...</p>';
251
+
252
+ try {
253
+ const response = await fetch(`${baseUrl}/`, {
254
+ headers: getHeaders()
255
+ });
256
+
257
+ if (response.ok) {
258
+ const data = await response.json();
259
+ document.getElementById('result').innerHTML = `
260
+ <div class="success">
261
+ <h3>✅ 健康检查成功</h3>
262
+ <div class="stats">
263
+ <div class="stat-card">
264
+ <div class="stat-value">${data.version}</div>
265
+ <div class="stat-label">版本</div>
266
+ </div>
267
+ <div class="stat-card">
268
+ <div class="stat-value">${data.platform}</div>
269
+ <div class="stat-label">平台</div>
270
+ </div>
271
+ <div class="stat-card">
272
+ <div class="stat-value">${data.status}</div>
273
+ <div class="stat-label">状态</div>
274
+ </div>
275
+ </div>
276
+ <details>
277
+ <summary style="cursor: pointer; margin: 10px 0;">📋 详细信息</summary>
278
+ <pre>${JSON.stringify(data, null, 2)}</pre>
279
+ </details>
280
+ </div>
281
+ `;
282
+ } else {
283
+ const error = await response.text();
284
+ document.getElementById('result').innerHTML = `
285
+ <div class="error">
286
+ <h3>❌ 健康检查失败</h3>
287
+ <p>状态码: ${response.status}</p>
288
+ <p>错误信息: ${error}</p>
289
+ </div>
290
+ `;
291
+ }
292
+ } catch (error) {
293
+ document.getElementById('result').innerHTML = `
294
+ <div class="error">
295
+ <h3>❌ 连接失败</h3>
296
+ <p>请检查 Space URL 是否正确</p>
297
+ <p>错误: ${error.message}</p>
298
+ </div>
299
+ `;
300
+ }
301
+ }
302
+
303
+ async function testStatus() {
304
+ const baseUrl = getBaseUrl();
305
+ if (!baseUrl) return;
306
+
307
+ document.getElementById('result').innerHTML = '<p class="loading">📊 正在获取状态信息...</p>';
308
+
309
+ try {
310
+ const response = await fetch(`${baseUrl}/status`, {
311
+ headers: getHeaders()
312
+ });
313
+
314
+ if (response.ok) {
315
+ const data = await response.json();
316
+ document.getElementById('result').innerHTML = `
317
+ <div class="success">
318
+ <h3>📊 系统状态</h3>
319
+ <div class="stats">
320
+ <div class="stat-card">
321
+ <div class="stat-value">${data.system?.cpuUsage || 'N/A'}</div>
322
+ <div class="stat-label">CPU 使用率</div>
323
+ </div>
324
+ <div class="stat-card">
325
+ <div class="stat-value">${data.system?.uptime || 'N/A'}</div>
326
+ <div class="stat-label">运行时间</div>
327
+ </div>
328
+ <div class="stat-card">
329
+ <div class="stat-value">${data.queue?.activeRequests || 0}</div>
330
+ <div class="stat-label">活跃请求</div>
331
+ </div>
332
+ <div class="stat-card">
333
+ <div class="stat-value">${data.queue?.maxConcurrent || 3}</div>
334
+ <div class="stat-label">最大并发</div>
335
+ </div>
336
+ </div>
337
+ <details>
338
+ <summary style="cursor: pointer; margin: 10px 0;">📋 完整状态</summary>
339
+ <pre>${JSON.stringify(data, null, 2)}</pre>
340
+ </details>
341
+ </div>
342
+ `;
343
+ } else {
344
+ const error = await response.text();
345
+ document.getElementById('result').innerHTML = `
346
+ <div class="error">
347
+ <h3>❌ 状态检查失败</h3>
348
+ <p>状态码: ${response.status}</p>
349
+ <p>错误信息: ${error}</p>
350
+ </div>
351
+ `;
352
+ }
353
+ } catch (error) {
354
+ document.getElementById('result').innerHTML = `
355
+ <div class="error">
356
+ <h3>❌ 连接失败</h3>
357
+ <p>错误: ${error.message}</p>
358
+ </div>
359
+ `;
360
+ }
361
+ }
362
+
363
+ async function takeScreenshot() {
364
+ const baseUrl = getBaseUrl();
365
+ if (!baseUrl) return;
366
+
367
+ const url = document.getElementById('targetUrl').value.trim();
368
+ const width = parseInt(document.getElementById('width').value);
369
+ const height = parseInt(document.getElementById('height').value);
370
+ const quality = parseInt(document.getElementById('quality').value);
371
+
372
+ if (!url) {
373
+ alert('请输入要截图的网址');
374
+ return;
375
+ }
376
+
377
+ const btn = document.getElementById('screenshotBtn');
378
+ btn.disabled = true;
379
+ btn.textContent = '📸 截图中...';
380
+
381
+ document.getElementById('result').innerHTML = '<p class="loading">📸 正在生成截图,请稍候...</p>';
382
+
383
+ const startTime = Date.now();
384
+
385
+ try {
386
+ const response = await fetch(`${baseUrl}/screenshot`, {
387
+ method: 'POST',
388
+ headers: getHeaders(),
389
+ body: JSON.stringify({ url, width, height, quality })
390
+ });
391
+
392
+ const endTime = Date.now();
393
+ const duration = ((endTime - startTime) / 1000).toFixed(2);
394
+
395
+ if (response.ok) {
396
+ const blob = await response.blob();
397
+ const imageUrl = URL.createObjectURL(blob);
398
+ const size = (blob.size / 1024).toFixed(1);
399
+
400
+ document.getElementById('result').innerHTML = `
401
+ <div class="success screenshot-result">
402
+ <h3>✅ 截图成功!</h3>
403
+ <div class="stats">
404
+ <div class="stat-card">
405
+ <div class="stat-value">${size} KB</div>
406
+ <div class="stat-label">文件大小</div>
407
+ </div>
408
+ <div class="stat-card">
409
+ <div class="stat-value">${width}×${height}</div>
410
+ <div class="stat-label">尺寸</div>
411
+ </div>
412
+ <div class="stat-card">
413
+ <div class="stat-value">${quality}%</div>
414
+ <div class="stat-label">质量</div>
415
+ </div>
416
+ <div class="stat-card">
417
+ <div class="stat-value">${duration}s</div>
418
+ <div class="stat-label">耗时</div>
419
+ </div>
420
+ </div>
421
+ <p>目标网址: <a href="${url}" target="_blank">${url}</a></p>
422
+ <img src="${imageUrl}" alt="Screenshot" loading="lazy">
423
+ <div style="margin-top: 15px;">
424
+ <a href="${imageUrl}" download="screenshot.jpg"
425
+ style="background: #27ae60; color: white; padding: 10px 20px; text-decoration: none; border-radius: 6px;">
426
+ 💾 下载图片
427
+ </a>
428
+ </div>
429
+ </div>
430
+ `;
431
+ } else {
432
+ const error = await response.json();
433
+ document.getElementById('result').innerHTML = `
434
+ <div class="error">
435
+ <h3>❌ 截图失败</h3>
436
+ <p><strong>状态码:</strong> ${response.status}</p>
437
+ <p><strong>错误类型:</strong> ${error.error || '未知错误'}</p>
438
+ <p><strong>错误信息:</strong> ${error.message || '无详细信息'}</p>
439
+ <p><strong>耗时:</strong> ${duration}s</p>
440
+ ${error.cpuUsage ? `<p><strong>CPU使用率:</strong> ${error.cpuUsage}</p>` : ''}
441
+ ${error.activeRequests ? `<p><strong>活跃请求:</strong> ${error.activeRequests}</p>` : ''}
442
+ </div>
443
+ `;
444
+ }
445
+ } catch (error) {
446
+ const endTime = Date.now();
447
+ const duration = ((endTime - startTime) / 1000).toFixed(2);
448
+
449
+ document.getElementById('result').innerHTML = `
450
+ <div class="error">
451
+ <h3>❌ 网络错误</h3>
452
+ <p><strong>错误:</strong> ${error.message}</p>
453
+ <p><strong>耗时:</strong> ${duration}s</p>
454
+ <p>请检查网络连接和 Space 状态</p>
455
+ </div>
456
+ `;
457
+ } finally {
458
+ btn.disabled = false;
459
+ btn.textContent = '📸 截图测试';
460
+ }
461
+ }
462
+
463
+ // 页面加载时尝试从 URL 获取 Space 地址
464
+ window.onload = function() {
465
+ const urlParams = new URLSearchParams(window.location.search);
466
+ const spaceUrl = urlParams.get('space');
467
+ if (spaceUrl) {
468
+ document.getElementById('spaceUrl').value = spaceUrl;
469
+ }
470
+ };
471
+ </script>
472
+ </body>
473
+ </html>
test-hf-api.sh ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # HF Spaces Screenshot API 测试脚本
4
+ # 使用方法: ./test-hf-api.sh [SPACE_URL] [HF_TOKEN]
5
+
6
+ # 配置
7
+ SPACE_URL="${1:-https://your-username-your-space-name.hf.space}"
8
+ HF_TOKEN="${2:-}"
9
+ TEST_URL="https://www.baidu.com"
10
+
11
+ # 颜色输出
12
+ RED='\033[0;31m'
13
+ GREEN='\033[0;32m'
14
+ YELLOW='\033[1;33m'
15
+ BLUE='\033[0;34m'
16
+ NC='\033[0m' # No Color
17
+
18
+ echo -e "${BLUE}🚀 HF Spaces Screenshot API 测试工具${NC}"
19
+ echo "======================================"
20
+ echo "Space URL: $SPACE_URL"
21
+ echo "Token: ${HF_TOKEN:+已设置}${HF_TOKEN:-未设置}"
22
+ echo ""
23
+
24
+ # 构建认证头
25
+ AUTH_HEADER=""
26
+ if [ ! -z "$HF_TOKEN" ]; then
27
+ if [[ $HF_TOKEN == hf_* ]]; then
28
+ AUTH_HEADER="Authorization: Bearer $HF_TOKEN"
29
+ echo -e "${GREEN}✅ 使用 HF Token 认证${NC}"
30
+ else
31
+ AUTH_HEADER="X-API-Key: $HF_TOKEN"
32
+ echo -e "${GREEN}✅ 使用自定义 API Key 认证${NC}"
33
+ fi
34
+ else
35
+ echo -e "${YELLOW}⚠️ 无认证信息,使用公开访问${NC}"
36
+ fi
37
+
38
+ echo ""
39
+
40
+ # 测试 1: 健康检查
41
+ echo -e "${BLUE}📋 测试 1: 健康检查${NC}"
42
+ echo "GET $SPACE_URL/"
43
+ echo ""
44
+
45
+ if [ ! -z "$AUTH_HEADER" ]; then
46
+ HEALTH_RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -H "$AUTH_HEADER" "$SPACE_URL/")
47
+ else
48
+ HEALTH_RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" "$SPACE_URL/")
49
+ fi
50
+
51
+ HTTP_CODE=$(echo "$HEALTH_RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
52
+ RESPONSE_BODY=$(echo "$HEALTH_RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')
53
+
54
+ if [ "$HTTP_CODE" -eq 200 ]; then
55
+ echo -e "${GREEN}✅ 健康检查成功 (HTTP $HTTP_CODE)${NC}"
56
+ echo "$RESPONSE_BODY" | python3 -m json.tool 2>/dev/null || echo "$RESPONSE_BODY"
57
+ else
58
+ echo -e "${RED}❌ 健康检查失败 (HTTP $HTTP_CODE)${NC}"
59
+ echo "$RESPONSE_BODY"
60
+ fi
61
+
62
+ echo ""
63
+ echo "======================================"
64
+
65
+ # 测试 2: 状态检查
66
+ echo -e "${BLUE}📊 测试 2: 状态检查${NC}"
67
+ echo "GET $SPACE_URL/status"
68
+ echo ""
69
+
70
+ if [ ! -z "$AUTH_HEADER" ]; then
71
+ STATUS_RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" -H "$AUTH_HEADER" "$SPACE_URL/status")
72
+ else
73
+ STATUS_RESPONSE=$(curl -s -w "HTTP_CODE:%{http_code}" "$SPACE_URL/status")
74
+ fi
75
+
76
+ HTTP_CODE=$(echo "$STATUS_RESPONSE" | grep -o "HTTP_CODE:[0-9]*" | cut -d: -f2)
77
+ RESPONSE_BODY=$(echo "$STATUS_RESPONSE" | sed 's/HTTP_CODE:[0-9]*$//')
78
+
79
+ if [ "$HTTP_CODE" -eq 200 ]; then
80
+ echo -e "${GREEN}✅ 状态检查成功 (HTTP $HTTP_CODE)${NC}"
81
+ echo "$RESPONSE_BODY" | python3 -m json.tool 2>/dev/null || echo "$RESPONSE_BODY"
82
+ else
83
+ echo -e "${RED}❌ 状态检查失败 (HTTP $HTTP_CODE)${NC}"
84
+ echo "$RESPONSE_BODY"
85
+ fi
86
+
87
+ echo ""
88
+ echo "======================================"
89
+
90
+ # 测试 3: 截图测试
91
+ echo -e "${BLUE}📸 测试 3: 截图测试${NC}"
92
+ echo "POST $SPACE_URL/screenshot"
93
+ echo "目标URL: $TEST_URL"
94
+ echo ""
95
+
96
+ # 准备请求数据
97
+ REQUEST_DATA='{
98
+ "url": "'$TEST_URL'",
99
+ "width": 1280,
100
+ "height": 720,
101
+ "quality": 75
102
+ }'
103
+
104
+ echo "请求数据:"
105
+ echo "$REQUEST_DATA" | python3 -m json.tool 2>/dev/null || echo "$REQUEST_DATA"
106
+ echo ""
107
+
108
+ # 执行截图请求
109
+ START_TIME=$(date +%s.%N)
110
+
111
+ if [ ! -z "$AUTH_HEADER" ]; then
112
+ curl -X POST "$SPACE_URL/screenshot" \
113
+ -H "Content-Type: application/json" \
114
+ -H "$AUTH_HEADER" \
115
+ -d "$REQUEST_DATA" \
116
+ -w "HTTP_CODE:%{http_code}\nTIME_TOTAL:%{time_total}s\nSIZE_DOWNLOAD:%{size_download} bytes\n" \
117
+ -o "test_screenshot_$(date +%s).jpg" \
118
+ -s > curl_output.tmp
119
+ else
120
+ curl -X POST "$SPACE_URL/screenshot" \
121
+ -H "Content-Type: application/json" \
122
+ -d "$REQUEST_DATA" \
123
+ -w "HTTP_CODE:%{http_code}\nTIME_TOTAL:%{time_total}s\nSIZE_DOWNLOAD:%{size_download} bytes\n" \
124
+ -o "test_screenshot_$(date +%s).jpg" \
125
+ -s > curl_output.tmp
126
+ fi
127
+
128
+ # 解析结果
129
+ HTTP_CODE=$(grep "HTTP_CODE:" curl_output.tmp | cut -d: -f2)
130
+ TIME_TOTAL=$(grep "TIME_TOTAL:" curl_output.tmp | cut -d: -f2)
131
+ SIZE_DOWNLOAD=$(grep "SIZE_DOWNLOAD:" curl_output.tmp | cut -d: -f2 | cut -d' ' -f1)
132
+
133
+ if [ "$HTTP_CODE" -eq 200 ]; then
134
+ echo -e "${GREEN}✅ 截图成功 (HTTP $HTTP_CODE)${NC}"
135
+ echo "⏱️ 响应时间: $TIME_TOTAL"
136
+ echo "📦 文件大小: $SIZE_DOWNLOAD bytes ($(echo "scale=1; $SIZE_DOWNLOAD/1024" | bc)KB)"
137
+ echo "💾 保存位置: test_screenshot_$(date +%s).jpg"
138
+
139
+ # 检查文件是否存在且大小合理
140
+ LATEST_FILE=$(ls -t test_screenshot_*.jpg 2>/dev/null | head -1)
141
+ if [ -f "$LATEST_FILE" ] && [ -s "$LATEST_FILE" ]; then
142
+ FILE_SIZE=$(stat -f%z "$LATEST_FILE" 2>/dev/null || stat -c%s "$LATEST_FILE" 2>/dev/null)
143
+ echo "✅ 文件验证通过,大小: ${FILE_SIZE} bytes"
144
+ else
145
+ echo -e "${YELLOW}⚠️ 文件可能损坏或为空${NC}"
146
+ fi
147
+ else
148
+ echo -e "${RED}❌ 截图失败 (HTTP $HTTP_CODE)${NC}"
149
+ # 显示错误信息
150
+ SCREENSHOT_FILE=$(ls -t test_screenshot_*.jpg 2>/dev/null | head -1)
151
+ if [ -f "$SCREENSHOT_FILE" ]; then
152
+ echo "错误信息:"
153
+ cat "$SCREENSHOT_FILE"
154
+ fi
155
+ fi
156
+
157
+ # 清理临时文件
158
+ rm -f curl_output.tmp
159
+
160
+ echo ""
161
+ echo "======================================"
162
+
163
+ # 测试总结
164
+ echo -e "${BLUE}📋 测试总结${NC}"
165
+ echo ""
166
+
167
+ if [ "$HTTP_CODE" -eq 200 ]; then
168
+ echo -e "${GREEN}🎉 所有测试通过!API 工作正常${NC}"
169
+ echo ""
170
+ echo "💡 使用建议:"
171
+ echo " - 可以在生产环境中使用此 API"
172
+ echo " - 建议设置适当的速率限制"
173
+ echo " - 监控服务器资源使用情况"
174
+
175
+ if [ -z "$HF_TOKEN" ]; then
176
+ echo ""
177
+ echo -e "${YELLOW}🔐 安全建议: 考虑将 Space 设为私有并使用 HF Token${NC}"
178
+ fi
179
+ else
180
+ echo -e "${RED}❌ 测试失败,请检查以下问题:${NC}"
181
+ echo " 1. Space URL 是否正确"
182
+ echo " 2. Space 是否正在运行"
183
+ echo " 3. 是否需要认证 token"
184
+ echo " 4. 网络连接是否正常"
185
+ fi
186
+
187
+ echo ""
188
+ echo "🔗 更多信息:"
189
+ echo " - Demo界面: $SPACE_URL/demo"
190
+ echo " - API文档: 查看 README.md"
191
+ echo " - 健康检查: $SPACE_URL/"