From 9294981305f2c20bf9fb093602dc5c91072b43f5 Mon Sep 17 00:00:00 2001 From: Kenneth Bingham Date: Wed, 29 Jan 2025 03:24:56 -0500 Subject: [PATCH] support custom domains and insecure https targets --- sdk/python/examples/proxy/proxy.py | 7 +++- sdk/python/sdk/zrok/zrok/proxy.py | 54 ++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/sdk/python/examples/proxy/proxy.py b/sdk/python/examples/proxy/proxy.py index d20597a4..815464cd 100644 --- a/sdk/python/examples/proxy/proxy.py +++ b/sdk/python/examples/proxy/proxy.py @@ -28,6 +28,9 @@ def main(): parser = argparse.ArgumentParser(description='Start a zrok proxy server') parser.add_argument('target_url', help='Target URL to proxy requests to') parser.add_argument('-n', '--unique-name', help='Unique name for the proxy instance') + parser.add_argument('-f', '--frontends', nargs='+', help='One or more space-separated frontends to use') + parser.add_argument('-k', '--insecure', action='store_false', dest='verify_ssl', default=True, + help='Skip SSL verification') args = parser.parse_args() logger.info("=== Starting proxy server ===") @@ -38,7 +41,9 @@ def main(): proxy_share = ProxyShare.create( root=root, target=args.target_url, - unique_name=args.unique_name + unique_name=args.unique_name, + frontends=args.frontends, + verify_ssl=args.verify_ssl ) # Log access information and start the proxy diff --git a/sdk/python/sdk/zrok/zrok/proxy.py b/sdk/python/sdk/zrok/zrok/proxy.py index eb5b0f7d..a25e1293 100644 --- a/sdk/python/sdk/zrok/zrok/proxy.py +++ b/sdk/python/sdk/zrok/zrok/proxy.py @@ -47,9 +47,11 @@ class ProxyShare: unique_name: Optional[str] = None _cleanup_registered: bool = False _app: Optional[Flask] = None + verify_ssl: bool = True @classmethod - def create(cls, root: Root, target: str, unique_name: Optional[str] = None) -> 'ProxyShare': + def create(cls, root: Root, target: str, unique_name: Optional[str] = None, + frontends: Optional[List[str]] = None, verify_ssl: bool = True) -> 'ProxyShare': """ Create a new proxy share, handling reservation and cleanup logic based on unique_name. @@ -57,6 +59,8 @@ class ProxyShare: root: The zrok root environment target: Target URL or service to proxy to unique_name: Optional unique name for a reserved share + frontends: Optional list of frontends to use, takes precedence over root's default_frontend + verify_ssl: Whether to verify SSL certificates when forwarding requests. Returns: ProxyShare instance configured with the created share @@ -70,30 +74,39 @@ class ProxyShare: root=root, share=existing_share, target=target, - unique_name=unique_name + unique_name=unique_name, + verify_ssl=verify_ssl ) - # Create new share request + # Compose the share request + if frontends: + share_frontends = frontends + elif root.cfg and root.cfg.DefaultFrontend: + share_frontends = [root.cfg.DefaultFrontend] + else: + share_frontends = ['public'] + share_request = ShareRequest( BackendMode=PROXY_BACKEND_MODE, ShareMode=PUBLIC_SHARE_MODE, - Target="http-proxy", - Frontends=['public'], - Reserved=bool(unique_name) + Target=target, + Frontends=share_frontends, + Reserved=True ) if unique_name: share_request.UniqueName = unique_name # Create the share share = CreateShare(root=root, request=share_request) - logger.info(f"Created new proxy share with endpoints: {', '.join(share.FrontendEndpoints)}") + logger.debug(f"Created new proxy share with endpoints: {', '.join(share.FrontendEndpoints)}") - # Create instance and setup cleanup if needed + # Create class instance and setup cleanup-at-exit if we reserved a random share token instance = cls( root=root, share=share, target=target, - unique_name=unique_name + unique_name=unique_name, + verify_ssl=verify_ssl ) if not unique_name: instance.register_cleanup() @@ -111,13 +124,19 @@ class ProxyShare: return None def register_cleanup(self): - """Register cleanup handler to release the share on exit.""" + """Register cleanup handler to release randomly generated shares on exit.""" if not self._cleanup_registered: def cleanup(): - ReleaseReservedShare(root=self.root, shr=self.share) - logger.info(f"Share {self.share.Token} released") + try: + ReleaseReservedShare(root=self.root, shr=self.share) + logger.info(f"Share {self.share.Token} released") + except Exception as e: + logger.error(f"Error during cleanup: {e}") + + # Register for normal exit only atexit.register(cleanup) self._cleanup_registered = True + return cleanup # Return the cleanup function for reuse def _create_app(self) -> Flask: """Create and configure the Flask app for proxying.""" @@ -138,7 +157,8 @@ class ProxyShare: data=request.get_data(), cookies=request.cookies, allow_redirects=False, - stream=True + stream=True, + verify=self.verify_ssl ) # Create the response @@ -154,17 +174,17 @@ class ProxyShare: return app def run(self): - """Start the proxy server.""" - if self._app is None: + """Run the proxy server.""" + if not self._app: self._app = self._create_app() - # Create options dictionary for zrok decorator zrok_opts: Dict[str, Any] = {} zrok_opts['cfg'] = zrok.decor.Opts(root=self.root, shrToken=self.token, bindPort=DUMMY_PORT) @zrok.decor.zrok(opts=zrok_opts) def run_server(): - serve(self._app, port=DUMMY_PORT) + serve(self._app, port=DUMMY_PORT, _quiet=True) + run_server() @property