Repository navigation
Expand file tree
/
Copy path03_web_service.py
More file actions
72 lines (61 loc) · 2.68 KB
/
Copy path03_web_service.py
File metadata and controls
72 lines (61 loc) · 2.68 KB
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
"""Start a Node.js HTTP service and call it through the sandbox's public URL."""
import asyncio
import contextlib
import json
import httpx
from agent_sandbox import ProviderSandbox
APP = r"""
const http = require('node:http');
http.createServer((req, res) => {
const url = new URL(req.url, 'http://localhost');
res.setHeader('content-type', 'application/json');
if (url.pathname === '/health') res.end(JSON.stringify({status: 'ok'}));
else if (url.pathname === '/api/echo') {
res.end(JSON.stringify({query: Object.fromEntries(url.searchParams)}));
}
else res.end(JSON.stringify({message: 'Hello from Sandbox!', node_version: process.version}));
}).listen(3000, '0.0.0.0');
"""
async def main() -> None:
async with await ProviderSandbox.create(template="base", timeout=300) as sandbox:
await sandbox.files.write("/tmp/example-server.js", APP)
reader = await sandbox.commands.start("node /tmp/example-server.js", timeout=240)
async def drain() -> None:
async for _ in reader:
pass
task = asyncio.create_task(drain())
try:
for _ in range(40):
ready = await sandbox.commands.run(
"curl -fsS http://127.0.0.1:3000/health", timeout=5
)
if ready.exit_code == 0:
assert json.loads(ready.stdout) == {"status": "ok"}
break
await asyncio.sleep(0.25)
else:
raise RuntimeError("The Node.js service did not become ready")
# Gateway credentials remain in request headers, never in printed URLs/logs.
origin = sandbox.network.get_url(3000)
async with httpx.AsyncClient(
headers=sandbox.network.get_access_headers(), timeout=30
) as client:
response = await client.get(origin + "/")
response.raise_for_status()
assert response.json()["message"] == "Hello from Sandbox!"
response = await client.get(origin + "/health")
response.raise_for_status()
assert response.json() == {"status": "ok"}
response = await client.get(
origin + "/api/echo", params={"foo": "bar", "lang": "zh"}
)
response.raise_for_status()
assert response.json() == {"query": {"foo": "bar", "lang": "zh"}}
print("PASS: public HTTP greeting, health and query echo")
finally:
task.cancel()
with contextlib.suppress(asyncio.CancelledError):
await task
print("Sandbox destroyed")
if __name__ == "__main__":
asyncio.run(main())