Skip to content

Commit d653877

Browse files
authored
server(api): change default server path (#47)
* change default server path * tests(server): update tests for configured route_prefix
1 parent 56545e3 commit d653877

File tree

3 files changed

+101
-19
lines changed

3 files changed

+101
-19
lines changed

pytrickle/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def __init__(
5252
app_context: Optional[Dict[str, Any]] = None,
5353
health_check_interval: float = 5.0,
5454
enable_default_routes: bool = True,
55-
route_prefix: str = "/api",
55+
route_prefix: str = "/",
5656
host: str = "0.0.0.0",
5757
# Startup/shutdown hooks
5858
on_startup: Optional[List[Callable]] = None,

tests/test_state_integration.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
from pytrickle.test_utils import MockFrameProcessor, create_mock_client
1717

1818

19+
def get_stream_route(server, endpoint):
20+
"""Get the full route path for a streaming endpoint."""
21+
prefix = server.route_prefix.rstrip('/')
22+
return f"{prefix}/stream/{endpoint}"
23+
24+
1925
@pytest_asyncio.fixture
2026
async def server_with_state():
2127
"""Create a server with state for integration testing."""
@@ -308,7 +314,7 @@ async def test_server_stream_state_validation(self, server_with_state):
308314
client = TestClient(test_server_instance)
309315
async with client:
310316
# Initial state validation
311-
resp = await client.get("/api/stream/status")
317+
resp = await client.get(get_stream_route(server, "status"))
312318
assert resp.status == 200
313319
data = await resp.json()
314320
assert data["client_active"] is False
@@ -323,7 +329,7 @@ async def test_server_stream_state_validation(self, server_with_state):
323329
server.current_client = mock_client
324330

325331
# Validate state changes are reflected
326-
resp = await client.get("/api/stream/status")
332+
resp = await client.get(get_stream_route(server, "status"))
327333
assert resp.status == 200
328334
data = await resp.json()
329335
assert data["client_active"] is True
@@ -334,7 +340,7 @@ async def test_server_stream_state_validation(self, server_with_state):
334340
server.state.set_active_client(False)
335341
server.state.update_active_streams(0)
336342

337-
resp = await client.get("/api/stream/status")
343+
resp = await client.get(get_stream_route(server, "status"))
338344
assert resp.status == 200
339345
data = await resp.json()
340346
assert data["client_active"] is False

tests/test_stream_server.py

Lines changed: 91 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212
from unittest.mock import patch, MagicMock, AsyncMock
1313

1414
from pytrickle.server import StreamServer
15-
from pytrickle.state import PipelineState
1615
from pytrickle.test_utils import MockFrameProcessor, create_mock_client
1716

17+
def get_stream_route(server, endpoint):
18+
"""Get the full route path for a streaming endpoint."""
19+
prefix = server.route_prefix.rstrip('/')
20+
return f"{prefix}/stream/{endpoint}"
21+
1822

1923
@pytest_asyncio.fixture
2024
async def test_server():
@@ -71,7 +75,7 @@ async def test_start_stream_success_with_validation(self, test_server):
7175
}
7276
}
7377

74-
resp = await client.post("/api/stream/start", json=payload)
78+
resp = await client.post(get_stream_route(server, "start"), json=payload)
7579
assert resp.status == 200
7680

7781
data = await resp.json()
@@ -109,7 +113,7 @@ async def test_stream_state_updates_during_lifecycle(self, test_server):
109113
assert server.state.active_client is True
110114

111115
# Verify this reflects in status endpoint
112-
resp = await client.get("/api/stream/status")
116+
resp = await client.get(get_stream_route(server, "status"))
113117
assert resp.status == 200
114118
data = await resp.json()
115119
assert data["active_streams"] == 1
@@ -138,7 +142,7 @@ async def test_start_stream_validation_error(self, test_server):
138142
# Missing publish_url and gateway_request_id
139143
}
140144

141-
resp = await client.post("/api/stream/start", json=payload)
145+
resp = await client.post(get_stream_route(server, "start"), json=payload)
142146
assert resp.status == 400
143147

144148
# Verify state wasn't changed
@@ -160,7 +164,7 @@ async def test_update_params_success_with_monitoring(self, test_server):
160164

161165
payload = {"intensity": 0.9}
162166

163-
resp = await client.post("/api/stream/params", json=payload)
167+
resp = await client.post(get_stream_route(server, "params"), json=payload)
164168
assert resp.status == 200
165169

166170
data = await resp.json()
@@ -182,7 +186,7 @@ async def test_update_params_no_active_stream(self, test_server):
182186

183187
payload = {"intensity": 0.9}
184188

185-
resp = await client.post("/api/stream/params", json=payload)
189+
resp = await client.post(get_stream_route(server, "params"), json=payload)
186190
assert resp.status == 400
187191

188192
data = await resp.json()
@@ -194,7 +198,7 @@ async def test_get_status_no_client(self, test_server):
194198
"""Test status endpoint when no client is active."""
195199
client, server = test_server
196200

197-
resp = await client.get("/api/stream/status")
201+
resp = await client.get(get_stream_route(server, "status"))
198202
assert resp.status == 200
199203

200204
data = await resp.json()
@@ -218,7 +222,7 @@ async def test_get_status_with_active_client(self, test_server):
218222
gateway_request_id="status-test"
219223
)
220224

221-
resp = await client.get("/api/stream/status")
225+
resp = await client.get(get_stream_route(server, "status"))
222226
assert resp.status == 200
223227

224228
data = await resp.json()
@@ -243,7 +247,7 @@ async def test_stop_stream_success_with_monitoring(self, test_server):
243247
server.state.set_active_client(True)
244248
server.state.update_active_streams(1)
245249

246-
resp = await client.post("/api/stream/stop", json={})
250+
resp = await client.post(get_stream_route(server, "stop"), json={})
247251
assert resp.status == 200
248252

249253
data = await resp.json()
@@ -267,7 +271,7 @@ async def test_stop_stream_no_active_stream(self, test_server):
267271
"""Test stop stream when no stream is active."""
268272
client, server = test_server
269273

270-
resp = await client.post("/api/stream/stop", json={})
274+
resp = await client.post(get_stream_route(server, "stop"), json={})
271275
assert resp.status == 400
272276

273277
data = await resp.json()
@@ -287,7 +291,7 @@ async def test_direct_state_manipulation(self, test_server):
287291
server.state.update_active_streams(1)
288292
server.state.set_active_client(True)
289293

290-
resp = await client.get("/api/stream/status")
294+
resp = await client.get(get_stream_route(server, "status"))
291295
assert resp.status == 200
292296
data = await resp.json()
293297
assert data["active_streams"] == 1
@@ -296,7 +300,7 @@ async def test_direct_state_manipulation(self, test_server):
296300
server.state.update_active_streams(0)
297301
server.state.set_active_client(False)
298302

299-
resp = await client.get("/api/stream/status")
303+
resp = await client.get(get_stream_route(server, "status"))
300304
assert resp.status == 200
301305
data = await resp.json()
302306
assert data["active_streams"] == 0
@@ -316,7 +320,7 @@ async def test_error_state_handling_with_validation(self, test_server):
316320
assert data == {"status": "ERROR"}
317321

318322
# Verify status endpoint reflects error
319-
resp = await client.get("/api/stream/status")
323+
resp = await client.get(get_stream_route(server, "status"))
320324
assert resp.status == 200
321325
data = await resp.json()
322326
assert server.state.is_error()
@@ -331,6 +335,78 @@ async def test_error_state_handling_with_validation(self, test_server):
331335
assert data["status"] in ["IDLE", "LOADING"] # Should be back to normal
332336

333337

338+
class TestDynamicRoutes:
339+
"""Test dynamic route functionality with different prefixes."""
340+
341+
@pytest.mark.parametrize("route_prefix", ["/", "/api", "/v1", "/custom"])
342+
@pytest.mark.asyncio
343+
async def test_routes_with_different_prefixes(self, route_prefix):
344+
"""Test that routes work with different prefixes."""
345+
processor = MockFrameProcessor()
346+
347+
server = StreamServer(
348+
frame_processor=processor,
349+
port=0,
350+
route_prefix=route_prefix,
351+
capability_name="test-model",
352+
pipeline="test-pipeline",
353+
version="1.0.0",
354+
)
355+
356+
# Attach state and mark ready
357+
processor.attach_state(server.state)
358+
server.state.set_startup_complete()
359+
360+
# Test that routes are constructed correctly
361+
expected_start_route = f"{route_prefix.rstrip('/')}/stream/start"
362+
actual_start_route = get_stream_route(server, "start")
363+
assert actual_start_route == expected_start_route
364+
365+
expected_status_route = f"{route_prefix.rstrip('/')}/stream/status"
366+
actual_status_route = get_stream_route(server, "status")
367+
assert actual_status_route == expected_status_route
368+
369+
expected_params_route = f"{route_prefix.rstrip('/')}/stream/params"
370+
actual_params_route = get_stream_route(server, "params")
371+
assert actual_params_route == expected_params_route
372+
373+
expected_stop_route = f"{route_prefix.rstrip('/')}/stream/stop"
374+
actual_stop_route = get_stream_route(server, "stop")
375+
assert actual_stop_route == expected_stop_route
376+
377+
@pytest.mark.asyncio
378+
async def test_functional_test_with_custom_prefix(self):
379+
"""Test that endpoints actually work with a custom prefix."""
380+
processor = MockFrameProcessor()
381+
382+
server = StreamServer(
383+
frame_processor=processor,
384+
port=0,
385+
route_prefix="/api/v2",
386+
capability_name="test-model",
387+
pipeline="test-pipeline",
388+
version="1.0.0",
389+
)
390+
391+
# Attach state and mark ready
392+
processor.attach_state(server.state)
393+
server.state.set_startup_complete()
394+
395+
app = server.get_app()
396+
test_server_instance = TestServer(app)
397+
398+
async with test_server_instance:
399+
client = TestClient(test_server_instance)
400+
async with client:
401+
# Test status endpoint with custom prefix
402+
resp = await client.get(get_stream_route(server, "status"))
403+
assert resp.status == 200
404+
405+
data = await resp.json()
406+
assert data["client_active"] is False
407+
assert data["active_streams"] == 0
408+
409+
334410
class TestErrorHandling:
335411
"""Test error handling scenarios with state validation."""
336412

@@ -351,7 +427,7 @@ async def test_client_error_state_propagation(self, test_server):
351427
"gateway_request_id": "error-test"
352428
}
353429

354-
resp = await client.post("/api/stream/start", json=payload)
430+
resp = await client.post(get_stream_route(server, "start"), json=payload)
355431
# API call succeeds, but client will fail in background
356432
assert resp.status == 200
357433

@@ -385,7 +461,7 @@ async def test_concurrent_stream_operations(self, test_server):
385461

386462
# Send multiple concurrent requests
387463
tasks = [
388-
client.post("/api/stream/start", json=payload)
464+
client.post(get_stream_route(server, "start"), json=payload)
389465
for _ in range(3)
390466
]
391467

0 commit comments

Comments
 (0)