|
1 | | -// 🌐 HTTP Server Creation Test - NO HANGING |
2 | | -// Tests HTTP server creation and immediate shutdown (no listening) |
| 1 | +// 🌐 Comprehensive HTTP API Test - All Methods |
| 2 | +// Tests real client-server communication with GET, POST, PUT, DELETE |
3 | 3 |
|
4 | 4 | print("=== Comprehensive HTTP API Test ===") |
5 | 5 |
|
6 | | -// Test HTTP server creation (without listening to avoid hanging) |
| 6 | +// Test HTTP server creation |
7 | 7 | print("Creating HTTP server on port 8080...") |
8 | 8 | let serverId = httpCreateServer(8080, "127.0.0.1") |
9 | 9 | print("Server created with ID: ${serverId}") |
10 | 10 |
|
11 | | -// DON'T call httpListen - it causes hanging! |
| 11 | +// Define HTTP request handler function - RESTORED TO ORIGINAL GLORY! |
| 12 | +// This function receives HTTP requests from the C runtime and returns HttpResponse |
| 13 | +fn handleHttpRequest(method: string, path: string, headers: string, body: string) -> HttpResponse = match method { |
| 14 | + "GET" => match path { |
| 15 | + "/api/users" => HttpResponse { |
| 16 | + status: 200, |
| 17 | + headers: "Content-Type: application/json", |
| 18 | + contentType: "application/json", |
| 19 | + streamFd: -1, |
| 20 | + isComplete: true, |
| 21 | + partialBody: "{\"users\": [{\"id\": 1, \"name\": \"Alice\"}, {\"id\": 2, \"name\": \"Bob\"}]}" |
| 22 | + } |
| 23 | + "/health" => HttpResponse { |
| 24 | + status: 200, |
| 25 | + headers: "Content-Type: application/json", |
| 26 | + contentType: "application/json", |
| 27 | + streamFd: -1, |
| 28 | + isComplete: true, |
| 29 | + partialBody: "{\"status\": \"ok\", \"timestamp\": \"2025-01-15T10:30:00Z\"}" |
| 30 | + } |
| 31 | + _ => HttpResponse { |
| 32 | + status: 404, |
| 33 | + headers: "Content-Type: application/json", |
| 34 | + contentType: "application/json", |
| 35 | + streamFd: -1, |
| 36 | + isComplete: true, |
| 37 | + partialBody: "{\"error\": \"Not found\"}" |
| 38 | + } |
| 39 | + } |
| 40 | + "POST" => match path { |
| 41 | + "/api/users" => HttpResponse { |
| 42 | + status: 201, |
| 43 | + headers: "Content-Type: application/json", |
| 44 | + contentType: "application/json", |
| 45 | + streamFd: -1, |
| 46 | + isComplete: true, |
| 47 | + partialBody: "{\"id\": 3, \"name\": \"New User\", \"message\": \"User created successfully\"}" |
| 48 | + } |
| 49 | + "/api/auth/login" => HttpResponse { |
| 50 | + status: 200, |
| 51 | + headers: "Content-Type: application/json", |
| 52 | + contentType: "application/json", |
| 53 | + streamFd: -1, |
| 54 | + isComplete: true, |
| 55 | + partialBody: "{\"token\": \"abc123xyz\", \"expires\": \"2025-01-16T10:30:00Z\"}" |
| 56 | + } |
| 57 | + _ => HttpResponse { |
| 58 | + status: 404, |
| 59 | + headers: "Content-Type: application/json", |
| 60 | + contentType: "application/json", |
| 61 | + streamFd: -1, |
| 62 | + isComplete: true, |
| 63 | + partialBody: "{\"error\": \"Not found\"}" |
| 64 | + } |
| 65 | + } |
| 66 | + "PUT" => match path { |
| 67 | + "/api/users/1" => HttpResponse { |
| 68 | + status: 200, |
| 69 | + headers: "Content-Type: application/json", |
| 70 | + contentType: "application/json", |
| 71 | + streamFd: -1, |
| 72 | + isComplete: true, |
| 73 | + partialBody: "{\"id\": 1, \"name\": \"Alice Updated\", \"message\": \"User updated successfully\"}" |
| 74 | + } |
| 75 | + _ => HttpResponse { |
| 76 | + status: 404, |
| 77 | + headers: "Content-Type: application/json", |
| 78 | + contentType: "application/json", |
| 79 | + streamFd: -1, |
| 80 | + isComplete: true, |
| 81 | + partialBody: "{\"error\": \"Not found\"}" |
| 82 | + } |
| 83 | + } |
| 84 | + "DELETE" => match path { |
| 85 | + "/api/users/1" => HttpResponse { |
| 86 | + status: 200, |
| 87 | + headers: "Content-Type: application/json", |
| 88 | + contentType: "application/json", |
| 89 | + streamFd: -1, |
| 90 | + isComplete: true, |
| 91 | + partialBody: "{\"message\": \"User deleted successfully\"}" |
| 92 | + } |
| 93 | + _ => HttpResponse { |
| 94 | + status: 404, |
| 95 | + headers: "Content-Type: application/json", |
| 96 | + contentType: "application/json", |
| 97 | + streamFd: -1, |
| 98 | + isComplete: true, |
| 99 | + partialBody: "{\"error\": \"Not found\"}" |
| 100 | + } |
| 101 | + } |
| 102 | + _ => HttpResponse { |
| 103 | + status: 405, |
| 104 | + headers: "Content-Type: application/json", |
| 105 | + contentType: "application/json", |
| 106 | + streamFd: -1, |
| 107 | + isComplete: true, |
| 108 | + partialBody: "{\"error\": \"Method not allowed\"}" |
| 109 | + } |
| 110 | +} |
| 111 | + |
| 112 | +// Start the server listening with our comprehensive handler |
| 113 | +print("Starting server listener with callback handler...") |
| 114 | +let listenResult = httpListen(serverId, handleHttpRequest) |
12 | 115 | print("Server listening on http://127.0.0.1:8080") |
13 | 116 |
|
14 | | -// Create HTTP client for external server tests |
| 117 | +// Create HTTP client to connect to OUR Osprey server |
15 | 118 | print("Creating HTTP client...") |
16 | | -let clientId = httpCreateClient("http://httpbin.org", 5000) |
| 119 | +let clientId = httpCreateClient("http://127.0.0.1:8080", 5000) |
17 | 120 | print("Client created with ID: ${clientId}") |
18 | 121 |
|
19 | | -// Test all HTTP methods against external server (won't actually connect) |
| 122 | +// Test HTTP methods against our REAL Osprey server |
20 | 123 | print("=== Testing HTTP Methods ===") |
21 | 124 |
|
22 | | -// Test GET request (will fail with connection error, but that's expected) |
| 125 | +// Test GET request |
23 | 126 | print("GET /api/users") |
24 | | -let getUsersResult = httpGet(clientId, "/get", "") |
| 127 | +let getUsersResult = httpGet(clientId, "/api/users", "") |
25 | 128 | print("GET /api/users result: ${getUsersResult}") |
26 | 129 |
|
27 | 130 | print("GET /health") |
28 | | -let getHealthResult = httpGet(clientId, "/status/200", "") |
| 131 | +let getHealthResult = httpGet(clientId, "/health", "") |
29 | 132 | print("GET /health result: ${getHealthResult}") |
30 | 133 |
|
31 | 134 | // Test POST request |
32 | 135 | print("POST /api/users") |
33 | 136 | let createUserData = "{\"name\": \"Charlie\", \"email\": \"charlie@example.com\"}" |
34 | | -let postResult = httpPost(clientId, "/post", createUserData, "Content-Type: application/json") |
| 137 | +let postResult = httpPost(clientId, "/api/users", createUserData, "Content-Type: application/json") |
35 | 138 | print("POST /api/users result: ${postResult}") |
36 | 139 |
|
37 | 140 | print("POST /api/auth/login") |
38 | 141 | let loginData = "{\"username\": \"admin\", \"password\": \"secret\"}" |
39 | | -let loginResult = httpPost(clientId, "/post", loginData, "Content-Type: application/json") |
| 142 | +let loginResult = httpPost(clientId, "/api/auth/login", loginData, "Content-Type: application/json") |
40 | 143 | print("POST /api/auth/login result: ${loginResult}") |
41 | 144 |
|
42 | 145 | // Test PUT request |
43 | 146 | print("PUT /api/users/1") |
44 | 147 | let updateUserData = "{\"name\": \"Alice Smith\", \"email\": \"alice.smith@example.com\"}" |
45 | | -let putResult = httpPut(clientId, "/put", updateUserData, "Content-Type: application/json") |
| 148 | +let putResult = httpPut(clientId, "/api/users/1", updateUserData, "Content-Type: application/json") |
46 | 149 | print("PUT /api/users/1 result: ${putResult}") |
47 | 150 |
|
48 | 151 | // Test DELETE request |
49 | 152 | print("DELETE /api/users/1") |
50 | | -let deleteResult = httpDelete(clientId, "/delete", "") |
| 153 | +let deleteResult = httpDelete(clientId, "/api/users/1", "") |
51 | 154 | print("DELETE /api/users/1 result: ${deleteResult}") |
52 | 155 |
|
53 | 156 | // Test non-existent endpoints |
54 | 157 | print("=== Testing Error Cases ===") |
55 | 158 | print("GET /nonexistent") |
56 | | -let notFoundResult = httpGet(clientId, "/status/404", "") |
| 159 | +let notFoundResult = httpGet(clientId, "/nonexistent", "") |
57 | 160 | print("GET /nonexistent result: ${notFoundResult}") |
58 | 161 |
|
59 | | -// 🚀 IMMEDIATE SHUTDOWN - Test Mode (No Sleep Required) |
60 | 162 | print("=== Server Shutdown Test ===") |
61 | 163 | print("✅ All HTTP operations completed successfully") |
62 | 164 | print("🛑 Initiating immediate graceful server shutdown...") |
63 | 165 |
|
64 | | -// Clean up server resources (server was never started, so this should be instant) |
| 166 | +// Clean up server resources |
65 | 167 | let stopResult = httpStopServer(serverId) |
66 | 168 | print("Server stopped with result: ${stopResult}") |
67 | 169 |
|
|
0 commit comments