docs(lib): define the VISION and TENETS
This commit is contained in:
100
docs/TENETS.md
Normal file
100
docs/TENETS.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Charter
|
||||||
|
|
||||||
|
> hyper is a protective and efficient HTTP library for all.
|
||||||
|
|
||||||
|
# Tenets
|
||||||
|
|
||||||
|
Tenets are guiding principles. They guide how decisions are made for the whole
|
||||||
|
project. Ideally, we do all of them all the time. In some cases, though, we may
|
||||||
|
be forced to decide between slightly penalizing one goal or another. In that
|
||||||
|
case, we tend to support those goals that come earlier in the list over those
|
||||||
|
that come later (but every case is different).
|
||||||
|
|
||||||
|
## 0. Open
|
||||||
|
|
||||||
|
hyper is open source, always. The success of hyper depends on the health of the
|
||||||
|
community building and using it. All contributions are in the open. We don't
|
||||||
|
maintain private versions, and don't include features that aren't useful to
|
||||||
|
others.
|
||||||
|
|
||||||
|
[We prioritize kindness][CONDUCT], compassion and empathy towards all
|
||||||
|
contributors. Technical skill is not a substitute for human decency.
|
||||||
|
|
||||||
|
[CONDUCT]: https://github.com/hyperium/hyper/blob/master/docs/CODE_OF_CONDUCT.md
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
It's not usually hard for an open source library to stay open and also meet its
|
||||||
|
other priorities. Here's some instances where being **Open** would be more
|
||||||
|
important than **Correct** or **Fast**:
|
||||||
|
|
||||||
|
- Say an individual were to bring forward a contribution that makes hyper more
|
||||||
|
correct, or faster, perhaps fixing some serious bug. But in doing so, they
|
||||||
|
also insulted people, harrassed other contributors or users, or shamed
|
||||||
|
everyone for the previous code. They felt their contribution was "invaluable".
|
||||||
|
We would not accept such a contribution, instead banning the user and
|
||||||
|
rewriting the code amongst the kind collaborators of the project.
|
||||||
|
|
||||||
|
- Say someone brings a contribution that adds a new feature useful for
|
||||||
|
performance or correctness, but their work accomplishes this by integrating
|
||||||
|
hyper with a proprietary library. We would not accept such a contribution,
|
||||||
|
because we don't want such a feature limited only to those users willing to
|
||||||
|
compromise openness, and we don't want to bifurcate the ecosystem between those
|
||||||
|
who make that compromise and those who don't.
|
||||||
|
|
||||||
|
## 1. Correct
|
||||||
|
|
||||||
|
hyper is a memory safe and precise implementation of the HTTP specification.
|
||||||
|
Memory safety is vital in a core Internet technology. Following the HTTP
|
||||||
|
specifications correctly protects users. It makes the software durable to the
|
||||||
|
“real world”. Where feasible, hyper enforces correct usage.
|
||||||
|
|
||||||
|
This is more than just "don't write bugs". hyper actively protects the user.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
- Even though we follow the **HTTP/\*** specs, hyper doesn't blindly implement
|
||||||
|
everything without considering if it is safe to do so.
|
||||||
|
|
||||||
|
## 2. Fast
|
||||||
|
|
||||||
|
A fast experience delights users. A faster network library means a faster
|
||||||
|
application, resulting in delighting our users’ users. Whether with one request,
|
||||||
|
or millions.
|
||||||
|
|
||||||
|
Being _fast_ means we improve throughput, drive down CPU usage, and improve
|
||||||
|
sustainability.
|
||||||
|
|
||||||
|
Fast _enough_. We don't sacrifice sanity for speed.
|
||||||
|
|
||||||
|
## 3. HTTP/*
|
||||||
|
|
||||||
|
hyper is specifically focused on HTTP. Supporting new HTTP versions is in scope,
|
||||||
|
but supporting separate protocols is not.
|
||||||
|
|
||||||
|
This also defines what the abstraction layer is: the API is designed around
|
||||||
|
sending and receiving HTTP messages.
|
||||||
|
|
||||||
|
## 4. Flexible
|
||||||
|
|
||||||
|
hyper enables as many usecases as possible. It has no opinion on application
|
||||||
|
structure, and makes few assumptions about its environment. This includes being
|
||||||
|
portable to different operating systems.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
- While we choose safer defaults to be **Correct**, hyper includes options to
|
||||||
|
_allow_ different behavior, when the user requires them.
|
||||||
|
- Providing choice usually makes things more complex, so being **Flexible** does
|
||||||
|
mean it's less _easy_. That can sometimes conflict with simplest way of making
|
||||||
|
hyper **Understandable**.
|
||||||
|
|
||||||
|
## 5. Understandable
|
||||||
|
|
||||||
|
hyper is [no more complicated than it has to
|
||||||
|
be](https://en.wikipedia.org/wiki/Occam%27s_razor). HTTP is not simple. It may
|
||||||
|
not be as "easy" as 1-line to do everything, but it shouldn't be "hard" to find
|
||||||
|
the answers.
|
||||||
|
|
||||||
|
From logical and misuse-resistant APIs, to stellar documentation, to transparent
|
||||||
|
metrics.
|
||||||
230
docs/VISION.md
Normal file
230
docs/VISION.md
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
# hyper Vision
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
This is an overview of what the shape of hyper looks like, but also somewhat
|
||||||
|
zoomed out, so that the _vision_ can survive while the exact minute details
|
||||||
|
might shift and change over time.
|
||||||
|
|
||||||
|
### Charter
|
||||||
|
|
||||||
|
> hyper is a protective and efficient HTTP library for all.
|
||||||
|
|
||||||
|
### Tenets
|
||||||
|
|
||||||
|
Tenets are guiding principles. They guide how decisions are made for the whole
|
||||||
|
project. Ideally, we do all of them all the time. In some cases, though, we may
|
||||||
|
be forced to decide between slightly penalizing one goal or another. In that
|
||||||
|
case, we tend to support those goals that come earlier in the list over those
|
||||||
|
that come later (but every case is different).
|
||||||
|
|
||||||
|
0. Open
|
||||||
|
1. Correct
|
||||||
|
2. Fast
|
||||||
|
3. HTTP/\*
|
||||||
|
4. Flexible
|
||||||
|
5. Understandable
|
||||||
|
|
||||||
|
There's a lot more detail about each in [TENETS](./TENETS.md).
|
||||||
|
|
||||||
|
## Use Cases
|
||||||
|
|
||||||
|
Who are the *users* of hyper? How would they use hyper?
|
||||||
|
|
||||||
|
### Low-Level Client Library (curl, reqwest, aws-sdk)
|
||||||
|
|
||||||
|
These client libraries care that hyper is **Flexible**, since they are
|
||||||
|
expressing their own opinion on how a more-featured HTTP client should act.
|
||||||
|
This includes opinions on connection establishment, management, pooling, HTTP
|
||||||
|
version options, and even runtimes.
|
||||||
|
|
||||||
|
curl's main reason for using hyper is that it is **Safe**.
|
||||||
|
|
||||||
|
### Web Server Frameworks (deno, axum)
|
||||||
|
|
||||||
|
These are using hyper's server feature to expose a different, higher-level API
|
||||||
|
to users. Besides the obvious requirements, these require that hyper is
|
||||||
|
**Fast**. Servers are costly, handling more requests faster is important to
|
||||||
|
them.
|
||||||
|
|
||||||
|
That hyper is **Flexible** is also important, in that it needs to be flexible
|
||||||
|
enough for them to build a server framework, and allow them to express their
|
||||||
|
own opinions about API to their users.
|
||||||
|
|
||||||
|
### Services and Proxies (linkerd, cloudflare, fastly)
|
||||||
|
|
||||||
|
These are using hyper directly, likely both the client and server, in order to
|
||||||
|
build efficient and powerful services, applications, and tools for their end
|
||||||
|
users. They care greatly that hyper is **Correct**, since web traffic can
|
||||||
|
stretch the limits of what is valid HTTP, and exercise less-common parts of the
|
||||||
|
specifications.
|
||||||
|
|
||||||
|
They also require hyper to be **Fast**, for similar reasons that the web server
|
||||||
|
frameworks do.
|
||||||
|
|
||||||
|
### New Rust Web Developers
|
||||||
|
|
||||||
|
These are developers who are either new to Rust, or new to web servers, and
|
||||||
|
have reached for hyper to start with.
|
||||||
|
|
||||||
|
It's likely that these users don't have strong opinions about how an HTTP
|
||||||
|
server or client should work, just that it _should_ handle all the things they
|
||||||
|
normally assume it would. For these users, it would be best to quickly help
|
||||||
|
them compare their own expectations with hyper's capabitilities, and may
|
||||||
|
suggest reaching for higher-level, _easier_ libraries instead.
|
||||||
|
|
||||||
|
Those that stick around after that recommendation are users that wish both to
|
||||||
|
learn at a lower level, and to pick and choose what batteries they plug in to
|
||||||
|
hyper as they move along. While they do care about the other tenets, that hyper
|
||||||
|
is **Understandable** is of extra importance to them.
|
||||||
|
|
||||||
|
## The Library
|
||||||
|
|
||||||
|
So with all that context in mind, what does hyper, the library, actually look
|
||||||
|
like? This doesn't highlight what _is_ and _isn't_ present. What currently
|
||||||
|
needs to change to reach this vision is left to individual version roadmaps.
|
||||||
|
|
||||||
|
### Layers
|
||||||
|
|
||||||
|
In all cases, a user brings their own runtime and IO to work with hyper. The IO
|
||||||
|
is provided to hyper, and hyper acts on top of it. hyper returns `Future`s that
|
||||||
|
the user then decides how to poll, likely involving their runtime options.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
#### Protocol Codecs
|
||||||
|
|
||||||
|
hyper has dedicated codecs for the major HTTP versions. Each is internally
|
||||||
|
designed to be **Correct** and **Fast** when it comes to encoding and decoding.
|
||||||
|
|
||||||
|
The individual codecs may be implemented as sub-crates, with a less-stable
|
||||||
|
promise, to support the **Flexible** needs of some users who wish to build
|
||||||
|
their own connection management, or customize encoding and decoding beyond what
|
||||||
|
is officially supported.
|
||||||
|
|
||||||
|
#### Connection State Management
|
||||||
|
|
||||||
|
A **Correct** implementation includes more than just enforcing certain
|
||||||
|
characters when encoding and decoding. Order of frames, and flags in certain
|
||||||
|
frames can affect the state of the connection. Some examples of things enforced
|
||||||
|
at this layer:
|
||||||
|
|
||||||
|
- If a message has a `content-length`, enforce only that many bytes are read or
|
||||||
|
written.
|
||||||
|
- Reading a `Response` before a `Request` is even written implies a mismatched
|
||||||
|
reply that should be interpreted as an error.
|
||||||
|
- The presence of some headers, such as `Connection: close`, or the absence of
|
||||||
|
others, such as `content-length` and `transfer-encoding`, can mean that the
|
||||||
|
connection should terminate after the current message.
|
||||||
|
- HTTP/2 and HTTP/3 may send connection-level frames that don't pertain to any
|
||||||
|
specific transaction, and must be read and handled regardless of if a user is
|
||||||
|
currently checking for a message.
|
||||||
|
|
||||||
|
#### HTTP Role and Version Abstraction
|
||||||
|
|
||||||
|
This is the public API layer. Methods exposed are around sending and receiving
|
||||||
|
`http::Request`s and `http::Response`s, not around framing specifics of the
|
||||||
|
different versions. These are built around a client or server `Connection`
|
||||||
|
interface.
|
||||||
|
|
||||||
|
By exposing this layer publicly, we take care of the **Correct** tenet, by not
|
||||||
|
forcing the user to send the specific frames themselves. The API should be
|
||||||
|
designed in a way that a user cannot easily (if at all) create an _incorrect_
|
||||||
|
HTTP connection.
|
||||||
|
|
||||||
|
Motivated by the **Flexible** tenet, there _are_ version-specific options that
|
||||||
|
can be configured at this level, and version-specific functionality can usually
|
||||||
|
be handled via `http::Extensions`.
|
||||||
|
|
||||||
|
### Not quite stable, but utile (useful)
|
||||||
|
|
||||||
|
Beyond what is directly in the hyper crate, there are useful (utile) parts that
|
||||||
|
may not meet hyper's stability promise. Developing, experimenting, and exposing
|
||||||
|
those parts is the purpose of the `hyper-util` crate. That crate does not have
|
||||||
|
the same stability level as hyper. However, the goal is that things that other
|
||||||
|
libraries might want to expose as a public dependency do not live in
|
||||||
|
`hyper-util` forever, but rather stabilize and get promoted into `hyper`.
|
||||||
|
|
||||||
|
Exactly what gets put into `hyper-util` presently is kept in the roadmap
|
||||||
|
documents.
|
||||||
|
|
||||||
|
### Stability Promise
|
||||||
|
|
||||||
|
What even is hyper's stability promise? Does it mean we are "done"? No. Will we
|
||||||
|
ever make breaking changes again? Probably. We'll still follow the [semantic
|
||||||
|
versioning](https://semver.org).
|
||||||
|
|
||||||
|
Prior to 1.0, hyper has already only done breaking changes once a year. So 1
|
||||||
|
year isn't much of a promise. We'll have significant more use and understanding
|
||||||
|
after a few years, and that could prompt some redesign.
|
||||||
|
|
||||||
|
As of this writing, we'll promise that _major_ versions of hyper are stable for
|
||||||
|
3 years. New features will come out in _minor_ versions frequently. If it is
|
||||||
|
determined necessary to make breaking changes to the API, we'll save them for
|
||||||
|
after the 3 years.
|
||||||
|
|
||||||
|
hyper also establishes a Minimum Supported Rust Version (MSRV). hyper will
|
||||||
|
support Rust versions at least 6 months old. If a new Rust version is released
|
||||||
|
with a feature hyper wishes to use, we won't do so until at least 6 months
|
||||||
|
afterwards. hyper will only ever require a new Rust version as a _minor_
|
||||||
|
release (1.x), not as a patch (1.x.y).
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
The security of hyper is a large part of what makes hyper _protective_. We make
|
||||||
|
hyper secure via the combined efforts of being **Correct**, focusing on
|
||||||
|
**HTTP/\***, and making it all **Understandable**.
|
||||||
|
|
||||||
|
### Memory Safety
|
||||||
|
|
||||||
|
Being **Correct** requires that hyper be memory-safe. Using the Rust language
|
||||||
|
gets us most of the way there. But there is the ability to write `unsafe`
|
||||||
|
Rust. Does being **Correct** mean that we can _never_ write `unsafe` code
|
||||||
|
anywhere? Even if it helps make hyper **Fast**? We can, carefully.
|
||||||
|
|
||||||
|
How do we balance the two, so that hyper is secure?
|
||||||
|
|
||||||
|
hyper prefers not to have large modules of intertwined `unsafe` code. hyper
|
||||||
|
does allow small `unsafe` blocks, no more than a few lines, where it's easier
|
||||||
|
to verify that the `unsafe` code was written **Correctly**.
|
||||||
|
|
||||||
|
### Meticulous Testing
|
||||||
|
|
||||||
|
hyper's test suite grows and grows. There's a lot that needs to be right.
|
||||||
|
Parsers, encoders, state machines. When easily isolated, those pieces have
|
||||||
|
internal unit tests. But hyper also keeps a large list of growing integration
|
||||||
|
tests that make sure all the parts are **Correct**.
|
||||||
|
|
||||||
|
Making writing new tests easy is a high priority. Investing in the testing
|
||||||
|
infrastructure is a proven way to make sure hyper stays **Correct** and secure.
|
||||||
|
|
||||||
|
### Constant Fuzzing
|
||||||
|
|
||||||
|
One thing is to know specific cases to test for. But we can't know all the
|
||||||
|
inputs or states that *might* cause a bug. That's why hyper has rounds of
|
||||||
|
fuzzing built into its CI. It's also why hyper signs up for and uses resources
|
||||||
|
to provide *constant*, around-the-clock fuzzing, always looking for something
|
||||||
|
that hyper should be hardened against.
|
||||||
|
|
||||||
|
### Security Process
|
||||||
|
|
||||||
|
hyper has an outlined
|
||||||
|
[SECURITY](https://github.com/hyperium/hyper/blob/master/SECURITY.md) process,
|
||||||
|
so we can safely report and fix issues.
|
||||||
|
|
||||||
|
## Non-goals
|
||||||
|
|
||||||
|
After writing this up, it is easier to articulate what sorts of things many
|
||||||
|
might associate with an HTTP library, but which are explicitly *not* for hyper.
|
||||||
|
These are all things that definitely **out of scope**.
|
||||||
|
|
||||||
|
- TLS: We learned early that bundling TLS directly in hyper [has
|
||||||
|
problems](https://github.com/hyperium/hyper/issues/985). People also have
|
||||||
|
very strong opinions about which TLS implementation to use. The design of
|
||||||
|
hyper allows users to bring their own TLS.
|
||||||
|
- Routing
|
||||||
|
- Cookies
|
||||||
|
- Not-HTTP: WebSockets, or other protocols that are built next to HTTP. It
|
||||||
|
should be possible to _use_ hyper to upgrade, but the actual next-protocol
|
||||||
|
should be handled by a different library.
|
||||||
4
docs/vision-arch.svg
Normal file
4
docs/vision-arch.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.7 KiB |
Reference in New Issue
Block a user