euler314 commited on
Commit
22e3009
·
verified ·
1 Parent(s): 297d891

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +57 -38
  2. requirements.txt +0 -1
app.py CHANGED
@@ -1,9 +1,9 @@
1
  import os
2
  import time
3
 
4
- from fastapi import FastAPI, Request
5
- from fastapi.responses import JSONResponse, Response
6
  import gradio as gr
 
 
7
 
8
  DOWNLOAD_SIZE_BYTES = 10 * 1024 * 1024
9
  _RANDOM_BLOB = os.urandom(DOWNLOAD_SIZE_BYTES)
@@ -14,33 +14,42 @@ NO_CACHE_HEADERS = {
14
  "Expires": "0",
15
  }
16
 
17
- fastapi_app = FastAPI()
18
 
 
 
 
 
 
19
 
20
- @fastapi_app.get("/ping_test")
21
- async def ping_test() -> Response:
22
- headers = {**NO_CACHE_HEADERS, "Content-Length": "4", "X-Server-Timestamp": str(time.time())}
23
- return Response(content="pong", media_type="text/plain", headers=headers)
24
 
 
25
 
26
- @fastapi_app.get("/download_test")
27
- async def download_test() -> Response:
28
- headers = {
29
- **NO_CACHE_HEADERS,
30
- "Content-Length": str(DOWNLOAD_SIZE_BYTES),
31
- "Content-Disposition": f'attachment; filename="speedtest_{DOWNLOAD_SIZE_BYTES}.bin"',
32
- }
33
- return Response(content=_RANDOM_BLOB, media_type="application/octet-stream", headers=headers)
 
 
 
34
 
 
 
 
 
35
 
36
- @fastapi_app.post("/upload_test")
37
- async def upload_test(request: Request) -> JSONResponse:
38
- payload = await request.body()
39
- headers = dict(NO_CACHE_HEADERS)
40
- return JSONResponse({"received_bytes": len(payload)}, headers=headers)
41
 
42
 
43
- LIBRESPEED_HTML = """
 
44
  <style>
45
  .speedtest-container {
46
  font-family: 'Segoe UI', Arial, sans-serif;
@@ -105,17 +114,17 @@ LIBRESPEED_HTML = """
105
  <div class="speedtest-grid">
106
  <div class="metric-card">
107
  <span class="metric-label">Download</span>
108
- <span id="dlSpeed" class="metric-value"></span>
109
  <div class="metric-subtext">Average throughput in Mbps</div>
110
  </div>
111
  <div class="metric-card">
112
  <span class="metric-label">Upload</span>
113
- <span id="ulSpeed" class="metric-value"></span>
114
  <div class="metric-subtext">Average throughput in Mbps</div>
115
  </div>
116
  <div class="metric-card">
117
  <span class="metric-label">Ping</span>
118
- <span id="ping" class="metric-value"></span>
119
  <div class="metric-subtext">Round-trip latency in ms</div>
120
  </div>
121
  </div>
@@ -132,7 +141,8 @@ LIBRESPEED_HTML = """
132
 
133
  function log(message) {
134
  const timestamp = new Date().toLocaleTimeString();
135
- logView.textContent += '[' + timestamp + '] ' + message + '\n';
 
136
  logView.scrollTop = logView.scrollHeight;
137
  }
138
 
@@ -197,25 +207,25 @@ LIBRESPEED_HTML = """
197
  startBtn.addEventListener('click', async () => {
198
  startBtn.disabled = true;
199
  resultsDiv.style.display = 'block';
200
- dlSpan.textContent = 'Testing';
201
- ulSpan.textContent = 'Testing';
202
- pingSpan.textContent = 'Testing';
203
  logView.textContent = '';
204
 
205
  try {
206
- log('Measuring ping');
207
  const pingMs = await measurePing();
208
  pingSpan.textContent = pingMs.toFixed(2) + ' ms';
209
  log('Average ping: ' + pingSpan.textContent);
210
 
211
- log('Running download test (10 MiB)');
212
  const downloadResult = await measureDownload();
213
  const downloadBps = downloadResult.bitsTransferred / downloadResult.durationSeconds;
214
  dlSpan.textContent = formatMbps(downloadBps);
215
  log('Download duration: ' + downloadResult.durationSeconds.toFixed(2) + ' s');
216
  log('Download speed: ' + dlSpan.textContent);
217
 
218
- log('Running upload test (10 MiB)');
219
  const uploadResult = await measureUpload(downloadResult.bitsTransferred / 8);
220
  const uploadBps = uploadResult.bitsTransferred / uploadResult.durationSeconds;
221
  ulSpan.textContent = formatMbps(uploadBps);
@@ -235,14 +245,23 @@ LIBRESPEED_HTML = """
235
  }
236
  });
237
  </script>
238
- """
239
 
240
- with gr.Blocks(fill_height=True) as demo:
241
- gr.HTML(value=LIBRESPEED_HTML)
242
 
243
- app = gr.mount_gradio_app(fastapi_app, demo, path="/")
 
244
 
245
- if __name__ == "__main__":
246
- import uvicorn
247
 
248
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import time
3
 
 
 
4
  import gradio as gr
5
+ from starlette.requests import Request
6
+ from starlette.responses import JSONResponse, Response
7
 
8
  DOWNLOAD_SIZE_BYTES = 10 * 1024 * 1024
9
  _RANDOM_BLOB = os.urandom(DOWNLOAD_SIZE_BYTES)
 
14
  "Expires": "0",
15
  }
16
 
 
17
 
18
+ def register_backend_routes(blocks: gr.Blocks) -> None:
19
+ """Attach REST endpoints to the underlying Gradio server once it exists."""
20
+ server_app = getattr(blocks, "server_app", None)
21
+ if server_app is None:
22
+ return
23
 
24
+ if getattr(server_app.state, "speedtest_routes_installed", False):
25
+ return
 
 
26
 
27
+ server_app.state.speedtest_routes_installed = True
28
 
29
+ async def ping_test() -> Response:
30
+ headers = {**NO_CACHE_HEADERS, "Content-Length": "4", "X-Server-Timestamp": str(time.time())}
31
+ return Response(content="pong", media_type="text/plain", headers=headers)
32
+
33
+ async def download_test() -> Response:
34
+ headers = {
35
+ **NO_CACHE_HEADERS,
36
+ "Content-Length": str(DOWNLOAD_SIZE_BYTES),
37
+ "Content-Disposition": f'attachment; filename="speedtest_{DOWNLOAD_SIZE_BYTES}.bin"',
38
+ }
39
+ return Response(content=_RANDOM_BLOB, media_type="application/octet-stream", headers=headers)
40
 
41
+ async def upload_test(request: Request) -> JSONResponse:
42
+ payload = await request.body()
43
+ headers = dict(NO_CACHE_HEADERS)
44
+ return JSONResponse({"received_bytes": len(payload)}, headers=headers)
45
 
46
+ server_app.add_api_route("/ping_test", ping_test, methods=["GET"])
47
+ server_app.add_api_route("/download_test", download_test, methods=["GET"])
48
+ server_app.add_api_route("/upload_test", upload_test, methods=["POST"])
 
 
49
 
50
 
51
+ with gr.Blocks(fill_height=True) as demo:
52
+ gr.HTML(value="""
53
  <style>
54
  .speedtest-container {
55
  font-family: 'Segoe UI', Arial, sans-serif;
 
114
  <div class="speedtest-grid">
115
  <div class="metric-card">
116
  <span class="metric-label">Download</span>
117
+ <span id="dlSpeed" class="metric-value">-</span>
118
  <div class="metric-subtext">Average throughput in Mbps</div>
119
  </div>
120
  <div class="metric-card">
121
  <span class="metric-label">Upload</span>
122
+ <span id="ulSpeed" class="metric-value">-</span>
123
  <div class="metric-subtext">Average throughput in Mbps</div>
124
  </div>
125
  <div class="metric-card">
126
  <span class="metric-label">Ping</span>
127
+ <span id="ping" class="metric-value">-</span>
128
  <div class="metric-subtext">Round-trip latency in ms</div>
129
  </div>
130
  </div>
 
141
 
142
  function log(message) {
143
  const timestamp = new Date().toLocaleTimeString();
144
+ logView.textContent += '[' + timestamp + '] ' + message + '
145
+ ';
146
  logView.scrollTop = logView.scrollHeight;
147
  }
148
 
 
207
  startBtn.addEventListener('click', async () => {
208
  startBtn.disabled = true;
209
  resultsDiv.style.display = 'block';
210
+ dlSpan.textContent = 'Testing...';
211
+ ulSpan.textContent = 'Testing...';
212
+ pingSpan.textContent = 'Testing...';
213
  logView.textContent = '';
214
 
215
  try {
216
+ log('Measuring ping...');
217
  const pingMs = await measurePing();
218
  pingSpan.textContent = pingMs.toFixed(2) + ' ms';
219
  log('Average ping: ' + pingSpan.textContent);
220
 
221
+ log('Running download test (10 MiB)...');
222
  const downloadResult = await measureDownload();
223
  const downloadBps = downloadResult.bitsTransferred / downloadResult.durationSeconds;
224
  dlSpan.textContent = formatMbps(downloadBps);
225
  log('Download duration: ' + downloadResult.durationSeconds.toFixed(2) + ' s');
226
  log('Download speed: ' + dlSpan.textContent);
227
 
228
+ log('Running upload test (10 MiB)...');
229
  const uploadResult = await measureUpload(downloadResult.bitsTransferred / 8);
230
  const uploadBps = uploadResult.bitsTransferred / uploadResult.durationSeconds;
231
  ulSpan.textContent = formatMbps(uploadBps);
 
245
  }
246
  });
247
  </script>
248
+ """)
249
 
 
 
250
 
251
+ def _ensure_routes() -> None:
252
+ register_backend_routes(demo)
253
 
 
 
254
 
255
+ demo.load(fn=_ensure_routes, inputs=None, outputs=None)
256
+
257
+
258
+ def build_app() -> gr.Blocks:
259
+ register_backend_routes(demo)
260
+ return demo
261
+
262
+
263
+ app = build_app()
264
+
265
+
266
+ if __name__ == "__main__":
267
+ app.queue(concurrency_count=10).launch(server_name="0.0.0.0", server_port=7860)
requirements.txt CHANGED
@@ -1,3 +1,2 @@
1
  # requirements.txt
2
  gradio==5.33.0
3
- uvicorn[standard]==0.30.1
 
1
  # requirements.txt
2
  gradio==5.33.0