modal 1.2.4.dev0__tar.gz → 1.2.4.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/PKG-INFO +1 -1
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_tunnel.py +11 -2
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_tunnel.pyi +25 -3
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/client.pyi +2 -2
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/experimental/flash.py +4 -2
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/experimental/flash.pyi +4 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_version/__init__.py +1 -1
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/LICENSE +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/README.md +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/__main__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_billing.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_clustered_functions.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_clustered_functions.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_container_entrypoint.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_functions.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_grpc_client.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_ipython.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_load_context.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_location.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_object.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_output.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_partial_function.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_pty.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_resolver.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_resources.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_runtime/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_runtime/asgi.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_runtime/execution_context.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_runtime/telemetry.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_serialization.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_traceback.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_type_manager.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/app_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/async_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/blob_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/deprecation.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/docker_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/function_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/git_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/hash_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/http_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/logger.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/mount_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/name_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/package_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/shell_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_utils/time_utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_vendor/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_vendor/tblib.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/_watcher.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/app.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/app.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/billing.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/builder/2023.12.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/builder/2024.04.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/builder/2024.10.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/builder/2025.06.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/builder/README.md +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/builder/base-images.json +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/call_graph.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/_download.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/_traceback.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/app.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/cluster.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/config.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/container.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/dict.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/entry_point.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/environment.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/import_refs.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/launch.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/network_file_system.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/profile.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/programs/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/programs/launch_instance_ssh.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/programs/run_marimo.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/programs/vscode.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/queues.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/run.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/secret.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/token.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/utils.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cli/volume.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/client.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cls.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/cls.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/config.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/container_process.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/container_process.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/dict.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/dict.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/environments.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/environments.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/exception.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/experimental/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/experimental/ipython.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/file_io.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/file_io.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/file_pattern_matcher.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/functions.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/functions.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/gpu.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/image.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/image.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/io_streams.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/io_streams.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/mount.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/mount.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/network_file_system.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/network_file_system.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/object.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/object.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/output.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/parallel_map.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/parallel_map.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/partial_function.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/partial_function.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/proxy.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/proxy.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/py.typed +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/queue.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/queue.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/retries.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/runner.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/runner.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/running_app.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/sandbox.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/sandbox.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/schedule.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/scheduler_placement.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/secret.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/secret.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/serving.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/serving.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/snapshot.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/snapshot.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/stream_type.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/token_flow.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/token_flow.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/volume.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal/volume.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal.egg-info/requires.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal.egg-info/top_level.txt +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_docs/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/__init__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/api.proto +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/api_grpc.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/api_pb2.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/py.typed +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/sandbox_router.proto +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/sandbox_router_grpc.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/sandbox_router_pb2.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/sandbox_router_pb2.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/task_command_router.proto +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/modal_version/__main__.py +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/pyproject.toml +0 -0
- {modal-1.2.4.dev0 → modal-1.2.4.dev2}/setup.cfg +0 -0
|
@@ -51,13 +51,17 @@ class Tunnel:
|
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
@asynccontextmanager
|
|
54
|
-
async def _forward(
|
|
54
|
+
async def _forward(
|
|
55
|
+
port: int, *, unencrypted: bool = False, h2_enabled: bool = False, client: Optional[_Client] = None
|
|
56
|
+
) -> AsyncIterator[Tunnel]:
|
|
55
57
|
"""Expose a port publicly from inside a running Modal container, with TLS.
|
|
56
58
|
|
|
57
59
|
If `unencrypted` is set, this also exposes the TCP socket without encryption on a random port
|
|
58
60
|
number. This can be used to SSH into a container (see example below). Note that it is on the public Internet, so
|
|
59
61
|
make sure you are using a secure protocol over TCP.
|
|
60
62
|
|
|
63
|
+
If `h2_enabled` is set, the TLS server will advertise support for HTTP/2.
|
|
64
|
+
|
|
61
65
|
**Important:** This is an experimental API which may change in the future.
|
|
62
66
|
|
|
63
67
|
**Usage:**
|
|
@@ -168,6 +172,8 @@ async def _forward(port: int, *, unencrypted: bool = False, client: Optional[_Cl
|
|
|
168
172
|
raise InvalidError(f"The port argument should be an int, not {port!r}")
|
|
169
173
|
if port < 1 or port > 65535:
|
|
170
174
|
raise InvalidError(f"Invalid port number {port}")
|
|
175
|
+
if h2_enabled and unencrypted:
|
|
176
|
+
raise InvalidError("H2 can only be used with encrypted ports")
|
|
171
177
|
|
|
172
178
|
if not client:
|
|
173
179
|
client = await _Client.from_env()
|
|
@@ -175,8 +181,11 @@ async def _forward(port: int, *, unencrypted: bool = False, client: Optional[_Cl
|
|
|
175
181
|
if client.client_type != api_pb2.CLIENT_TYPE_CONTAINER:
|
|
176
182
|
raise InvalidError("Forwarding ports only works inside a Modal container")
|
|
177
183
|
|
|
184
|
+
tunnel_type = api_pb2.TUNNEL_TYPE_H2 if h2_enabled else api_pb2.TUNNEL_TYPE_UNSPECIFIED
|
|
178
185
|
try:
|
|
179
|
-
response = await client.stub.TunnelStart(
|
|
186
|
+
response = await client.stub.TunnelStart(
|
|
187
|
+
api_pb2.TunnelStartRequest(port=port, unencrypted=unencrypted, tunnel_type=tunnel_type)
|
|
188
|
+
)
|
|
180
189
|
except GRPCError as exc:
|
|
181
190
|
if exc.status == Status.ALREADY_EXISTS:
|
|
182
191
|
raise InvalidError(f"Port {port} is already forwarded")
|
|
@@ -54,7 +54,11 @@ class Tunnel:
|
|
|
54
54
|
...
|
|
55
55
|
|
|
56
56
|
def _forward(
|
|
57
|
-
port: int,
|
|
57
|
+
port: int,
|
|
58
|
+
*,
|
|
59
|
+
unencrypted: bool = False,
|
|
60
|
+
h2_enabled: bool = False,
|
|
61
|
+
client: typing.Optional[modal.client._Client] = None,
|
|
58
62
|
) -> typing.AsyncContextManager[Tunnel]:
|
|
59
63
|
'''Expose a port publicly from inside a running Modal container, with TLS.
|
|
60
64
|
|
|
@@ -62,6 +66,8 @@ def _forward(
|
|
|
62
66
|
number. This can be used to SSH into a container (see example below). Note that it is on the public Internet, so
|
|
63
67
|
make sure you are using a secure protocol over TCP.
|
|
64
68
|
|
|
69
|
+
If `h2_enabled` is set, the TLS server will advertise support for HTTP/2.
|
|
70
|
+
|
|
65
71
|
**Important:** This is an experimental API which may change in the future.
|
|
66
72
|
|
|
67
73
|
**Usage:**
|
|
@@ -171,7 +177,13 @@ def _forward(
|
|
|
171
177
|
|
|
172
178
|
class __forward_spec(typing_extensions.Protocol):
|
|
173
179
|
def __call__(
|
|
174
|
-
self,
|
|
180
|
+
self,
|
|
181
|
+
/,
|
|
182
|
+
port: int,
|
|
183
|
+
*,
|
|
184
|
+
unencrypted: bool = False,
|
|
185
|
+
h2_enabled: bool = False,
|
|
186
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
175
187
|
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[Tunnel]:
|
|
176
188
|
'''Expose a port publicly from inside a running Modal container, with TLS.
|
|
177
189
|
|
|
@@ -179,6 +191,8 @@ class __forward_spec(typing_extensions.Protocol):
|
|
|
179
191
|
number. This can be used to SSH into a container (see example below). Note that it is on the public Internet, so
|
|
180
192
|
make sure you are using a secure protocol over TCP.
|
|
181
193
|
|
|
194
|
+
If `h2_enabled` is set, the TLS server will advertise support for HTTP/2.
|
|
195
|
+
|
|
182
196
|
**Important:** This is an experimental API which may change in the future.
|
|
183
197
|
|
|
184
198
|
**Usage:**
|
|
@@ -287,7 +301,13 @@ class __forward_spec(typing_extensions.Protocol):
|
|
|
287
301
|
...
|
|
288
302
|
|
|
289
303
|
def aio(
|
|
290
|
-
self,
|
|
304
|
+
self,
|
|
305
|
+
/,
|
|
306
|
+
port: int,
|
|
307
|
+
*,
|
|
308
|
+
unencrypted: bool = False,
|
|
309
|
+
h2_enabled: bool = False,
|
|
310
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
291
311
|
) -> typing.AsyncContextManager[Tunnel]:
|
|
292
312
|
'''Expose a port publicly from inside a running Modal container, with TLS.
|
|
293
313
|
|
|
@@ -295,6 +315,8 @@ class __forward_spec(typing_extensions.Protocol):
|
|
|
295
315
|
number. This can be used to SSH into a container (see example below). Note that it is on the public Internet, so
|
|
296
316
|
make sure you are using a secure protocol over TCP.
|
|
297
317
|
|
|
318
|
+
If `h2_enabled` is set, the TLS server will advertise support for HTTP/2.
|
|
319
|
+
|
|
298
320
|
**Important:** This is an experimental API which may change in the future.
|
|
299
321
|
|
|
300
322
|
**Usage:**
|
|
@@ -32,7 +32,7 @@ class _Client:
|
|
|
32
32
|
server_url: str,
|
|
33
33
|
client_type: int,
|
|
34
34
|
credentials: typing.Optional[tuple[str, str]],
|
|
35
|
-
version: str = "1.2.4.
|
|
35
|
+
version: str = "1.2.4.dev2",
|
|
36
36
|
):
|
|
37
37
|
"""mdmd:hidden
|
|
38
38
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -163,7 +163,7 @@ class Client:
|
|
|
163
163
|
server_url: str,
|
|
164
164
|
client_type: int,
|
|
165
165
|
credentials: typing.Optional[tuple[str, str]],
|
|
166
|
-
version: str = "1.2.4.
|
|
166
|
+
version: str = "1.2.4.dev2",
|
|
167
167
|
):
|
|
168
168
|
"""mdmd:hidden
|
|
169
169
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -30,13 +30,14 @@ class _FlashManager:
|
|
|
30
30
|
port: int,
|
|
31
31
|
process: Optional[subprocess.Popen] = None,
|
|
32
32
|
health_check_url: Optional[str] = None,
|
|
33
|
+
h2_enabled: bool = False,
|
|
33
34
|
):
|
|
34
35
|
self.client = client
|
|
35
36
|
self.port = port
|
|
36
37
|
# Health check is not currently being used
|
|
37
38
|
self.health_check_url = health_check_url
|
|
38
39
|
self.process = process
|
|
39
|
-
self.tunnel_manager = _forward_tunnel(port, client=client)
|
|
40
|
+
self.tunnel_manager = _forward_tunnel(port, h2_enabled=h2_enabled, client=client)
|
|
40
41
|
self.stopped = False
|
|
41
42
|
self.num_failures = 0
|
|
42
43
|
self.task_id = os.environ["MODAL_TASK_ID"]
|
|
@@ -170,6 +171,7 @@ async def flash_forward(
|
|
|
170
171
|
port: int,
|
|
171
172
|
process: Optional[subprocess.Popen] = None,
|
|
172
173
|
health_check_url: Optional[str] = None,
|
|
174
|
+
h2_enabled: bool = False,
|
|
173
175
|
) -> _FlashManager:
|
|
174
176
|
"""
|
|
175
177
|
Forward a port to the Modal Flash service, exposing that port as a stable web endpoint.
|
|
@@ -178,7 +180,7 @@ async def flash_forward(
|
|
|
178
180
|
"""
|
|
179
181
|
client = await _Client.from_env()
|
|
180
182
|
|
|
181
|
-
manager = _FlashManager(client, port, process=process, health_check_url=health_check_url)
|
|
183
|
+
manager = _FlashManager(client, port, process=process, health_check_url=health_check_url, h2_enabled=h2_enabled)
|
|
182
184
|
await manager._start()
|
|
183
185
|
return manager
|
|
184
186
|
|
|
@@ -10,6 +10,7 @@ class _FlashManager:
|
|
|
10
10
|
port: int,
|
|
11
11
|
process: typing.Optional[subprocess.Popen] = None,
|
|
12
12
|
health_check_url: typing.Optional[str] = None,
|
|
13
|
+
h2_enabled: bool = False,
|
|
13
14
|
):
|
|
14
15
|
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
15
16
|
...
|
|
@@ -36,6 +37,7 @@ class FlashManager:
|
|
|
36
37
|
port: int,
|
|
37
38
|
process: typing.Optional[subprocess.Popen] = None,
|
|
38
39
|
health_check_url: typing.Optional[str] = None,
|
|
40
|
+
h2_enabled: bool = False,
|
|
39
41
|
): ...
|
|
40
42
|
|
|
41
43
|
class __is_port_connection_healthy_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
@@ -92,6 +94,7 @@ class __flash_forward_spec(typing_extensions.Protocol):
|
|
|
92
94
|
port: int,
|
|
93
95
|
process: typing.Optional[subprocess.Popen] = None,
|
|
94
96
|
health_check_url: typing.Optional[str] = None,
|
|
97
|
+
h2_enabled: bool = False,
|
|
95
98
|
) -> FlashManager:
|
|
96
99
|
"""Forward a port to the Modal Flash service, exposing that port as a stable web endpoint.
|
|
97
100
|
This is a highly experimental method that can break or be removed at any time without warning.
|
|
@@ -105,6 +108,7 @@ class __flash_forward_spec(typing_extensions.Protocol):
|
|
|
105
108
|
port: int,
|
|
106
109
|
process: typing.Optional[subprocess.Popen] = None,
|
|
107
110
|
health_check_url: typing.Optional[str] = None,
|
|
111
|
+
h2_enabled: bool = False,
|
|
108
112
|
) -> FlashManager:
|
|
109
113
|
"""Forward a port to the Modal Flash service, exposing that port as a stable web endpoint.
|
|
110
114
|
This is a highly experimental method that can break or be removed at any time without warning.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|