1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Serving the API over HTTPS (issue #300).
//!
//! # Why this exists at all
//!
//! The browser console at `https://leviath.dev/lair` cannot call a `lev serve`
//! that is not on loopback. Browsers block a mixed-content request *inside the
//! browser*, before it is sent - so the server never sees it and no response
//! header lifts it. `--cors` is not involved and cannot help.
//!
//! Loopback is the only exemption, and this is the part that surprises people:
//! `http://localhost` is treated as potentially trustworthy, and
//! `http://192.168.1.50:3000` is blocked exactly like a public address.
//!
//! # Bring your own certificate
//!
//! Nothing here generates one. A self-signed certificate made on the user's
//! behalf would not fix the console anyway - a subresource `fetch` gets no
//! interstitial to click through - so it would make `lev serve` look secure
//! while teaching people to click past TLS warnings. `mkcert` and
//! `tailscale cert` both produce certificates that actually work; the docs
//! explain which to reach for.
use PathBuf;
use ;
/// A certificate and its key, both present.
///
/// Constructing one is the only way to reach the HTTPS path, which is what
/// makes "one flag without the other" unrepresentable rather than a check
/// somebody has to remember.
/// Decide whether to serve HTTPS, from the two flags.
///
/// One flag without the other is an error rather than a silent fallback to
/// HTTP. Falling back would start a server on the scheme the user did not ask
/// for, and they would find out from a mixed-content error in a browser on
/// another machine - which is the failure this whole feature exists to end.
/// The URL scheme the server will actually answer on.
///
/// Used for the startup banner, which matters more than it looks: the line it
/// prints is the URL a user copies into the console, and a banner saying
/// `http://` for an HTTPS server sends them to an endpoint that cannot work.
/// Read the certificate and key into a server config.
///
/// Fails before the listener is bound. A server that binds and then rejects
/// every handshake looks like a network problem from the other machine and is
/// far harder to diagnose than one that refuses to start with a message naming
/// the file it could not read.
///
/// The error names the path, because "invalid certificate" without one is
/// unactionable when two files were supplied.
pub async
pub