Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 35 additions & 17 deletions koyeb/sandbox/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def __init__(
self._created_at = time.time()
self._sandbox_url: Optional[Tuple[str, Optional[str]]] = None
self._domain: Optional[str] = None
self._url: Optional[str] = None
self._client = None

@property
Expand Down Expand Up @@ -476,7 +477,6 @@ def _get_domain(self) -> Optional[str]:
Internal method to get the public domain of the sandbox.

Returns the domain name (e.g., "app-name-org.koyeb.app") without protocol or path.
To construct the URL, use: f"https://{sandbox.get_domain()}"

Returns:
Optional[str]: The domain name or None if unavailable
Expand All @@ -500,27 +500,45 @@ def _get_domain(self) -> Optional[str]:
except (NotFoundException, ApiException, Exception):
return None

def get_domain(self) -> Optional[str]:
def _get_url(self) -> Optional[str]:
"""
Get the public domain of the sandbox.
Get the public URL of the sandbox with protocol.

Returns the domain name (e.g., "app-name-org.koyeb.app") without protocol or path.
To construct the URL, use: f"https://{sandbox.get_domain()}"
Returns the full URL (e.g., "https://app-name-org.koyeb.app/r/routing_key/" or
"https://app-name-org.koyeb.app").

Returns:
Optional[str]: The domain name or None if unavailable
Optional[str]: The full URL or None if unavailable
"""
if self._domain is None:
if self._url is None:
url_data = self.get_url_and_header_from_metadata()
if url_data:
domain = url_data[0].split("://")[1]
self._domain = f"{domain}/r/{url_data[1]}/"
return self._domain
self._url = f"{url_data[0]}/r/{url_data[1]}/"
return self._url

domain = self._get_domain()
if domain:
self._domain = domain
return self._domain
self._url = f"https://{domain}"
return self._url

def get_domain(self) -> Optional[str]:
"""
Get the public domain of the sandbox.

Returns the domain (e.g., "app-name-org.koyeb.app/r/routing_key/" or
"app-name-org.koyeb.app") without protocol. To get the full URL with protocol,
use sandbox._get_url()

Returns:
Optional[str]: The domain or None if unavailable
"""
url = self._get_url()
if url:
if url.startswith("https://"):
return url[8:]
elif url.startswith("http://"):
return url[7:]
return url

def get_tcp_proxy_info(self) -> Optional[tuple[str, int]]:
"""
Expand Down Expand Up @@ -715,14 +733,14 @@ def expose_port(self, port: int) -> ExposedPort:
response = client.bind_port(port)
self._check_response_error(response, f"expose port {port}")

# Get domain for exposed_at
domain = self.get_domain()
if not domain:
raise SandboxError("Domain not available for exposed port")
# Get URL for exposed_at
url = self._get_url()
if not url:
raise SandboxError("URL not available for exposed port")

# Return the port from response if available, otherwise use the requested port
exposed_port = int(response.get("port", port))
exposed_at = f"https://{domain}"
exposed_at = url
return ExposedPort(port=exposed_port, exposed_at=exposed_at)
except Exception as e:
if isinstance(e, SandboxError):
Expand Down
Loading