-
Notifications
You must be signed in to change notification settings - Fork 0
Add HTTPS/TLS support for the built-in web server #564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
a6ab539
feat(webserver): add HTTPS/TLS support with auto-redirect and dual-se…
claude 89206bb
fix(webserver): address PR #564 review feedback and Windows CI failure
claude e8e9c98
Merge branch 'main' into claude/wfl-https-support-j3sn6a
logbie 0572850
Merge branch 'main' into claude/wfl-https-support-j3sn6a
logbie 3e48f7a
refactor(webserver): align rustls-pemfile with warp on v2
claude File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| # HTTPS/TLS support for the built-in web server | ||
|
|
||
| **Date:** 2026-07-04 | ||
|
|
||
| ## What was added | ||
|
|
||
| The `listen` statement grew two optional clauses: | ||
|
|
||
| ```wfl | ||
| // HTTPS, paths in the code | ||
| listen on port 8443 secured with certificate "cert.pem" and key "key.pem" as secure_server | ||
|
|
||
| // HTTPS, paths from .wflcfg (web_server_tls_cert_file / web_server_tls_key_file) | ||
| listen on port 8443 secured as secure_server | ||
|
|
||
| // Native HTTP -> HTTPS 301 redirect server | ||
| listen on port 8080 redirecting to port 8443 as redirect_server | ||
| ``` | ||
|
|
||
| Plain `listen` is untouched, and running an HTTP server *alongside* an HTTPS one | ||
| (instead of redirecting) works by simply issuing two `listen` statements. | ||
|
|
||
| ## Design decisions worth remembering | ||
|
|
||
| ### No new keywords | ||
|
|
||
| `secured`, `certificate`, `key`, and `redirecting` are **plain identifiers** | ||
| matched positionally by the parser, not lexer tokens. `key` in particular is | ||
| used as a variable in existing programs (`TestPrograms/hash_security_test.wfl` | ||
| does `store key as "secret_key_456"`), so reserving it would have broken | ||
| backward compatibility. The keyword count stays at 178. | ||
|
|
||
| The cost is dealing with the lexer's multi-word identifier merging: adjacent | ||
| identifiers fuse into one token, so `port my_port secured` arrives as | ||
| `Identifier("my_port secured")` and `certificate cert_var` as | ||
| `Identifier("certificate cert_var")`. The parser splits these apart with the | ||
| same strip-prefix/suffix approach `respond ... and content_type` already uses. | ||
| One subtlety: the merged `... secured` detection must happen *before* the port | ||
| expression is parsed, because `with` is a concatenation operator and | ||
| `parse_expression` would swallow `with certificate "..."` into the port | ||
| expression. | ||
|
|
||
| `redirecting to` (rather than `and redirect to`) avoids the same trap: `and` | ||
| is a boolean operator and would be absorbed by the port expression. | ||
|
|
||
| ### Config precedence | ||
|
|
||
| TLS intent always lives in the program; `.wflcfg` only supplies default file | ||
| paths for the bare `secured` form. A plain `listen` never becomes HTTPS via | ||
| config — otherwise dropping cert paths into `.wflcfg` would silently convert | ||
| the HTTP half of a dual-server setup. | ||
|
|
||
| ### warp TLS plumbing | ||
|
|
||
| - `warp` is now built with `features = ["tls"]`. That pulls in tokio-rustls | ||
| 0.25 → **rustls 0.22.4**, which coexists with the **rustls 0.23.35** already | ||
| in the tree via sqlx's `runtime-tokio-rustls`. Two rustls minors compile | ||
| fine side by side; unifying them means upgrading warp (or replacing it) | ||
| some day. | ||
| - warp's `TlsServer` has no `try_bind_ephemeral`, and its `bind_ephemeral` | ||
| panics *inside the spawned task* on a bad certificate or occupied port. The | ||
| interpreter therefore uses `try_bind_with_graceful_shutdown` with a | ||
| never-completing signal (`std::future::pending()`), which returns both TLS | ||
| config errors and bind errors synchronously as `Result`. On top of that, | ||
| certificate/key files are pre-validated with `rustls-pemfile` (now a direct | ||
| dependency; it was already in the lockfile) so a missing or malformed file | ||
| produces an actionable message naming the path. | ||
|
|
||
| ### Redirect servers are native | ||
|
|
||
| The redirect listener answers 301 inside warp itself — requests never enter | ||
| the WFL request loop, so `wait for request` on a redirect server never fires | ||
| (documented). This sidesteps the fact that `respond` can't set custom headers | ||
| yet (the `Location` header requirement). The Location URL preserves host | ||
| (port stripped, IPv6 brackets kept), path, and query, and omits the target | ||
| port when it's 443. The server is still registered in `web_servers` so | ||
| `close server` works. | ||
|
|
||
| ## Testing | ||
|
|
||
| - `tests/web_server_tls_parser_test.rs` — 14 parser cases incl. all merged | ||
| identifier forms and error cases. | ||
| - `tests/web_server_tls_test.rs` — end-to-end with rcgen-generated | ||
| self-signed certs (localhost + 127.0.0.1 SANs; reqwest needs | ||
| `danger_accept_invalid_certs`): HTTPS round-trip, HTTP-to-TLS-port failure, | ||
| redirect Location assertion, config-driven bare `secured`, dual HTTP+HTTPS, | ||
| and both actionable error paths. | ||
| - `scripts/run_web_tests.sh` / `.ps1` — new TLS section generating a cert | ||
| with openssl and driving `TestPrograms/web_server_tls.wfl` (CI-SKIP'd in | ||
| the plain integration run) with curl. Readiness is probed via the redirect | ||
| port so the probe doesn't consume the program's single `wait for request`. | ||
|
|
||
| ## Known limitations | ||
|
|
||
| - Application-level responses remain sequential per server (existing | ||
| behavior); TLS handshakes are concurrent inside warp. | ||
| - The JS transpiler emits a warning for `secured`/`redirecting` listens and | ||
| generates a plain `http` server. | ||
| - Exotic merged-identifier shapes (e.g. a port expression like | ||
| `base_port plus offset secured`) aren't recognized; use a simple variable | ||
| or literal port with the `secured` clause. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.