Skip to content

Commit 311ba2b

Browse files
committed
docs(lib): define the VISION and TENETS
1 parent 1d895b8 commit 311ba2b

File tree

3 files changed

+334
-0
lines changed

3 files changed

+334
-0
lines changed

docs/TENETS.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Charter
2+
3+
> hyper is a protective and efficient HTTP library for all.
4+
5+
# Tenets
6+
7+
Tenets are guiding principles. They guide how decisions are made for the whole
8+
project. Ideally, we do all of them all the time. In some cases, though, we may
9+
be forced to decide between slightly penalizing one goal or another. In that
10+
case, we tend to support those goals that come earlier in the list over those
11+
that come later (but every case is different).
12+
13+
## 0. Open
14+
15+
hyper is open source, always. The success of hyper depends on the health of the
16+
community building and using it. All contributions are in the open. We don't
17+
maintain private versions, and don't include features that aren't useful to
18+
others.
19+
20+
[We prioritize kindness][CONDUCT], compassion and empathy towards all
21+
contributors. Technical skill is not a substitute for human decency.
22+
23+
[CONDUCT]: https://github.com/hyperium/hyper/blob/master/docs/CODE_OF_CONDUCT.md
24+
25+
### Examples
26+
27+
It's not usually hard for an open source library to stay open and also meet its
28+
other priorities. Here's some instances where being **Open** would be more
29+
important than **Correct** or **Fast**:
30+
31+
- Say an individual were to bring forward a contribution that makes hyper more
32+
correct, or faster, perhaps fixing some serious bug. But in doing so, they
33+
also insulted people, harrassed other contributors or users, or shamed
34+
everyone for the previous code. They felt their contribution was "invaluable".
35+
We would not accept such a contribution, instead banning the user and
36+
rewriting the code amongst the kind collaborators of the project.
37+
38+
- Say someone brings a contribution that adds a new feature useful for
39+
performance or correctness, but their work accomplishes this by integrating
40+
hyper with a proprietary library. We would not accept such a contribution,
41+
because we don't want such a feature limited only to those users willing to
42+
compromise openness, and we don't want to bifurcate the ecosystem between those
43+
who make that compromise and those who don't.
44+
45+
## 1. Correct
46+
47+
hyper is a memory safe and precise implementation of the HTTP specification.
48+
Memory safety is vital in a core Internet technology. Following the HTTP
49+
specifications correctly protects users. It makes the software durable to the
50+
“real world”. Where feasible, hyper enforces correct usage.
51+
52+
This is more than just "don't write bugs". hyper actively protects the user.
53+
54+
### Examples
55+
56+
- Even though we follow the **HTTP/\*** specs, hyper doesn't blindly implement
57+
everything without considering if it is safe to do so.
58+
59+
## 2. Fast
60+
61+
A fast experience delights users. A faster network library means a faster
62+
application, resulting in delighting our users’ users. Whether with one request,
63+
or millions.
64+
65+
Being _fast_ means we improve throughput, drive down CPU usage, and improve
66+
sustainability.
67+
68+
Fast _enough_. We don't sacrifice sanity for speed.
69+
70+
## 3. HTTP/*
71+
72+
hyper is specifically focused on HTTP. Supporting new HTTP versions is in scope,
73+
but supporting separate protocols is not.
74+
75+
This also defines what the abstraction layer is: the API is designed around
76+
sending and receiving HTTP messages.
77+
78+
## 4. Flexible
79+
80+
hyper enables as many usecases as possible. It has no opinion on application
81+
structure, and makes few assumptions about its environment. This includes being
82+
portable to different operating systems.
83+
84+
### Examples
85+
86+
- While we choose safer defaults to be **Correct**, hyper includes options to
87+
_allow_ different behavior, when the user requires them.
88+
- Providing choice usually makes things more complex, so being **Flexible** does
89+
mean it's less _easy_. That can sometimes conflict with simplest way of making
90+
hyper **Understandable**.
91+
92+
## 5. Understandable
93+
94+
hyper is [no more complicated than it has to
95+
be](https://en.wikipedia.org/wiki/Occam%27s_razor). HTTP is not simple. It may
96+
not be as "easy" as 1-line to do everything, but it shouldn't be "hard" to find
97+
the answers.
98+
99+
From logical and misuse-resistant APIs, to stellar documentation, to transparent
100+
metrics.

docs/VISION.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
# hyper Vision
2+
3+
## Purpose
4+
5+
This is an overview of what the shape of hyper looks like, but also somewhat
6+
zoomed out, so that the _vision_ can survive while the exact minute details
7+
might shift and change over time.
8+
9+
### Charter
10+
11+
> hyper is a protective and efficient HTTP library for all.
12+
13+
### Tenets
14+
15+
Tenets are guiding principles. They guide how decisions are made for the whole
16+
project. Ideally, we do all of them all the time. In some cases, though, we may
17+
be forced to decide between slightly penalizing one goal or another. In that
18+
case, we tend to support those goals that come earlier in the list over those
19+
that come later (but every case is different).
20+
21+
0. Open
22+
1. Correct
23+
2. Fast
24+
3. HTTP/\*
25+
4. Flexible
26+
5. Understandable
27+
28+
There's a lot more detail about each in [TENETS](./TENETS.md).
29+
30+
## Use Cases
31+
32+
Who are the *users* of hyper? How would they use hyper?
33+
34+
### Low-Level Client Library (curl, reqwest, aws-sdk)
35+
36+
These client libraries care that hyper is **Flexible**, since they are
37+
expressing their own opinion on how a more-featured HTTP client should act.
38+
This includes opinions on connection establishment, management, pooling, HTTP
39+
version options, and even runtimes.
40+
41+
curl's main reason for using hyper is that it is **Safe**.
42+
43+
### Web Server Frameworks (deno, axum)
44+
45+
These are using hyper's server feature to expose a different, higher-level API
46+
to users. Besides the obvious requirements, these require that hyper is
47+
**Fast**. Servers are costly, handling more requests faster is important to
48+
them.
49+
50+
That hyper is **Flexible** is also important, in that it needs to be flexible
51+
enough for them to build a server framework, and allow them to express their
52+
own opinions about API to their users.
53+
54+
### Services and Proxies (linkerd, cloudflare, fastly)
55+
56+
These are using hyper directly, likely both the client and server, in order to
57+
build efficient and powerful services, applications, and tools for their end
58+
users. They care greatly that hyper is **Correct**, since web traffic can
59+
stretch the limits of what is valid HTTP, and exercise less-common parts of the
60+
specifications.
61+
62+
They also require hyper to be **Fast**, for similar reasons that the web server
63+
frameworks do.
64+
65+
### New Rust Web Developers
66+
67+
These are developers who are either new to Rust, or new to web servers, and
68+
have reached for hyper to start with.
69+
70+
It's likely that these users don't have strong opinions about how an HTTP
71+
server or client should work, just that it _should_ handle all the things they
72+
normally assume it would. For these users, it would be best to quickly help
73+
them compare their own expectations with hyper's capabitilities, and may
74+
suggest reaching for higher-level, _easier_ libraries instead.
75+
76+
Those that stick around after that recommendation are users that wish both to
77+
learn at a lower level, and to pick and choose what batteries they plug in to
78+
hyper as they move along. While they do care about the other tenets, that hyper
79+
is **Understandable** is of extra importance to them.
80+
81+
## The Library
82+
83+
So with all that context in mind, what does hyper, the library, actually look
84+
like? This doesn't highlight what _is_ and _isn't_ present. What currently
85+
needs to change to reach this vision is left to individual version roadmaps.
86+
87+
### Layers
88+
89+
In all cases, a user brings their own runtime and IO to work with hyper. The IO
90+
is provided to hyper, and hyper acts on top of it. hyper returns `Future`s that
91+
the user then decides how to poll, likely involving their runtime options.
92+
93+
![architecture diagram](./vision-arch.svg)
94+
95+
96+
#### Protocol Codecs
97+
98+
hyper has dedicated codecs for the major HTTP versions. Each is internally
99+
designed to be **Correct** and **Fast** when it comes to encoding and decoding.
100+
101+
The individual codecs may be implemented as sub-crates, with a less-stable
102+
promise, to support the **Flexible** needs of some users who wish to build
103+
their own connection management, or customize encoding and decoding beyond what
104+
is officially supported.
105+
106+
#### Connection State Management
107+
108+
A **Correct** implementation includes more than just enforcing certain
109+
characters when encoding and decoding. Order of frames, and flags in certain
110+
frames can affect the state of the connection. Some examples of things enforced
111+
at this layer:
112+
113+
- If a message has a `content-length`, enforce only that many bytes are read or
114+
written.
115+
- Reading a `Response` before a `Request` is even written implies a mismatched
116+
reply that should be interpreted as an error.
117+
- The presence of some headers, such as `Connection: close`, or the absence of
118+
others, such as `content-length` and `transfer-encoding`, can mean that the
119+
connection should terminate after the current message.
120+
- HTTP/2 and HTTP/3 may send connection-level frames that don't pertain to any
121+
specific transaction, and must be read and handled regardless of if a user is
122+
currently checking for a message.
123+
124+
#### HTTP Role and Version Abstraction
125+
126+
This is the public API layer. Methods exposed are around sending and receiving
127+
`http::Request`s and `http::Response`s, not around framing specifics of the
128+
different versions. These are built around a client or server `Connection`
129+
interface.
130+
131+
By exposing this layer publicly, we take care of the **Correct** tenet, by not
132+
forcing the user to send the specific frames themselves. The API should be
133+
designed in a way that a user cannot easily (if at all) create an _incorrect_
134+
HTTP connection.
135+
136+
Motivated by the **Flexible** tenet, there _are_ version-specific options that
137+
can be configured at this level, and version-specific functionality can usually
138+
be handled via `http::Extensions`.
139+
140+
### Not quite stable, but utile (useful)
141+
142+
Beyond what is directly in the hyper crate, there are useful (utile) parts that
143+
may not meet hyper's stability promise. Developing, experimenting, and exposing
144+
those parts is the purpose of the `hyper-util` crate. That crate does not have
145+
the same stability level as hyper. However, the goal is that things that other
146+
libraries might want to expose as a public dependency do not live in
147+
`hyper-util` forever, but rather stabilize and get promoted into `hyper`.
148+
149+
Exactly what gets put into `hyper-util` presently is kept in the roadmap
150+
documents.
151+
152+
### Stability Promise
153+
154+
What even is hyper's stability promise? Does it mean we are "done"? No. Will we
155+
ever make breaking changes again? Probably. We'll still follow the [semantic
156+
versioning](https://semver.org).
157+
158+
Prior to 1.0, hyper has already only done breaking changes once a year. So 1
159+
year isn't much of a promise. We'll have significant more use and understanding
160+
after a few years, and that could prompt some redesign.
161+
162+
As of this writing, we'll promise that _major_ versions of hyper are stable for
163+
3 years. New features will come out in _minor_ versions frequently. If it is
164+
determined necessary to make breaking changes to the API, we'll save them for
165+
after the 3 years.
166+
167+
hyper also establishes a Minimum Supported Rust Version (MSRV). hyper will
168+
support Rust versions at least 6 months old. If a new Rust version is released
169+
with a feature hyper wishes to use, we won't do so until at least 6 months
170+
afterwards. hyper will only ever require a new Rust version as a _minor_
171+
release (1.x), not as a patch (1.x.y).
172+
173+
## Security
174+
175+
The security of hyper is a large part of what makes hyper _protective_. We make
176+
hyper secure via the combined efforts of being **Correct**, focusing on
177+
**HTTP/\***, and making it all **Understandable**.
178+
179+
### Memory Safety
180+
181+
Being **Correct** requires that hyper be memory-safe. Using the Rust language
182+
gets us most of the way there. But there is the ability to write `unsafe`
183+
Rust. Does being **Correct** mean that we can _never_ write `unsafe` code
184+
anywhere? Even if it helps make hyper **Fast**? We can, carefully.
185+
186+
How do we balance the two, so that hyper is secure?
187+
188+
hyper prefers not to have large modules of intertwined `unsafe` code. hyper
189+
does allow small `unsafe` blocks, no more than a few lines, where it's easier
190+
to verify that the `unsafe` code was written **Correctly**.
191+
192+
### Meticulous Testing
193+
194+
hyper's test suite grows and grows. There's a lot that needs to be right.
195+
Parsers, encoders, state machines. When easily isolated, those pieces have
196+
internal unit tests. But hyper also keeps a large list of growing integration
197+
tests that make sure all the parts are **Correct**.
198+
199+
Making writing new tests easy is a high priority. Investing in the testing
200+
infrastructure is a proven way to make sure hyper stays **Correct** and secure.
201+
202+
### Constant Fuzzing
203+
204+
One thing is to know specific cases to test for. But we can't know all the
205+
inputs or states that *might* cause a bug. That's why hyper has rounds of
206+
fuzzing built into its CI. It's also why hyper signs up for and uses resources
207+
to provide *constant*, around-the-clock fuzzing, always looking for something
208+
that hyper should be hardened against.
209+
210+
### Security Process
211+
212+
hyper has an outlined
213+
[SECURITY](https://github.com/hyperium/hyper/blob/master/SECURITY.md) process,
214+
so we can safely report and fix issues.
215+
216+
## Non-goals
217+
218+
After writing this up, it is easier to articulate what sorts of things many
219+
might associate with an HTTP library, but which are explicitly *not* for hyper.
220+
These are all things that definitely **out of scope**.
221+
222+
- TLS: We learned early that bundling TLS directly in hyper [has
223+
problems](https://github.com/hyperium/hyper/issues/985). People also have
224+
very strong opinions about which TLS implementation to use. The design of
225+
hyper allows users to bring their own TLS.
226+
- Routing
227+
- Cookies
228+
- Not-HTTP: WebSockets, or other protocols that are built next to HTTP. It
229+
should be possible to _use_ hyper to upgrade, but the actual next-protocol
230+
should be handled by a different library.

0 commit comments

Comments
 (0)