11from typing import Any , Dict , List , Optional
22
33import orjson
4+ import packaging .version
45from fastapi import HTTPException , Request , Response , status
5- from packaging import version
66
77from dstack ._internal .core .errors import ServerClientError , ServerClientErrorCode
88from dstack ._internal .core .models .common import CoreModel
99from dstack ._internal .utils .json_utils import get_orjson_default_options , orjson_default
10+ from dstack ._internal .utils .version import parse_version
1011
1112
1213class CustomORJSONResponse (Response ):
@@ -122,8 +123,15 @@ def get_request_size(request: Request) -> int:
122123 return int (request .headers ["content-length" ])
123124
124125
126+ def get_client_version (request : Request ) -> Optional [packaging .version .Version ]:
127+ version = request .headers .get ("x-api-version" )
128+ if version is None :
129+ return None
130+ return parse_version (version )
131+
132+
125133def check_client_server_compatibility (
126- client_version : Optional [str ],
134+ client_version : Optional [packaging . version . Version ],
127135 server_version : Optional [str ],
128136) -> Optional [CustomORJSONResponse ]:
129137 """
@@ -132,28 +140,18 @@ def check_client_server_compatibility(
132140 """
133141 if client_version is None or server_version is None :
134142 return None
135- parsed_server_version = version .parse (server_version )
136- # latest allows client to bypass compatibility check (e.g. frontend)
137- if client_version == "latest" :
143+ parsed_server_version = parse_version (server_version )
144+ if parsed_server_version is None :
138145 return None
139- try :
140- parsed_client_version = version .parse (client_version )
141- except version .InvalidVersion :
142- return CustomORJSONResponse (
143- status_code = status .HTTP_400_BAD_REQUEST ,
144- content = {
145- "detail" : get_server_client_error_details (
146- ServerClientError ("Bad API version specified" )
147- )
148- },
149- )
150146 # We preserve full client backward compatibility across patch releases.
151147 # Server is always partially backward-compatible (so no check).
152- if parsed_client_version > parsed_server_version and (
153- parsed_client_version .major > parsed_server_version .major
154- or parsed_client_version .minor > parsed_server_version .minor
148+ if client_version > parsed_server_version and (
149+ client_version .major > parsed_server_version .major
150+ or client_version .minor > parsed_server_version .minor
155151 ):
156- return error_incompatible_versions (client_version , server_version , ask_cli_update = False )
152+ return error_incompatible_versions (
153+ str (client_version ), server_version , ask_cli_update = False
154+ )
157155 return None
158156
159157
0 commit comments