Skip to content

Commit e6c2bcb

Browse files
Bihan  RanaBihan  Rana
authored andcommitted
Resolve SGLang API expose issue
1 parent 23d3e69 commit e6c2bcb

File tree

2 files changed

+29
-47
lines changed

2 files changed

+29
-47
lines changed

src/dstack/_internal/proxy/gateway/model_routers/__init__.py

Lines changed: 6 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,16 @@
1-
from typing import Dict, List, Optional, Type
1+
from typing import Optional
22

3-
from dstack._internal.core.models.routers import AnyRouterConfig, RouterType
4-
from dstack._internal.utils.logging import get_logger
3+
from dstack._internal.core.models.routers import AnyRouterConfig
4+
from dstack._internal.proxy.gateway.model_routers.sglang import SglangRouter
55

66
from .base import Replica, Router, RouterContext
77

8-
logger = get_logger(__name__)
9-
10-
"""This provides a registry of available router implementations."""
11-
12-
_ROUTER_CLASSES: List[Type[Router]] = []
13-
14-
try:
15-
from dstack._internal.proxy.gateway.model_routers.sglang import SglangRouter
16-
17-
_ROUTER_CLASSES.append(SglangRouter)
18-
logger.debug("Registered SglangRouter")
19-
except ImportError as e:
20-
logger.warning("SGLang router not available: %s", e)
21-
22-
_ROUTER_TYPE_TO_CLASS_MAP: Dict[RouterType, Type[Router]] = {}
23-
24-
for router_class in _ROUTER_CLASSES:
25-
router_type_str = getattr(router_class, "TYPE", None)
26-
if router_type_str is None:
27-
logger.warning(f"Router class {router_class.__name__} missing TYPE attribute, skipping")
28-
continue
29-
router_type = RouterType(router_type_str)
30-
_ROUTER_TYPE_TO_CLASS_MAP[router_type] = router_class
31-
32-
_AVAILABLE_ROUTER_TYPES = list(_ROUTER_TYPE_TO_CLASS_MAP.keys())
33-
34-
35-
def get_router_class(router_type: RouterType) -> Optional[Type[Router]]:
36-
"""Get the router class for a given router type."""
37-
return _ROUTER_TYPE_TO_CLASS_MAP.get(router_type)
38-
398

409
def get_router(router: AnyRouterConfig, context: Optional[RouterContext] = None) -> Router:
4110
"""Factory function to create a router instance from router configuration."""
42-
router_type = RouterType(router.type)
43-
router_class = get_router_class(router_type)
44-
45-
if router_class is None:
46-
available_types = [rt.value for rt in _AVAILABLE_ROUTER_TYPES]
47-
raise ValueError(
48-
f"Router type '{router_type.value}' is not available. "
49-
f"Available types: {available_types}"
50-
)
51-
52-
# Router implementations may have different constructor signatures
53-
# SglangRouter takes (router, context), others might differ
54-
return router_class(router=router, context=context)
11+
if router.type == "sglang":
12+
return SglangRouter(router=router, context=context)
13+
raise ValueError(f"Router type '{router.type}' is not available")
5514

5615

5716
__all__ = [

src/dstack/_internal/proxy/gateway/resources/nginx/service.jinja2

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,28 @@ server {
2222
access_log {{ access_log_path }} dstack_stat;
2323
client_max_body_size {{ client_max_body_size }};
2424

25+
{% if router is not none and router.type == "sglang" %}
26+
# Whitelist approach: Only allow safe user-facing endpoints
27+
# Allow /generate
28+
location = /generate {
29+
{% if auth %}
30+
auth_request /_dstack_auth;
31+
{% endif %}
32+
try_files /nonexistent @$http_upgrade;
33+
}
34+
# Allow /v1/* endpoints (regex match)
35+
location ~ ^/v1/ {
36+
{% if auth %}
37+
auth_request /_dstack_auth;
38+
{% endif %}
39+
try_files /nonexistent @$http_upgrade;
40+
}
41+
# Block everything else
42+
# This will match any path that doesn't match /generate or /v1/*
43+
location ~ . {
44+
return 403;
45+
}
46+
{% else %}
2547
{% for location in locations %}
2648
location {{ location.prefix }} {
2749
{% if auth %}
@@ -35,6 +57,7 @@ server {
3557
{% endif %}
3658
}
3759
{% endfor %}
60+
{% endif %}
3861

3962
location @websocket {
4063
set $dstack_replica_hit 1;

0 commit comments

Comments
 (0)