mirror of
https://github.com/Noratrieb/icefun.git
synced 2026-01-14 12:55:02 +01:00
private
This commit is contained in:
parent
25adea4103
commit
7af1274587
160 changed files with 38999 additions and 4 deletions
21
hyper/docs/CODE_OF_CONDUCT.md
Normal file
21
hyper/docs/CODE_OF_CONDUCT.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Code of Conduct
|
||||
|
||||
## Be Kind
|
||||
|
||||
- Don't be mean.
|
||||
- Insulting anyone is prohibited.
|
||||
- Harassment of any kind is prohibited.
|
||||
- If another person feels uncomfortable with your remarks, stop it.
|
||||
- If a moderator deems your comment or conduct as inappropriate, stop it.
|
||||
- Disagreeing is fine, but keep it to technical arguments. Never attack the person.
|
||||
- Give the benefit of the doubt. Assume good intentions.
|
||||
- Show empathy. There are 3 interpretations to any message: what we thought, what we said, and what they understand.
|
||||
- This does mean we exclude people who are not kind. We are happy to make that sacrifice.
|
||||
|
||||
## Or Else
|
||||
|
||||
- Violations of the Code of Conduct will result in 1 warning.
|
||||
- If the violation is major, a moderator may just ban immediately.
|
||||
- If a warning has already been given, a moderator will ban the offender.
|
||||
- There is no process for appealing a ban.
|
||||
- Any violations can be reported to sean@seanmonstar.com.
|
||||
65
hyper/docs/COMMITS.md
Normal file
65
hyper/docs/COMMITS.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Git Commit Guidelines
|
||||
|
||||
We have very precise rules over how our git commit messages can be formatted. This leads to **more
|
||||
readable messages** that are easy to follow when looking through the **project history**. But also,
|
||||
we use the git commit messages to **generate the change log**.
|
||||
|
||||
## Commit Message Format
|
||||
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
|
||||
format that includes a **type**, a **scope** and a **subject**:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||
to read on github as well as in various git tools.
|
||||
|
||||
## Type
|
||||
Must be one of the following:
|
||||
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
* **docs**: Documentation only changes
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
|
||||
semi-colons, etc)
|
||||
* **refactor**: A code change that neither fixes a bug or adds a feature
|
||||
* **perf**: A code change that improves performance
|
||||
* **test**: Adding missing tests
|
||||
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
|
||||
generation
|
||||
|
||||
## Scope
|
||||
The scope should refer to a module in hyper that is being touched. Examples:
|
||||
|
||||
* client
|
||||
* server
|
||||
* http1
|
||||
* http2
|
||||
* ffi
|
||||
* upgrade
|
||||
* examples
|
||||
|
||||
## Subject
|
||||
|
||||
The subject contains succinct description of the change:
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
## Body
|
||||
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
|
||||
## Footer
|
||||
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
|
||||
The last line of commits introducing breaking changes should be in the form `BREAKING CHANGE: <desc>`
|
||||
113
hyper/docs/ISSUES.md
Normal file
113
hyper/docs/ISSUES.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# Issues
|
||||
|
||||
The [issue tracker][issues] for hyper is where we track all features, bugs, and discuss proposals.
|
||||
|
||||
## Triaging
|
||||
|
||||
Once an issue has been opened, it is normal for there to be discussion
|
||||
around it. Some contributors may have differing opinions about the issue,
|
||||
including whether the behavior being seen is a bug or a feature. This
|
||||
discussion is part of the process and should be kept focused, helpful, and
|
||||
professional.
|
||||
|
||||
The objective of helping with triaging issues is to help reduce the issue
|
||||
backlog and keep the issue tracker healthy, while enabling newcomers another
|
||||
meaningful way to get engaged and contribute.
|
||||
|
||||
### Acknowledge
|
||||
|
||||
Acknowledge the human. This is meant actively, such as giving a welcome, or
|
||||
thanks for a detailed report, or any other greeting that makes the person feel
|
||||
that their contribution (issues are contributions!) is valued. It also is meant
|
||||
to be internalized, and be sure to always [treat the person kindly][COC]
|
||||
throughout the rest of the steps of triaging.
|
||||
|
||||
### Ask for more info
|
||||
|
||||
Frequently, we need more information than was originally provided to fully
|
||||
evaluate an issue.
|
||||
|
||||
If it is a bug report, ask follow up questions that help us get a [minimum
|
||||
reproducible example][MRE]. This may take several round-trip questions. Once
|
||||
all the details are gathered, it may be helpful to edit the original issue text
|
||||
to include them all.
|
||||
|
||||
### Categorize
|
||||
|
||||
Once enough information has been gathered, the issue should be categorized
|
||||
with [labels][#labels]. Ideally, most issues should be labelled with an area,
|
||||
effort, and severity. An issue _can_ have multiple areas, pick what fits. There
|
||||
should be only one severity, and the descriptions of each should help to pick
|
||||
the right one. The hardest label to select is "effort". If after reading the
|
||||
descriptions of each effort level, you're still unsure, you can ping a
|
||||
maintainer to pick one.
|
||||
|
||||
### Adjust the title
|
||||
|
||||
An optional step when triaging is to adjust the title once more information is
|
||||
known. Sometimes an issue starts as a question, and through discussion, it
|
||||
turns out to be a feature request, or a bug report. In those cases, the title
|
||||
should be changed from a question, and the title should be a succinct action to
|
||||
be taken. For example, a question about an non-existent configuration option
|
||||
may be reworded to "Add option to Client to do Zed".
|
||||
|
||||
### Mentoring
|
||||
|
||||
The last part of triaging is to try to make the issue a learning experience.
|
||||
After a discussion with the reporter, it would be good to ask if they are now
|
||||
interested in submitting the change described in the issue.
|
||||
|
||||
Otherwise, it would be best to leave the issue with a series of steps for
|
||||
anyone else to try to write the change. That could be pointing out that a
|
||||
design proposal is needed, addressing certain points. Or, if the required
|
||||
changes are mostly know, a list of links to modules and functions where code
|
||||
needs to be changed, and to what. That way we mentor newcomers to become
|
||||
successful contributors of new [pull requests][PRs].
|
||||
|
||||
## Labels
|
||||
|
||||
Issues are organized with a set of labels. Most labels follow a system of being prefixed by a "type".
|
||||
|
||||
### Area
|
||||
|
||||
The area labels describe what part of hyper is relevant.
|
||||
|
||||
- **A-body**: streaming request and response bodies.
|
||||
- **A-client**: the HTTP client.
|
||||
- **A-dependencies**: library dependencies.
|
||||
- **A-docs**: documentation.
|
||||
- **A-error**: error reporting and types.
|
||||
- **A-ffi**: the C API.
|
||||
- **A-http1**: the HTTP/1 specifics.
|
||||
- **A-http2**: the HTTP/2 specifics.
|
||||
- **A-server**: the HTTP server.
|
||||
- **A-tests**: the unit and integration tests.
|
||||
|
||||
### Blocked
|
||||
|
||||
These labels indicate an issue is "blocked" for some reason.
|
||||
|
||||
- **B-breaking-change**: a breaking change that is waiting for the next semver-compatible release.
|
||||
- **B-rfc**: request for comments. More discussion is needed to explore the design.
|
||||
- **B-upstream**: waiting on something in a dependency or the compiler.
|
||||
|
||||
### Effort
|
||||
|
||||
The effort labels are a best-guess at roughly how much effort and knowledge of hyper is needed to accomplish the task.
|
||||
|
||||
- **E-easy**: a great starting point for a new contributor.
|
||||
- **E-medium**: some knowledge of how hyper internals work would be useful.
|
||||
- **E-hard**: likely requires a deeper understanding of how hyper internals work.
|
||||
|
||||
### Severity
|
||||
|
||||
The severity marks how _severe_ the issue is. Note this isn't "importance" or "priority".
|
||||
|
||||
- **S-bug**: something is wrong, this is bad!
|
||||
- **S-feature**: this is a new feature request, adding something new.
|
||||
- **S-performance**: make existing working code go faster.
|
||||
- **S-refactor**: improve internal code to help readability and maintenance.
|
||||
|
||||
[issues]: https://github.com/hyperium/hyper/issues
|
||||
[COC]: ./CODE_OF_CONDUCT.md
|
||||
[PRs]: ./PULL_REQUESTS.md
|
||||
9
hyper/docs/MSRV.md
Normal file
9
hyper/docs/MSRV.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Minimum Support Rust Version (MSRV)
|
||||
|
||||
hyper's current policy is to always support a Rust version at least 6 months
|
||||
old. That is, a compiler version released within the last 6 months can compile
|
||||
hyper. It is possible that an older compiler can work, but that is not
|
||||
guaranteed. We try to increase the MSRV responsibly, only when a significant
|
||||
new feature is needed.
|
||||
|
||||
The current MSRV is: **1.56**.
|
||||
49
hyper/docs/PULL_REQUESTS.md
Normal file
49
hyper/docs/PULL_REQUESTS.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Pull Requests
|
||||
|
||||
Pull requests are the way to submit changes to the hyper repository.
|
||||
|
||||
## Submitting a Pull Request
|
||||
|
||||
In most cases, it a good idea to discuss a potential change in an
|
||||
[issue](ISSUES.md). This will allow other contributors to provide guidance and
|
||||
feedback _before_ significant code work is done, and can increase the
|
||||
likelihood of getting the pull request merged.
|
||||
|
||||
### Tests
|
||||
|
||||
If the change being proposed alters code (as opposed to only documentation for
|
||||
example), it is either adding new functionality to hyper or it is fixing
|
||||
existing, broken functionality. In both of these cases, the pull request should
|
||||
include one or more tests to ensure that hyper does not regress in the future.
|
||||
|
||||
### Commits
|
||||
|
||||
Once code, tests, and documentation have been written, a commit needs to be
|
||||
made. Following the [commit guidelines](COMMITS.md) will help with the review
|
||||
process by making your change easier to understand, and makes it easier for
|
||||
hyper to produce a valuable changelog with each release.
|
||||
|
||||
However, if your message doesn't perfectly match the guidelines, **do not
|
||||
worry!** The person that eventually merges can easily fixup the message at that
|
||||
time.
|
||||
|
||||
### Opening the Pull Request
|
||||
|
||||
From within GitHub, open a new pull request from your personal branch.
|
||||
|
||||
Once opened, pull requests are usually reviewed within a few days.
|
||||
|
||||
### Discuss and Update
|
||||
|
||||
You will probably get feedback or requests for changes to your Pull Request.
|
||||
This is a big part of the submission process so don't be discouraged! Some
|
||||
contributors may sign off on the Pull Request right away, others may have more
|
||||
detailed comments or feedback. This is a necessary part of the process in order
|
||||
to evaluate whether the changes are correct and necessary.
|
||||
|
||||
Any community member can review a PR and you might get conflicting feedback.
|
||||
Keep an eye out for comments from code owners to provide guidance on
|
||||
conflicting feedback.
|
||||
|
||||
You don't need to close the PR and create a new one to address feedback. You
|
||||
may simply push new commits to the existing branch.
|
||||
3
hyper/docs/README.md
Normal file
3
hyper/docs/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Developing hyper
|
||||
|
||||
This is a set of documents outline how hyper is developed, how to contribute or get involved, various processes we use, and internal design explanations.
|
||||
404
hyper/docs/ROADMAP.md
Normal file
404
hyper/docs/ROADMAP.md
Normal file
|
|
@ -0,0 +1,404 @@
|
|||
# hyper 1.0 Roadmap
|
||||
|
||||
## Goal
|
||||
|
||||
Align current hyper to the [hyper VISION][VISION].
|
||||
|
||||
The VISION outlines a decision-making framework, use-cases, and general shape
|
||||
of hyper. This roadmap describes the currently known problems with hyper, and
|
||||
then shows what changes are needed to make hyper 1.0 look more like what is in
|
||||
the VISION.
|
||||
|
||||
## Known Issues
|
||||
|
||||
|
||||
> **Note**: These known issues are as of hyper v0.14.x. After v1.0 is released,
|
||||
ideally these issues will have been solved. Keeping this history may be helpful
|
||||
to Future Us, though.
|
||||
|
||||
### Higher-level Client and Server problems
|
||||
|
||||
Both the higher-level `Client` and `Server` types have stability concerns.
|
||||
|
||||
For the `hyper::Server`:
|
||||
|
||||
- The `Accept` trait is complex, and too easy to get wrong. If used with TLS, a slow TLS handshake
|
||||
can affect all other new connections waiting for it to finish.
|
||||
- The `MakeService<&IO>` is confusing. The bounds are an assault on the eyes.
|
||||
- The `MakeService` API doesn't allow to easily annotate the HTTP connection with `tracing`.
|
||||
- Graceful shutdown doesn't give enough control.
|
||||
|
||||
|
||||
It's more common for people to simply use `hyper::server::conn` at this point,
|
||||
than to bother with the `hyper::Server`.
|
||||
|
||||
While the `hyper::Client` is much easier to use, problems still exist:
|
||||
|
||||
- The whole `Connect` design isn't stable.
|
||||
- ALPN and proxies can provide surprising extra configuration of connections.
|
||||
- Some `Connect` implementations may wish to view the path, in addition to the scheme, host, and port.
|
||||
- Wants `runtime` feature
|
||||
- The Pool could be made more general or composable. At the same time, more customization is
|
||||
desired, and it's not clear
|
||||
how to expose it yet.
|
||||
|
||||
|
||||
### Runtime woes
|
||||
|
||||
hyper has been able to support different runtimes, but it has sometimes awkward
|
||||
default support for Tokio.
|
||||
|
||||
- The `runtime` cargo-feature isn't additive
|
||||
- Built-in Tokio support can be confusing
|
||||
- Executors and Timers
|
||||
- The `runtime` feature currently enables a few options that require a timer, such as timeouts and
|
||||
keepalive intervals. It implicitly relies on Tokio's timer context. This can be quite confusing.
|
||||
- IO traits
|
||||
- Should we publicly depend on Tokio's traits?
|
||||
- `futures-io`?
|
||||
- Definitely nope.
|
||||
- Not stable. (0.3?)
|
||||
- No uninitialized memory.
|
||||
- Eventual `std` traits?
|
||||
- They've been in design for years.
|
||||
- We cannot base our schedule on them.
|
||||
- When they are stable, we can:
|
||||
- Provide a bridge in `hyper-util`.
|
||||
- Consider a 2.0 of hyper.
|
||||
- Define our own traits, provide util wrappers?
|
||||
|
||||
### Forwards-compatibility
|
||||
|
||||
There's a concern about forwards-compatibility. We want to be able to add
|
||||
support for new HTTP features without needing a new major version. While most
|
||||
of `http` and `hyper` are prepared for that, there's two potential problems.
|
||||
|
||||
- New frames on an HTTP stream (body)
|
||||
- Receiving a new frame type would require a new trait method
|
||||
- There's no way to implement a "receive unknown frame" that hyper doesn't know about.
|
||||
- Sending an unknown frame type would be even harder.
|
||||
- Besides being able to pass an "unknown" type through the trait, the user would need to be
|
||||
able to describe how that frame is encoded in HTTP/2/3.
|
||||
- New HTTP versions
|
||||
- HTTP/3 will require a new transport abstraction. It's not as simple as just using some
|
||||
`impl AsyncRead + AsyncWrite`. While HTTP/2 bundled the concept of stream creation internally,
|
||||
and thus could be managed wholly on top of a read-write transport, HTTP/3 is different. Stream
|
||||
creation is shifted to the QUIC protocol, and HTTP/3 needs to be able to use that directly.
|
||||
- This means the existing `Connection` types for both client and server will not be able to
|
||||
accept a QUIC transport so we can add HTTP/3 support.
|
||||
|
||||
### Errors
|
||||
|
||||
It's not easy to match for specific errors.
|
||||
|
||||
The `Error::source()` can leak an internal dependency. For example, a
|
||||
`hyper::Error` may wrap an `h2::Error`. Users can downcast the source at
|
||||
runtime, and hyper internally changing the version of its `h2` dependency can
|
||||
cause runtime breakage for users.
|
||||
|
||||
Formatting errors is in conflict with the current expected norm. The
|
||||
`fmt::Display` implementation for `hyper::Error` currently prints its own
|
||||
message, and then prints the message of any wrapped source error. The Errors
|
||||
Working Group currently recommends that errors only print their own message
|
||||
(link?). This conflict means that error "reporters", which crawl a source chain
|
||||
and print each error, has a lot of duplicated information.
|
||||
|
||||
```
|
||||
error fetching website: error trying to connect: tcp connect error: Connection refused (os error 61)
|
||||
tcp connect error: Connection refused (os error 61)
|
||||
Connection refused (os error 61)
|
||||
```
|
||||
|
||||
While there is a good reason for why hyper's `Error` types do this, at the very
|
||||
least, it _is_ unfortunate.
|
||||
|
||||
### You call hyper, or hyper calls you?
|
||||
|
||||
> Note: this problem space, of who calls whom, will be explored more deeply in
|
||||
> a future article.
|
||||
|
||||
At times, it's been wondered whether hyper should call user code, or if user
|
||||
code should call hyper. For instance, should a `Service` be called with a
|
||||
request when the connection receives one, or should the user always poll for
|
||||
the next request.
|
||||
|
||||
There's a similar question around sending a message body. Should hyper ask the
|
||||
body for more data to write, or should the user call a `write` method directly?
|
||||
|
||||
These both get at a root topic about [write
|
||||
observability](https://github.com/hyperium/hyper/issues/2181). How do you know
|
||||
when a response, or when body data, has been written successfully? This is
|
||||
desirable for metrics, or for triggering other side-effects.
|
||||
|
||||
The `Service` trait also has some other frequently mentioned issues. Does
|
||||
`poll_ready` pull its complexity weight for servers? What about returning
|
||||
errors, what does that mean? Ideally users would turn all errors into
|
||||
appropriate `http::Response`s. But in HTTP/2 and beyond, stream errors are
|
||||
different from HTTP Server Error responses. Could the `Service::Error` type do
|
||||
more to encourage best practices?
|
||||
|
||||
## Design
|
||||
|
||||
The goal is to get hyper closer to the [VISION][], using that to determine the
|
||||
best way to solve the known issues above. The main thrust of the proposed
|
||||
changes are to make hyper more **Flexible** and stable.
|
||||
|
||||
In order to keep hyper **Understandable**, however, the proposed changes *must*
|
||||
be accompanied by providing utilities that solve the common usage patterns,
|
||||
documentation explaining how to use the more flexible pieces, and guides on how
|
||||
to reach for the `hyper-util`ity belt.
|
||||
|
||||
The majority of the changes are smaller and can be contained to the *Public
|
||||
API* section, since they usually only apply to a single module or type. But the
|
||||
biggest changes are explained in detail here.
|
||||
|
||||
### Split per HTTP version
|
||||
|
||||
The existing `Connection` types, both for the client and server, abstract over
|
||||
HTTP version by requiring a generic `AsyncRead + AsyncWrite` transport type.
|
||||
But as we figure out HTTP/3, that needs to change. So to prepare now, the
|
||||
`Connection` types will be split up.
|
||||
|
||||
For example, there will now be `hyper::server::conn::http1::Connection` and
|
||||
`hyper::server::conn::http2::Connection` types.
|
||||
|
||||
These specific types will still have a very similar looking API that, as the
|
||||
VISION describes, provides **Correct** connection management as it pertains to
|
||||
HTTP.
|
||||
|
||||
There will be still be a type to wrap the different versions. It will no longer
|
||||
be generic over the transport type, to prepare for being able to wrap HTTP/3
|
||||
connections. Exactly how it will wrap, either by using internal trait objects,
|
||||
or an `enum Either` style, or using a `trait Connection` that each type
|
||||
implements, is something to be determined. It's likely that this "auto" type
|
||||
will start in `hyper-util`.
|
||||
|
||||
### Focus on the `Connection` level
|
||||
|
||||
As mentioned in the *Known Issues*, the higher-level `Client` and `Server` have
|
||||
stability and complexity problems. Therefore, for hyper 1.0, the main API will
|
||||
focus on the "lower-level" connection types. The `Client` and `Server` helpers
|
||||
will be moved to `hyper-util`.
|
||||
|
||||
## Public API
|
||||
|
||||
### body
|
||||
|
||||
The `Body` struct is removed. Its internal "variants" are [separated into
|
||||
distinct types](https://github.com/hyperium/hyper/issues/2345), and can start
|
||||
in either `hyper-util` or `http-body-util`.
|
||||
|
||||
The exported trait `HttpBody` is renamed to `Body`.
|
||||
|
||||
A single `Body` implementation in `hyper` is the one provided by receiving
|
||||
client responses and server requests. It has the name `Streaming`.
|
||||
|
||||
> **Unresolved**: Other names can be considered during implementation. Another
|
||||
> option is to not publicly name the implementation, but return `Response<impl
|
||||
Body>`s.
|
||||
|
||||
The `Body` trait will be experimented on to see about making it possible to
|
||||
return more frame types beyonds just data and trailers.
|
||||
|
||||
> **Unresolved**: What exactly this looks like will only be known after
|
||||
> experimentation.
|
||||
|
||||
### client
|
||||
|
||||
The high-level `hyper::Client` will be removed, along with the
|
||||
`hyper::client::connect` module. They will be explored more in `hyper-util`.
|
||||
|
||||
As described in *Design*, the `client::conn` module will gain `http1` and
|
||||
`http2` sub-modules, providing per-version `SendRequest`, `Connection`, and
|
||||
`Builder` structs. An `auto` version can be explored in `hyper-util`.
|
||||
|
||||
### error
|
||||
|
||||
The `hyper::Error` struct remains in place.
|
||||
|
||||
All errors returned from `Error::source()` are made opaque. They are wrapped an
|
||||
internal `Opaque` newtype that still allows printing, but prevents downcasting
|
||||
to the internal dependency.
|
||||
|
||||
A new `hyper::error::Code` struct is defined. It is an opaque struct, with
|
||||
associated constants defining various code variants.
|
||||
|
||||
> Alternative: define a non-exhaustive enum. It's not clear that this is
|
||||
> definitely better, though. Keeping it an opaque struct means we can add
|
||||
> secondary parts to the code in the future, or add bit flags, or similar
|
||||
> extensions.
|
||||
|
||||
The purpose of `Code` is to provide an abstraction over the kind of error that
|
||||
is encountered. The `Code` could be some behavior noticed inside hyper, such as
|
||||
an incomplete HTTP message. Or it can be "translated" from the underlying
|
||||
protocol, if it defines protocol level errors. For example, an
|
||||
`h2::Reason::CANCEL`.
|
||||
|
||||
### rt
|
||||
|
||||
The `Executor` trait stays in here.
|
||||
|
||||
Define a new trait `Timer`, which describes a way for users to provide a source
|
||||
of sleeping/timeout futures. Similar to `Executor`, a new generic is added to
|
||||
connection builders to provide a `Timer`.
|
||||
|
||||
### server
|
||||
|
||||
The higher-level `hyper::Server` struct, its related `Builder`, and the
|
||||
`Accept` trait are all removed.
|
||||
|
||||
The `AddrStream` struct will be completely removed, as it provides no value but
|
||||
causes binary bloat.
|
||||
|
||||
Similar to `client`, and as describe in the *Design*, the `conn` modules will
|
||||
be expanded to support `http1` and `http2` submodules. An `auto` version can be
|
||||
explored in `hyper-util`.
|
||||
|
||||
### service
|
||||
|
||||
A vendored and simplified `Service` trait will be explored.
|
||||
|
||||
The error type for `Service`s used for a server will explore having the return
|
||||
type changed from any error to one that can become a `hyper::error::Code`.
|
||||
|
||||
> **Unresolved**: Both of the above points are not set in stone. We will
|
||||
> explore and decide if they are the best outcome during development.
|
||||
|
||||
The `MakeService` pieces will be removed.
|
||||
|
||||
### Cargo Features
|
||||
|
||||
Remove the `stream` feature. The `Stream` trait is not stable, and we cannot
|
||||
depend on an unstable API.
|
||||
|
||||
Remove the `tcp` and `runtime` features. The automatic executor and timer parts
|
||||
are handled by providing implementations of `Executor` and `Timer`. The
|
||||
`connect` and `Accept` parts are also moving to `hyper-util`.
|
||||
|
||||
### Public Dependencies
|
||||
|
||||
- `http`
|
||||
- `http-body`
|
||||
- `bytes`
|
||||
|
||||
Cannot be public while "unstable":
|
||||
|
||||
- `tracing`
|
||||
|
||||
## `hyper-util`
|
||||
|
||||
|
||||
### body
|
||||
|
||||
A channel implementation of `Body` that has an API to know when the data has
|
||||
been successfully written is provided in `hyper_util::body::channel`.
|
||||
|
||||
### client
|
||||
|
||||
A `Pool` struct that implements `Service` is provided. It fills a similar role
|
||||
as the previous `hyper::Client`.
|
||||
|
||||
> **Note**: The `Pool` might be something that goes into the `tower` crate
|
||||
> instead. Or it might stay here as a slightly more specialized racing-connect
|
||||
> pool. We'll find out as we go.
|
||||
|
||||
A `connect` submodule that mostly mirrors the existing `hyper::client::connect`
|
||||
module is moved here. Connectors can be used as a source to provide `Service`s
|
||||
used by the `Pool`.
|
||||
|
||||
### rt
|
||||
|
||||
We can provide Tokio-backed implementations of `Executor` and `Timer`.
|
||||
|
||||
### server
|
||||
|
||||
A `GracefulShutdown` helper is provided, to allow for similar style of graceful
|
||||
shutdown as the previous `hyper::Server` did, but with better control.
|
||||
|
||||
# Appendix
|
||||
|
||||
## Unresolved Questions
|
||||
|
||||
There are some parts of the proposal which are not fully resolved. They are
|
||||
mentioned in Design and API sections above, but also collected here for easy
|
||||
finding. While they all have _plans_, they are more exploratory parts of the
|
||||
API, and thus they have a higher possibility of changing as we implement them.
|
||||
|
||||
The goal is to have these questions resolved and removed from the document by
|
||||
the time there is a [Release Candidate][timeline].
|
||||
|
||||
### Should there be `hyper::io` traits?
|
||||
|
||||
Depending on `tokio` just for `AsyncRead` and `AsyncWrite` is convenient, but
|
||||
can be confusing for users integrating hyper with other runtimes. It also ties
|
||||
our version directly to Tokio. We can consider having vendored traits, and
|
||||
providing Tokio wrappers in `hyper-util`.
|
||||
|
||||
### Should returned body types be `impl Body`?
|
||||
|
||||
### How could the `Body` trait prepare for unknown frames?
|
||||
|
||||
We will experiment with this, and keep track of those experiments in a
|
||||
dedicated issue. It might be possible to use something like this:
|
||||
|
||||
```rust
|
||||
pub trait Body {
|
||||
type Data;
|
||||
fn poll_frame(..) -> Result<Option<Frame<Self::Data>>>;
|
||||
}
|
||||
|
||||
pub struct Frame<T>(Kind<T>);
|
||||
|
||||
enum Kind<T> {
|
||||
Data(T),
|
||||
Trailers(HeaderMap),
|
||||
Unknown(Box<dyn FrameThingy>),
|
||||
}
|
||||
```
|
||||
|
||||
### Should there be a simplified `hyper::Service` trait, or should hyper depend on `tower-service`?
|
||||
|
||||
- There's still a few uncertain decisions around tower, such as if it should be
|
||||
changed to `async fn call`, and if `poll_ready` is the best way to handle
|
||||
backpressure.
|
||||
- It's not clear that the backpressure is something needed at the `Server`
|
||||
boundary, thus meaning we should remove `poll_ready` from hyper.
|
||||
- It's not 100% clear if we should keep the service pattern, or use a
|
||||
pull-based API. This will be explored in a future blog post.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why did you pick _that_ name? Why not this other better name?
|
||||
|
||||
Naming is hard. We certainly should solve it, but discussion for particular
|
||||
names for structs and traits should be scoped to the specific issues. This
|
||||
document is to define the shape of the library API.
|
||||
|
||||
### Should I publicly depend on `hyper-util`?
|
||||
|
||||
The `hyper-util` crate will not reach 1.0 when `hyper` does. Some types and
|
||||
traits are being moved to `hyper-util`. As with any pre-1.0 crate, you _can_
|
||||
publicly depend on it, but it is explicitly less stable.
|
||||
|
||||
In most cases, it's recommended to not publicly expose your dependency on
|
||||
`hyper-util`. If you depend on a trait, such as used by the moved higher-level
|
||||
`Client` or `Server`, it may be better for your users to define your own
|
||||
abstraction, and then make an internal adapter.
|
||||
|
||||
### Isn't this making hyper harder?
|
||||
|
||||
We are making hyper more **flexible**. As noted in the [VISION][], most use
|
||||
cases of hyper require it to be flexible. That _can_ mean that the exposed API
|
||||
is lower level, and that it feels more complicated. It should still be
|
||||
**understandable**.
|
||||
|
||||
But the hyper 1.0 effort is more than just the single `hyper` crate. Many
|
||||
useful helpers will be migrated to a `hyper-util` crate, and likely improved in
|
||||
the process. The [timeline][] also points out that we will have a significant
|
||||
documentation push. While the flexible pieces will be in hyper to compose how
|
||||
they need, we will also write guides for the [hyper.rs][] showing people how to
|
||||
accomplish the most common tasks.
|
||||
|
||||
[timeline]: https://seanmonstar.com/post/676912131372875776/hyper-10-timeline
|
||||
[VISION]: https://github.com/hyperium/hyper/pull/2772
|
||||
[hyper.rs]: https://hyper.rs
|
||||
100
hyper/docs/TENETS.md
Normal file
100
hyper/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, harassed 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
hyper/docs/VISION.md
Normal file
230
hyper/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 capabilities, 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
hyper/docs/vision-arch.svg
Normal file
4
hyper/docs/vision-arch.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.7 KiB |
Loading…
Add table
Add a link
Reference in a new issue