Public URLs
Give a port inside a sandbox a public HTTPS address, for a preview, a webhook receiver or a demo:
$ froog exec my-box --detach -- 'cd app && npm run dev -- --port 3000'
$ froog host my-box 3000
https://my-box-3000-k7f2qx.froogusercontent.com/?_token=pt_9c1e…
$ froog host my-box 3000 --public # no token: anyone with the address
$ froog host my-box 3000 --subdomain acme-demo # https://acme-demo.froogusercontent.com
$ froog host my-box 3000 --title "API docs" # a label in listings
$ froog host my-box # list
$ froog host my-box 3000 --rm # remove
$ froog new web --host 3000:public # a URL from the start (repeat --host; PORT alone is private)
The service can listen on localhost or 0.0.0.0. A private URL opens nothing on froog's firewall. A --public one also opens its TCP port on the sandbox's IPv6 address (see Network), and closes it again when the URL is removed or made private. Traffic through the URL, websockets included, reaches it through an SSH tunnel from froog's edge (it doesn't hold off auto-stop). The URL stays the same across stop, start and restore. While the sandbox is stopped, visitors see a short notice, or, with auto-start, it starts. A new URL is private, like boat's: it carries a _token. The first visit redirects to the same address without it and sets a cookie (__Host-froog_url) for that host, so the link works in a browser. An API client sends Cookie: __Host-froog_url=<token> instead (or follows the redirect with a cookie jar: curl -L -c jar -b jar URL). Treat the full link like a password. --public drops the token. Hosting the same port again without it makes a new token, so --public then plain froog host replaces a leaked one. A private URL in an iframe on another site may stay blank (browsers block third-party cookies): use --public for embeds. --subdomain renames a URL (3-40 lowercase letters, digits and hyphens, or 409 subdomain_taken if someone has it), and the old address stops working. --title labels a URL in listings (up to 100 characters, hosting again without it keeps it, --title "" removes it). Up to 50 per sandbox, and 20 new addresses per account a day. The first visit to a new URL takes a few seconds while its certificate is issued.
Wait for a port. To know when the server you started is up, wait for its port: froog wait my-box --port 3000 --timeout 2m returns once something listens on it inside the sandbox, on any address, and exits 1 if nothing does in time (default 60 seconds, at most 10 minutes). API: POST /sandboxes/{name}/wait {port, timeout_secs?} answers {port, ready, waited_ms}, with ready: false after the timeout. A sandbox that is still starting, or stopped with auto-start, counts against the same timeout. It needs only sandbox.read (starting an auto-start sandbox needs sandbox.resume or sandbox.update, as for every call), and it isn't recorded in the command history.
A token per viewer. To share a private URL with several people and cut one off later, give each their own token. It expires (default a day, 60 seconds to 30 days) and can be revoked without touching the others or the URL's own token:
$ froog url-token create my-box 3000 --ttl 2h --label alice
https://my-box-3000-k7f2qx.froogusercontent.com/?_token=pvt_51d0…
$ froog url-token list my-box 3000
$ froog url-token revoke my-box 3000 utk_…
A viewer token works like the URL's own: as ?_token= (turned into a cookie that lasts until the token expires) or in the cookie. Every request is checked, so a revoked or expired token stops working at the viewer's next request. Any private URL token, the URL's own included, can also go in an X-Froog-Url-Token header, for scripts and API clients that don't keep cookies. API: POST /sandboxes/{name}/urls/{port}/tokens {ttl_secs?, label?} returns {id, token, url, expires_at} (the secret only this once), GET lists the live ones, DELETE …/tokens/{id} revokes one. Up to 100 live tokens per URL. Public URLs have none (409 url_public). Making a URL public, or removing it, deletes its viewer tokens.