A Vue-powered speed test service for Alibaba Cloud ESA edge functions, packaged as a single JavaScript deployment file with build-time token protection.
ESA Edge Speed is a browser and app-facing network speed test server for Alibaba Cloud ESA / EdgeRoutine. It provides latency, jitter, one-shot download, continuous multi-connection flow testing, and optional upload testing through one edge function.
The frontend is Vue. The backend is JavaScript. The deployable edge artifact is generated as a single file: dist-edge/edge.js.
Recommended repository description:
Single-file Alibaba Cloud ESA edge speed test server with Vue UI, app APIs, streaming download, flow testing, upload testing, and build-time token protection.
Recommended topics:
aliyun-esa, edge-function, edgeroutine, speedtest, network-testing, vue3, vite, single-file-js, app-api, token-protection
- Browser speed test UI with latency, jitter, one-shot download, flow testing, parallel streams, and optional upload.
- Flow testing supports up to 64 browser-side streams, unlimited duration, manual stop, and optional traffic caps.
- App-ready
/api/*endpoints for native apps, WebView, mini programs, and monitoring probes. - Single-file edge backend in edge/speedtest-edge.js.
- Single-file ESA deploy output generated by
npm run build:edge. - Build-time token injection for ESA environments where runtime environment variables are unavailable.
- Streaming binary responses via
ReadableStreamto avoid large memory allocation. no-storeandno-transformresponse headers to keep speed test traffic from being cached or compressed.- CORS allowlist, request size limits, upload limits, and constant-time token comparison.
Client browser or App
|
| HTTPS
v
Alibaba Cloud ESA edge node
|
| single JavaScript function
v
edge/speedtest-edge.js
|
+-- Vue static assets
+-- /api/config
+-- /api/ping
+-- /api/download
+-- /api/flow
+-- /api/upload
.
├── edge/speedtest-edge.js # ESA edge function source
├── src/ # Vue frontend
├── tools/local-edge.mjs # Local fetch-handler simulator
├── tools/inline-static.mjs # Inlines Vue dist into one edge file
├── tools/privacy-scan.mjs # Public-repo safety scan
├── tools/smoke-test.mjs # API smoke test
├── APP_INTEGRATION.md # App integration protocol
├── SECURITY.md # Token and public-repo safety notes
└── dist-edge/edge.js # Generated deploy artifact, ignored by git
npm install
npm run devLocal services:
- Vue frontend:
http://127.0.0.1:5173 - Local edge API simulator:
http://127.0.0.1:8787
Vite proxies /api/* to the local edge simulator.
npm run build:edgeUpload dist-edge/edge.js to ESA Functions / EdgeRoutine and bind the target route or domain to that function.
Important: dist-edge/edge.js may contain build-time access tokens. It is a deploy artifact only. Do not commit it to a public repository. This repo ignores dist/ and dist-edge/.
For ESA GitHub-connected builds, use:
| Field | Value |
|---|---|
| Install command | npm install |
| Build command | npm run build:edge |
| Root directory | / |
| Static resource directory | /dist |
| Function file path | /dist-edge/edge.js |
| Node.js version | 22.x |
Do not set the function file path to /edge/speedtest-edge.js for production builds. That source file is valid code, but it does not contain build-time injected tokens. The generated /dist-edge/edge.js file contains the ESA module entry and the build-time token config.
ESA functions cannot read runtime environment variables in this deployment model, so access tokens are injected at build time by tools/inline-static.mjs.
Recommended token format:
- At least 32 characters.
- Prefer 32 random bytes encoded as base64url, usually 43 characters.
- No whitespace.
- No placeholder text such as
example,replace,secret,password, ortoken. - Never use a
VITE_prefix for private tokens. Vite exposesVITE_variables to frontend code.
Generate a token:
openssl rand -base64 32 | tr '+/' '-_' | tr -d '='Build with one token:
SPEEDTEST_TOKEN='<base64url-random-43-chars-or-longer>' npm run build:edgeBuild with multiple tokens for app key rotation:
SPEEDTEST_TOKENS='<token-a>,<token-b>' npm run build:edgeRestrict CORS origins during build:
SPEEDTEST_TOKEN='<base64url-random-43-chars-or-longer>' \
SPEEDTEST_ALLOWED_ORIGINS='https://speed.example.com,https://app.example.com' \
npm run build:edge| Method | Path | Purpose | Auth |
|---|---|---|---|
GET |
/api/config |
Public limits and edge metadata | No |
GET |
/api/health |
Health check | No |
GET |
/api/ping |
Latency and jitter sampling | Yes, when token is enabled |
GET |
/api/download?bytes=67108864 |
One-shot download speed test | Yes, when token is enabled |
GET |
/api/flow?bytes=1073741824 |
Continuous flow test, client cancels by time, traffic cap, or manual stop | Yes, when token is enabled |
POST |
/api/upload |
Upload speed test | Yes, when token is enabled |
App integration details are in APP_INTEGRATION.md.
The default limits live in edge/speedtest-edge.js. Do not write real tokens into source code.
const DEFAULT_CONFIG = {
allowedOrigins: ["*"],
defaultSingleBytes: 64 * 1024 * 1024,
maxDownloadBytes: 512 * 1024 * 1024,
maxFlowBytes: 1024 * 1024 * 1024,
maxUploadBytes: 64 * 1024 * 1024,
maxParallel: 64
};Production recommendations:
- Set
SPEEDTEST_TOKENorSPEEDTEST_TOKENSduring build. - Put the same token in app requests via
X-Speedtest-Token. - Set
SPEEDTEST_ALLOWED_ORIGINSto your production domain and app WebView origins. - Exclude
/api/downloadand/api/flowfrom platform compression and caching rules. - Rotate tokens by building once with both old and new tokens, shipping the app update, then rebuilding with only the new token.
Build and generate the ESA deploy file:
npm run build:edgeRun the local API simulator:
npm run dev:apiRun API smoke tests:
npm run test:smokeRun the public repository safety scan:
npm run scan:privacyAlibaba Cloud documentation describes ESA functions as an edge JavaScript runtime that supports ES6 and standard Web Service Worker APIs. The examples use addEventListener("fetch", ...) and new Response(...). The documented constraints include a 120-second function response time, a 10-second first-byte gateway wait, and a 4 MB single JavaScript file limit. This project uses streaming responses and checks the generated file size during build.
References:
MIT