## 1. Project Overview & Quickstart (hyperium/governance)

# governance

Open-source repository hyperium/governance

### Repository Details
- **Repository:** [hyperium/governance](https://github.com/hyperium/governance)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (hyperium/hyperium.github.io)

## File: _config.yml

# Site settings
title: hyper - fast and safe HTTP for the Rust language
baseurl: "/" # the subpath of your site, e.g. /blog/
url: "https://hyper.rs" # the base hostname & protocol for your site

defaults:
  -
    scope:
      path: "_legacy/"
      type: "guides"
    values:
      layout: "guide"
  -
    scope:
      path: "_stable/"
      type: "guides"
    values:
      layout: "guide"
  -
    scope:
      path: "_contrib/"
      type: "guides"
    values:
      layout: "guide"
  

collections:
  legacy:
    permalink: /guides/0.14/:path/
    output: true
  stable:
    permalink: /guides/1/:path/
    output: true
  posts:
    permalink: /blog/:year/:month/:day/:title/
    output: true
  contrib:
    permalink: /contrib/:path/
    output: true

# Build settings
markdown: kramdown
highlighter: rouge

kramdown:
    input: GFM
    syntax_highlighter: rouge

relative_links:
  enabled: true
  collections: true

plugins:
  - jekyll-redirect-from

hyper_docs_url: https://docs.rs/hyper/latest
examples_url: https://github.com/hyperium/hyper/tree/master/examples
http_body_util_url: https://docs.rs/http-body-util/latest
hyper_tls_url: https://docs.rs/hyper-tls/latest
hyper_util_url: https://docs.rs/hyper-util/latest
http_docs_url: https://docs.rs/http/latest

futures_url: https://docs.rs/futures/0.3.*
legacy_docs_url: https://docs.rs/hyper/0.14.*
legacy_examples_url: https://github.com/hyperium/hyper/tree/0.14.x/examples

---

## File: blog.md

---
layout: default
permalink: /blog
---



    
    {% for post in site.posts %}
        <li>
            <h2 class="post-title">
                <a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
            </h2>
        </li>
    {% endfor %}

---

## File: index.md

---
layout: home
---

---

## File: _contrib/code-of-conduct.md

---
title: >-
  Code of Conduct
layout: guide
hyper_path: docs/CODE_OF_CONDUCT.md
---

## 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.

---

## File: _contrib/code-style.md

---
title: >-
  Code Style
layout: guide
hyper_path: docs/CODE_STYLE.md
---

hyper uses the default configuration of `rustfmt`.

## cargo fmt

`cargo fmt --all` does not work in hyper. Please use the following commands:

```txt
# Mac or Linux
rustfmt --check --edition 2021 $(git ls-files '*.rs')

# Powershell
Get-ChildItem . -Filter "*.rs" -Recurse | foreach { rustfmt --check --edition 2021 $_.FullName }
```

> **NOTE**: If you are using `rust-analyzer`, you can add the following two lines in your `settings.json` to make sure the features get taken into account when checking the project:
>
>    ```json
>     "rust-analyzer.cargo.features": ["full"],
>     "rust-analyzer.check.features": ["full"],
>    ```

---

## File: _contrib/collaborators.md

---
title: >-
  hyper Collaborator Guide
layout: guide
hyper_path: docs/COLLABORATORS.md
---

This document describes how collaborators manage hyper.

- First off, a collaborator doesn't need to do all of the following perfectly.
	- It takes time to learn.
	- Instead, focus on growth.
	- Get in the habit of checking this guide with some frequency, and improve rather than stagnate.

## Exemplify the Code of Conduct

- Our [code of conduct](./code-of-conduct.md) is not elaborate. It doesn't require much study, nor explication.
- To be a good collaborator, it does require internalizing it.
- The code of conduct is proactive, positive.
- A collaborator must be a good example of being kind.
	- It should not be possible to find significant fault in a collaborator against the simple principles in the code of conduct.

## Internalize the Vision

- Understand and use the project's [vision](./vision.md) when helping guide decisions.

## Review Pull Requests

- Review pull requests promptly and kindly. Approve CI for new contributors.
	- Consider telling a maintainer to add you to the automated review queue.
- Collaborators should feel comfortable approving and merging straightforward changes. Such as documentation, chores, styling, simple refactors, and basic bug fixes.
- When reviewing larger changes, keep in mind the points on [being API caretakers](#api-caretakers).
- When approving a PR, allow time for other collaborators to look before merging.
	- Especially if the PR is newer, or has a more significant change.
- When merging, prefer squashing (it adds in the PR number). Touch up the commit message to match our [commits](./commits.md) style.

## Provide Feedback on Features and Designs

Collaborators try to participate early and often when new features are proposed. They also actively consider and recommend new features that users may need.

### API Caretakers

Collaborators are caretakers of hyper's API. When proposing, discussing, or reviewing changes to hyper, keep the following in mind:

- Conservative additions
	- Conservative APIs reduce breaking changes
- Don't expose internal implementation details
	- [Accessors can reveal internal repr](https://seanmonstar.com/micro/20260721-accessors-reveal-internal-repr/)
- hyper-util is a place to explore first
	- [Vision: Not quite stable, but utile](./vision.md#not-quite-stable-but-utile-useful)
	- [Roadmap: hyper-util](./roadmap.md#hyper-util)
- Unstable features
	- Unstable features are not bound by our stability promise.
	- We don't just name a crate feature with unstable.
		- This has the problem of an intermediary crate enabling it, and someone depending on _that_ crate and not realizing they are accessing unstable hyper features.
	- All unstable features require a conditional config flag passed to the Rust compiler.
		- For example, `hyper_unstable_ffi`.
- Breaking changes
	- These would usually be reserved for a new SemVer major release, such as v2.0, and thus would usually be very rare.
	- An exception is fixing a mistake quickly after release of a new feature.
	- All breaking changes require approval by a maintainer.

## Welcome New Contributors

- Help new contributors find their way around the project and its processes. Follow the guidance on [acknowledging people when triaging](./issues.md#acknowledge).

## Answer Questions

- Answer questions in issues or chat when you can, or help find someone who can. See the project's [help channels](./contributing.md#help).

## Mentor Contributors

- Help contributors grow toward becoming project members. Issue triaging often provides opportunities for [mentoring](./issues.md#mentoring), but the ideas can be applied to reviews, or when answering questions.

---

## File: _contrib/commits.md

---
title: >-
  Git Commit Guidelines
layout: guide
hyper_path: docs/COMMITS.md
---

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>`

---

## File: _contrib/contributing.md

---
title: >-
  Contributing to Hyper
layout: guide
hyper_path: docs/CONTRIBUTING.md
---

You want to contribute? You're awesome!

Contributions come in all shapes and sizes. Let's take a tour of some of the different ways you could contribute.

## [Code of Conduct](code-of-conduct.md)

Firstly, all interactions with the project need to abide by the code of conduct. This makes sure everyone is treated kindly.

## [Issues](issues.md)

- **Filing an issue** is a contribution. We appreciate you letting us know about bugs you've found, and any information that you can provide that we can use to make hyper better. Without your filing it, we may not be aware of the bug.
- [Triaging issues](issues.md#triaging) is a huge help. By your helping make issues better, the reporters can get answers sooner, and others can fix them with less effort. You can also volunteer as a frequent [triager](maintainers.md#triagers).
- Discuss [feature requests][feat] (especially those marked [request-for-comment][b-rfc]).

[feat]: https://github.com/hyperium/hyper/issues?q=is%3Aissue+is%3Aopen+label%3AC-feature
[b-rfc]: https://github.com/hyperium/hyper/issues?q=is%3Aissue+is%3Aopen+label%3AB-rfc


## [Pull Requests](pull-requests.md)

By the way, consider checking the [list of easy issues](https://github.com/hyperium/hyper/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy) if you want to submit something.

- [Submitting a Pull Request](pull-requests.md#submitting-a-pull-request)
- [Commit Guidelines](commits.md)

## Documentation

Improving hyper's documentation is a huge help for everyone who is trying to _use_ hyper.

- The API [documentation](https://docs.rs/hyper) is stored as rustdoc comments directly in the source.
- The main website has [tutorial-style guides](https://hyper.rs/guides). As of v1, they are currently in a [revamp](https://github.com/hyperium/hyper/issues/3411), and would greatly benefit from being filled out.

## Help

Helping others use hyper in their specific workflows is a very valuable way to contribute.

- Answer questions asked directly in hyper's [Discussions](https://github.com/hyperium/hyper/discussions).
- Join our [Discord](https://discord.gg/kkwpueZ) and help those who show up with questions.
- **Blog about hyper.** You writing a blog post about how you use hyper to do something specific, or how you contributed a new feature, or debugged something in it, is a great idea. Not all examples can fit in the hyper repo. Search engines will help people find their use cases on your blog. And you can describe processes in more depth or from a different perspective.

---

## File: _contrib/governance.md

---
title: >-
  Governance
layout: guide
hyper_path: docs/GOVERNANCE.md
---

## Making decisions

There's two main pieces to the way decisions are made in hyper:

1. A decision-making framework
2. The people who apply it

The people are described [lower down in this document](#roles).

### Decision-making framework

We start with the users. The project wouldn't exist without them, and it exists
in order to enable users to do amazing things with HTTP. We listen to our
users. Some actively contribute their thoughts, but many others we must seek
out to learn about their usage, joys, and headaches. Those insights allow our
experts to determine the best solutions for the users.

We then define a set of [tenets](./tenets.md), which are guiding principles
that can be used to measure aspects of individual decisions. It should be
possible to identify one or more tenets that apply to why a decision is made.
And the set helps us balance which priorities are more important for our users.

We combine the usecases with the tenets to come up with a [vision](./vision.md)
that provides a longer-term plan of what hyper _should_ look like.

Finally, we define a [roadmap](./roadmap.md) that describes what the
short-term, tactical changes to bring hyper closer in line with the vision.

## Roles

These are the roles people can fill when participating in the project. A list
of the people in each role is available in [maintainers](./maintainers.md).

### Contributor

A contributor is anyone who contributes their time to provide value for the
project. This could be in the form of code, documentation, filing issues,
discussing designs, or helping others on the issue tracker or in chat.

All contributors MUST follow the [Code of Conduct][coc].

👋  **New here?** [This could be you!][contrib]

### Triager

Triagers assess issues on the issue tracker. They help make sure the work is
well organized, and are critical for making new issue reporters feeling
welcome.

Responsibilities:

- Adhere to the [Code of Conduct][coc]
- Follow the [triager's guide][triage-guide]

Privileges:

- Can edit, label, and close issues
- Member of the organization
- Can be assigned issues and pull requests

How to become:

- Make a few [contributions][contrib] to the project, to show you can follow
  the [Code of Conduct][coc].
- Self-nominate by making a pull request adding yourself to the
  [list](./maintainers.md#triagers).


### Collaborator

Collaborators are contributors who have been helping out in a consistent basis.
See the [collaborator guide](./collaborators.md) for practical guidance on the role.

Responsibilities:

- Be exemplars of the [Code of Conduct][coc]
- Internalize the [vision](./vision.md)
- Reviewing pull requests from other contributors
- Provide feedback on proposed features and design documents
- [Welcome new contributors][triage-guide]
- Answer questions in issues and/or chat
- Mentor contributors to become members

Privileges:

- Can review and merge pull requests
- Can trigger re-runs of CI, and approve CI for first-time contributors
- Can assign issues and pull requests to other organization members

How to become:

- Work at fulfilling the above responsibilities.
- Any collaborator may nominate a contributor who has been around for some time
  and is already filling the responsibilities.
- Another collaborator must second the nomination.
- If there are no objections, a maintainer will welcome the new collaborator.

Don't be afraid to ask a collaborator for what you could work on to reach this
goal!

### Advisor

Advisors are contributors with a lot of domain expertise. They offer advice on
proposals, complicated bugs or features, based on their experience elsewhere in
the industry.

Responsibilities:

- Adhere to the [Code of Conduct][coc]
- Try to offer advice when the `@hyperium/advisors` team is tagged for input.
  (This is not a frequent occurrence, so the time commitment should generally be
  low.)

How to become:

- Advisors are invited by a maintainer.
- Sometimes they are experienced Collaborators who must step back from active
  contributing. Sometimes they are experts placed elsewhere who are friendly to
  the project.

### Maintainer

Maintainers are the project admins. Besides being a collaborator, they take care
of house-keeping duties, help lead the direction, and have the final authority when
required.

[coc]: ./code-of-conduct.md
[contrib]: ./contributing.md
[triage-guide]: ./issues.md#triaging

---

## File: _contrib/index.md

---
title: >-
  Developing hyper
permalink: /contrib/
layout: guide
hyper_path: docs/README.md
---

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.

---

## File: _contrib/issues.md

---
title: >-
  Issues
layout: guide
hyper_path: docs/ISSUES.md
---

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.

### Category

The category marks what kind of issue this is.

- **C-bug**: something is wrong, this is bad!
- **C-feature**: this is a new feature request, adding something new.
- **C-performance**: make existing working code go faster.
- **C-refactor**: improve internal code to help readability and maintenance.
- **C-chore**: a general chore or maintenance task.

### 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.


[issues]: https://github.com/hyperium/hyper/issues
[COC]: ./code-of-conduct.md
[PRs]: ./pull-requests.md
[MRE]: https://en.wikipedia.org/wiki/Minimal_reproducible_example

---

## File: _contrib/maintainers.md

---
title: >-
  The People
layout: guide
hyper_path: docs/MAINTAINERS.md
---

To see what these roles do, and how to become one, look at [governance](./governance.md).

## Triagers

- Eray Karatay (@programatik29)
- Oddbjørn Grødem (@oddgrd)

## Collaborators

- Sean McArthur (@seanmonstar)
- Steven Fackler (@sfackler)
- dswij (@dswij)
- tottoto (@tottoto)
- katelyn martin (@cratelyn)
- 0x676e67 (@0x676e67)

### Collaborator emeriti

- Jonathan Reem (@reem)
- Carl Lerche (@carllerche)
- Oliver Gould (@olix0r)
- Eliza Weisman (@hawkw)
- Lucio Franco (@LucioFranco)
- Adam Foltzer (@acfoltzer)
- David Pedersen (@davidpdrsn)
- Anthony Ramine (@nox)
- Noah Kennedy (@Noah-Kennedy)

## Advisors

- Oliver Gould (@olix0r)
- Adam Foltzer (@acfoltzer)

## Maintainers

- Sean McArthur (@seanmonstar)

---

## File: _contrib/msrv.md

---
title: >-
  Minimum Supported Rust Version (MSRV)
layout: guide
hyper_path: docs/MSRV.md
---

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.63**.

---

## File: _contrib/pull-requests.md

---
title: >-
  Pull Requests
layout: guide
hyper_path: docs/PULL_REQUESTS.md
---

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.

---

## File: _contrib/roadmap-1.0.md

---
title: >-
  hyper 1.0 Roadmap
layout: guide
hyper_path: docs/ROADMAP-1.0.md
---

> This was the roadmap to arrive at hyper v1.0. It is kept for historical purposes. See [roadmap](./roadmap.md) for the latest.

## 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`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

---

## File: _contrib/roadmap.md

---
title: >-
  Roadmap
layout: guide
hyper_path: docs/ROADMAP.md
---

## Goal

Align current hyper to the [hyper vision](./vision.md).

The vision outlines a decision-making framework, use-cases, and general shape
of hyper. This roadmap describes the focus areas to continue to improve hyper
to look more like what is in the vision.

## Focus Areas

While open source is not a company, open source can be guiding. We _can_ focus
attention to specific areas of improvement, which are based on conversations
with users, and prioritized by frequency and impact.

To that end, the following 4 areas are current focus of the project:

1. Documentation
2. `hyper-util`
3. HTTP/3
4. Observability

Each area benefits from having a top level description and goal, a place to
track progress, and a champion (or two) that helps push the effort.

### Documentation

hyper has stabilized, so investing in documentation is wise! The way it is used
won't change much, so documentation won't become outdated quickly. A tool that
people don't know how to use isn't helpful at all. This helps hyper be
**Understandable**.

The documentation focus area includes several different forms:

- The API docs as a reference.
- Examples as form of how-to.
- Website guides as tutorials.

Each of these could benefit from dedicated planning of their overall structure,
editing the content that already exists, and creating the rest that is sorely
missing.

### hyper-util

`hyper-util` serves two main purposes:

1. Provide useful patterns that build on top of hyper.
2. Explore, stabilize, and graduate some of those patterns into hyper itself.

To that end, there are several new features that can be worked on and iterated
on in `hyper-util` right now:

- New design for a higher-level `Client`.
- Breaking apart some patterns from `reqwest`, such as proxy helpers.
- Server automatic version detection.
- Improved builder patterns that make it easier to configure complicated
  options.

### HTTP/3

hyper has an HTTP/3 crate, `h3`, that is generic over any QUIC implementation,
similar to how hyper's HTTP/1 and HTTP/2 can be provided any IO transport. It
supports much of HTTP/3 already, and interoperates with most other
implementations. While some brave users have been trying it out the hard way
(such as reqwest), it's time to bring HTTP/3 to more users.

The aim is to eventually support `hyper::client::conn::http3` and
`hyper::server::conn::http3`.

To do so, work is needed:

- Harden the `h3` crate itself, such as fixing any straggling interop issues,
  and filling out the spec conformance tags we use for accountability.
- Proposal for (initially unstable) `hyper::rt::quic` integration, allowing
  people to bring their own QUIC.
- Write the `hyper::proto::http3` glue that translates hyper's connection
  patterns with the `h3` crate.

### Observability

It's extremely common once operating a service using hyper to want more
visibility in what exactly is happening. It's important to realize that there
are 3 concepts involved that frequently get conflated: events, tracing, and
metrics.

Some existing ways to get some of these:

- Unstable `tracing` integraton inside hyper.
- `tower_http::trace` which instruments outside of hyper, using `Service` and
  `Body`.

However, there are some events and metrics that are only known inside hyper,
and having official, stable support would be very helpful.

Some potential options would be:

- Stabilizing specific `tracing` events (blocked on the `tracing` crate
  stabilizing...)
- Provide a rudimentary, programmatic way to query metrics without another
  crate.
- Provide some sort of `hyper-metrics` helper.

## Beyond

The above are focus areas that are the most frequently asked for, and so have
the most attention. That doesn't mean that nothing else can be worked on.

Motivated individuals that want to help make other improvements are certainly
welcome!

---

## File: _contrib/tenets.md

---
title: >-
  Charter
layout: guide
hyper_path: docs/TENETS.md
---

> 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](./code-of-conduct.md), compassion and empathy towards all
contributors. Technical skill is not a substitute for human decency.

### 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.

---

## File: _contrib/vision.md

---
title: >-
  hyper Vision
layout: guide
hyper_path: docs/VISION.md
---

## 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 are 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.

---

## File: _contrib/hips/0000-template.md

---
title: >-
  HIP-0000: Template
layout: guide
hyper_path: docs/hips/0000-template.md
---

- Authors:
- Created: (date)
- PR: (link to pull request)

## Summary

(The tl;dr. Concise statement of the reason for the document and recommendation.)

## Tenets

(List of tenets, values, guiding principles that are used to evaluate the proposal.)

## Motivation

(Clearly explain the problem.)

## Recommendation

### User Experience

### Implementation

### Testing Plan

(Optional: are there any special considerations for testing required?)

### Security Considerations

(What security risks might exist for the recommendation? Can we reduce them? What should users consider when using it?)

## Alternatives

(List alternatives considered, and especially why they were not recommended. This portion of "documenting the why" helps Future Us to see if anything has changed since last considered.)

## Unresolved Questions


## References

---

## File: _contrib/hips/0001-hyper-improvement-proposals.md

---
title: >-
  HIP-0001: hyper Improvement Proposals
layout: guide
hyper_path: docs/hips/0001-hyper-improvement-proposals.md
---

- Authors: seanmonstar
- Created: 2026-09-01
- PR: [#4131](https://github.com/hyperium/hyper/pull/4131)

## Summary

HIPs establish a predictable, written‑first process for proposing and evaluating significant changes to hyper. They provide an authoritative place to articulate the problem, the design rationale, and the tradeoffs so contributors can make informed, durable decisions.

## Tenets

- Open: the decision-making process should be out in the open, for all to see and any to participate.
- Understandable: Code and changelogs are not the complete theory. Others should be able to understand what we meant.
- Writing is thinking: while the written artifact is extremely valuable, the process of creating is thinking itself. It refines our thought, sharpens it, makes it better.
- Document the why: just as important is understanding why we thought that way. This allows evaluating when the decision should be reconsidered.

## Motivation

hyper's existing contribution process does not adequately support proposals for large features and design changes.

Much of the shape of hyper can be seen in the [vision](../vision.md) and [1.0 roadmap](../roadmap-1.0.md). Adding new small features is very easy. However, designing large new systems in hyper must be handled with care. hyper is deployed at massive scale. The stability promise requires we be deliberate with what API to expose.

The current process is to ask people to write up larger designs in an issue. GitHub issues are terrible places to discuss multiple points at once. Or people submit massive pull requests, and the discussion is sprinkled through the code reviews.

It's extremely difficult for reviewers to be sure they understand the design, and to ensure that all critical aspects have been considered. If an implementation is denied for a desirable feature, new pull requests tend to be submitted which don't address the previous concerns. The barrier for someone to contribute goes up due to the lack of structure. And the review process slows down as reviewers struggle to continuously rebuild mental context.

## Recommendation

Introduce a structured, written process for proposing, discussing, and deciding large design changes. We call these **hyper Improvement Proposals** (HIPs). They are similar in spirit to [RFCs](https://en.wikipedia.org/wiki/Request_for_Comments).

### Scope

When should HIPs be used?

HIPs are intended for changes that significantly affect hyper's architecture, public API, performance characteristics, or long‑term maintenance burden. They are useful when a decision is difficult to reverse, when there appear to be several strong options, or as a foundation for future proposals.

When are they not needed?

Small, localized changes that do not alter core design or guarantees generally do not require a HIP.

### Content

What should be included in a HIP?

This defines at a high level the purpose of what content is included. The exact sections might change over time, and so are defined in a separate `0000-template.md` file.

But in general, HIPs should provide the following information:

- Objective - the problem, the motivation, the what are we even doing here.
- Tenets - how to measure solutions
    - A meta point here: spend more time on the objective, tenets, and alternatives. The recommendation will fall into place.
- A single recommendation
    - The job of a proposal is to propose a solution, not to propose a problem.
    - There will often be several ways to solve anything.
    - The proposal should research and measure the options using the facts and tenets, and decide which is the best.
        - The discussion during the proposal period may change what is the recommended solution.
        - The essence of those discussions should be recaptured into the proposal itself. Both in the recommendation section, and also potentially in an FAQ appendix.
        - Future readers should not need to reconstruct the design from the review comments.
- The whys (and why nots) of the solution
    - A proposal should always include why the recommendation is the best option, and why the other options were not chosen
- References
    - Links to all the relevant research that was done
    - Links to previous discussions
- Appendices
    - FAQ

#### Do not use AI to write

AI (LLMs) have their benefits, but since a major reason for writing this is the thinking process, do not use AI to write the actual English in a HIP.

#### What not to include

- Minor details that do not need to be discussed to accept the proposal.

### Lifecycle

- Start with an issue.
    - (A HIP should almost never be started without a previous discussion)
- If the feature request seems large enough, a collaborator may ask for a HIP.
- In a new branch, copy the template file to `0000-your-feature-name.md`.
- Fill out the sections based on the instructions in the template.
    - You don't need to have fully polished prose in every section to submit for discussion.
    - It can even be beneficial to submit initially with bullet points.
    - Balance giving proper thought to the sections, with moving quickly to get appropriate feedback.
- Consider sharing an early draft with someone else first.
- Submit a pull request, and include a big reminder to prefer line comments over top-level PR comments.
- As discussion occurs, revise the sections.
    - Consider adding to an FAQ appendix.
- Eventually, a [maintainer](../governance.md#maintainer) will decide whether the proposal is accepted or rejected.

Once a proposal is accepted, a number will be assigned. The file in the PR can be renamed with the assigned number, and then merged into trunk.

#### Rejection

If a proposal is rejected or withdrawn, its pull request is closed without assigning a HIP number or merging the document. The pull request remains the record of that discussion. If the discussion reveals a generally applicable constraint or principle, that information should instead be incorporated into the appropriate project documentation.

#### Mutability and History

HIPs are mutable, even after being accepted.

Significant changes can be added to a `## History` section of the document, inserted before any `## References` or appendices. Besides explaining what changed, the reasoning for _why_ should be included.

## Alternatives

- Ad-hoc design docs
    - While design documents are an ideal artifact, without defining a process behind them, it's hard for contributors to know when to use one or how.
- Module documentation
    - A reader of module documentation is not the right audience.
    - The purpose of module documentation is to explain how to use the library.
    - It is not a great place to document the why.
- Issues and Pull Requests
    - This is the status quo.
    - Discussion in issues is a horrible experience.
    - Spreads out the full design across disconnected areas.
    - Silos the knowledge directly in GitHub.
- A chat application, such as Zulip
    - Chat-style messages are extremely poor for having thoughtful discussion and decisions.
    - They become littered with messages that have no longer-term value, and it makes it hard to piece back together what a decision is.
    - No contributor should ever _have_ to participate in chat-style messaging.

## Unresolved Questions

- Is there a point when significant changes to an accepted HIP should itself be a new HIP?
    - Possibly, but I'm not sure it's worth deciding yet.

## References

- <https://rust-lang.github.io/rfcs/0002-rfc-process.html>
- <https://rfd.shared.oxide.computer/rfd/0001>
- <https://peps.python.org/pep-0001/>
- <https://docs.jj-vcs.dev/latest/design_docs/>
- <https://blog.ceejbot.com/posts/design-docs/>
- <https://adr.github.io/>

---

## File: _contrib/hips/index.md

---
title: >-
  hyper Improvement Proposals
permalink: /contrib/hips/
layout: guide
---

- [HIP-0001: hyper Improvement Proposals](./0001-hyper-improvement-proposals/)

---

## File: _data/contrib.yml

- title: Contributing
  path: ""
  docs:
  - title: Getting started
    path: contributing
  - title: Code of conduct
    path: code-of-conduct
  - title: Commits
    path: commits
  - title: Issues
    path: issues
  - title: Pull requests
    path: pull-requests
  - title: HIPs
    path: hips
  - title: MSRV
    path: msrv
  - title: Governance
    path: governance
  - title: Maintainers
    path: maintainers
  - title: Collaborators
    path: collaborators
  - title: Tenets
    path: tenets
  - title: Vision
    path: vision
  - title: Roadmap
    path: roadmap

---

## File: _data/legacy.yml

- title: Guide
  path: ""
  guides:
  - server
  - client

- title: Server
  path: "/server"
  guides:
  - hello-world
  - echo
  - graceful-shutdown

- title: Client
  path: "/client"
  guides:
  - basic
  - advanced
  - configuration

---

## File: _data/stable.yml

- title: Guide
  path: ""
  guides:
  - init
  - server
  - client
  - upgrading

- title: Init
  path: "/init"
  guides:
  - setup
  - runtime

- title: Server
  path: "/server"
  guides:
  - hello-world
  - echo
  - middleware
  - graceful-shutdown

- title: Client
  path: "/client"
  guides:
  - basic
  - connectors

- title: Upgrading
  path: "/upgrading"
  anchor: true
  guides: []

---

## File: _legacy/index.md

---
title:  Getting Started
layout: guide
permalink: /guides/0.14/
---

hyper is an HTTP library for the Rust language.

> **NOTE**: These guides are for the older 0.14.x version of hyper. Did
> you want the [v1 guides](/guides/1)?

You can start using it by first adding it to your `Cargo.toml`:

```toml
[dependencies]
hyper = "0.14"
```

- If building a web server, continue with the [Server guide][].
- If trying to talk to a server, continue with the [Client guide][].

You could also look at the [generated API documentaton][docs].

[docs]: {{ site.legacy_docs_url }}
[Server guide]: server/hello-world.md
[Client guide]: client/basic.md

---

## File: _legacy/client/advanced.md

---
title: Advanced Client Usage
layout: guide
redirect_from: 
    - /guides/client/advanced
---

Once you've done all the setup in the [simple guide][], you probably
have more advanced requests you need to make. In this guide, we'll
make a `POST` request, and make multiple requests at the same time.

## Making a POST

We can prepare a [`Request`][Request] before giving it to the client.
Since we want to post some JSON, and not just simply get a resource,
that's what we'll do.

```rust
# extern crate hyper;
use hyper::{Body, Method, Request, Uri};
# fn main() {}
```

After a quick addition to imports, let's prepare a `Request`:

```rust
# extern crate hyper;
# extern crate tokio;
# mod no_run {
# use hyper::{Body, Method, Request};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let req = Request::builder()
        .method(Method::POST)
        .uri("http://httpbin.org/post")
        .header("content-type", "application/json")
        .body(Body::from(r#"{"library":"hyper"}"#))?;

    // We'll send it in a second...

    Ok(())
# }
# }
# fn main() {}
```

Using a convenient request builder, we set the [`Method`][Method] to `POST`,
add a URL, and some headers describing our payload. Lastly, a call to `body`
with our JSON bytes.

Now, we can give that to the `client` with the `request` method:


```rust
# extern crate hyper;
# use hyper::{Client, Request};
# async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
# let req = Request::default();
// let req = ...

let client = Client::new();

// POST it...
let resp = client.request(req).await?;

println!("Response: {}", resp.status());
# Ok(())
# }
# fn main() {}
```

## Multiple Requests

While `await` allows us to write "asynchronous" code in a way that looks
"synchronous", to take full advantage of it, we can make multiple requests
in parallel instead of serially.

We're going to take advantage of "joining" futures, and so need to update our
imports again:

```toml
[dependencies]
hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }
futures = "0.3"
```

Now, we'll create some `async` blocks to describe each future, but since they
are lazy, we can start them in parallel.

```rust
# extern crate hyper;
# extern crate futures;
# use hyper::{Client, Request, Uri};
# async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let client = Client::new();

let ip_fut = async {
    let resp = client.get(Uri::from_static("http://httpbin.org/ip")).await?;
    hyper::body::to_bytes(resp.into_body()).await
};
let headers_fut = async {
    let resp = client.get(Uri::from_static("http://httpbin.org/headers")).await?;
    hyper::body::to_bytes(resp.into_body()).await
};

// Wait on both them at the same time:
let (ip, headers) = futures::try_join!(ip_fut, headers_fut)?;
#
# Ok(())
# }
# fn main() {}
```

[simple guide]: ./basic.md
[Request]: {{ site.legacy_docs_url }}/hyper/struct.Request.html
[Method]: {{ site.legacy_docs_url }}/hyper/struct.Method.html

---

## File: _legacy/client/basic.md

---
title: Getting Started with a Client
layout: guide
redirect_from: 
    - /guides/client/basic
---

To start with, we'll just get a simple `GET` request to a webpage working,
so we can see all the moving parts. First, we need our dependencies.
Let's tell Cargo about our dependencies by having this in the Cargo.toml.

## Dependencies

```toml
[dependencies]
hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }
```

Now, we need to import pieces to use from our dependencies:

```rust
# extern crate hyper;
use hyper::Client;
# fn main() {}
```

## Runtime

Now, we'll make a request in the `main` of our program. This may seem
like a bit of work just to make a simple request, and you'd be correct,
but the point here is just to show all the setup required. Once you have this,
you are set to make thousands of client requests efficiently.

We have to setup some sort of runtime. By default, hyper can make use of the
[Tokio runtime][Tokio]. If you've never used futures in Rust
before, you may wish to read through [Tokio's guide on Futures][Tokio-Futures].


```rust
# extern crate tokio;
# mod no_run {
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    // This is where we will setup our HTTP client requests.

    Ok(())
}
# }
# fn main() {}
```

## GET

We can now create a hyper [`Client`][Client] that will be registered to our runtime.

Calling `client.get` returns a `Future` that will eventually be fulfilled with a
[`Response`][Response].

```rust
# extern crate hyper;
# use hyper::Client;
# async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Still inside `async fn main`...
let client = Client::new();

// Parse an `http::Uri`...
let uri = "http://httpbin.org/ip".parse()?;

// Await the response...
let mut resp = client.get(uri).await?;

println!("Response: {}", resp.status());
# Ok(())
# }
# fn main() {}
```

## Response bodies

Bodies in hyper are always streamed asynchronously. But it's easy to `await`
for each chunk as it comes in! We'll make use of the `HttpBody` trait.

We'll also simply write the body to `stdout`. So, some new imports:

```rust
# extern crate hyper;
# extern crate tokio;
use hyper::body::HttpBody as _;
use tokio::io::{stdout, AsyncWriteExt as _};
```

```rust
# extern crate hyper;
# extern crate tokio;
# use hyper::Client;
# use hyper::body::HttpBody as _;
# use tokio::io::{stdout, AsyncWriteExt as _};
# async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Previously...
let client = Client::new();
let uri = "http://httpbin.org/ip".parse()?;
let mut resp = client.get(uri).await?;
println!("Response: {}", resp.status());

// And now...
while let Some(chunk) = resp.body_mut().data().await {
    stdout().write_all(&chunk?).await?;
}
#
# Ok(())
# }
# fn main() {}
```

And that's it! You can see the [full example here][example].

[Client]: {{ site.legacy_docs_url }}/hyper/client/struct.Client.html
[Tokio]: https://tokio.rs
[Tokio-Futures]: https://tokio.rs/tokio/tutorial/async
[StatusCode]: {{ site.legacy_docs_url }}/hyper/struct.StatusCode.html
[Response]: {{ site.legacy_docs_url }}/hyper/struct.Response.html
[example]: {{ site.legacy_examples_url }}/client.rs

---

## File: _legacy/client/configuration.md

---
title: Client Configuration
layout: guide
redirect_from: 
    - /guides/client/configuration
---

## Using TLS

By default, a [`Client`][] can only speak to HTTP addresses. This is because hyper doesn't
ship with a TLS implementation. You may have noticed that `Client::new()` returns a 
`Client<HttpConnector>`. We can plug in a different connector using the client config.

Since connecting to HTTPS addresses is so common, hyper provides a separate [hyper-tls][]
crate with a pluggable `HttpsConnector`. Here's how you'd use it.

```rust
# extern crate hyper;
# extern crate hyper_tls;
#
use hyper::Client;
use hyper_tls::HttpsConnector;

# fn run() {
let https = HttpsConnector::new();
let client = Client::builder()
    .build::<_, hyper::Body>(https);
# }
# fn main() {}
```

## Connectors

As mentioned in the section about TLS, [`Client`][] is generic over a connector.

You can plug in any kind of connector you need. This means that you could pick a
different TLS implementation than the one chosen by `hyper-tls`, such as `rustls`.
You could also have a completely different way of creating IO objects. Here's some
ideas of things that could be connectors:

- Unix sockets
- Proxies
- In-memory streams (such as for testing)

[`Client`]: {{ site.legacy_docs_url }}/hyper/client/struct.Client.html
[hyper-tls]: {{ site.hyper_tls_url }}

---

## File: _legacy/client/index.md

---
title: Client Guides
permalink: /0.14/client
redirect_from: 
    - /guides/client/
---

This is just placeholder page. It should probably become a table of
contents for the client guides.

---

## File: _legacy/server/echo.md

---
title: Echo, echo, echo
layout: guide
redirect_from: 
    - /guides/server/echo
---

You already have a [Hello World server](hello-world.md)? Excellent! Usually,
servers do more than just spit out the same body for every request. To
exercise several more parts of hyper, this guide will go through
building an echo server.

An echo server will listen for incoming connections and send back the
request body as the response body on `POST` requests.

## Routing

First thing we will do, beyond renaming our service to `echo`, is setup some
routing. We want to have a route explaining instructions on how to use
our server, and another for receiving data. Oh, and we should also
handle the case when someone asks for a route we don't know!

We're going to be using more of the [futures][future-crate] crate, so let's add
that as a dependency:

```toml
[dependencies]
hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }
futures = "0.3"
```

Then, we need to add some to our imports:

```rust
# extern crate hyper;
# extern crate futures;
use hyper::{Method, StatusCode};
# fn main() {}
```

And make some changes to your `Service`, such as returning a `Future` of a `Response`,
since we may not have one ready immediately:

```rust
# extern crate futures;
# extern crate hyper;
# use futures::future::{self, Future};
# use hyper::{Body, Method, Request, Response, StatusCode};
#
async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
    let mut response = Response::new(Body::empty());

    match (req.method(), req.uri().path()) {
        (&Method::GET, "/") => {
            *response.body_mut() = Body::from("Try POSTing data to /echo");
        },
        (&Method::POST, "/echo") => {
            // we'll be back
        },
        _ => {
            *response.status_mut() = StatusCode::NOT_FOUND;
        },
    };

    Ok(response)
}
# fn main() {}
```

We built a super simple routing table just by matching on the `method`
and `path` of an incoming `Request`. If someone requests `GET /`, our
service will let them know they should try our echo powers out. We also
are checking for `POST /echo`, but currently don't do anything about it.

Our third rule catches any other method and path combination, and
changes the `StatusCode` of the `Response`. The default status of a
`Response` is HTTP's `200 OK` (`StatusCode::OK`), which is correct for
the other routes. But the third case will instead send back `404 Not
Found`.

## Body Streams

Now let's get that echo in place. We'll start with the simplest solution, and
then make alterations exercising more complex things you can do with the
`Body` streams.

First up, plain echo. Both the `Request` and the `Response` have body streams,
and by default, you can easily just pass the `Body` of the `Request` into the
`Response`.

```rust
# extern crate hyper;
# use hyper::{Body, Method, Request, Response};
# fn echo(req: Request<Body>) -> Response<Body> {
#     let mut response = Response::default();
#     match (req.method(), req.uri().path()) {
// inside that match from before
(&Method::POST, "/echo") => {
    *response.body_mut() = req.into_body();
},
#         _ => unreachable!(),
#     }
#     response
# }
# fn main() {}
```

Running our server now will echo any data we `POST` to `/echo`. That was easy.
What if we wanted to uppercase all the text? We could use a `map` on our streams.

### Body mapping

We're going to need a couple of extra imports, so let's add those to the top of the file:

```rust
# extern crate futures;
# extern crate hyper;
use futures::TryStreamExt as _;
# fn main() {}
```

A `Body` implements the `Stream` trait from futures, producing a bunch of
`Bytes`s, as data comes in. `Bytes` is just a convenient type from hyper
that represents a bunch of bytes. It can be easily converted into other
typical containers of bytes.

Next, let's add a new `/echo/uppercase` route mapping the body to uppercase:

```rust
# extern crate hyper;
# extern crate futures;
# use futures::TryStreamExt as _;
# use hyper::{Body, Method, Request, Response};
# fn echo(req: Request<Body>) -> Response<Body> {
#     let mut response = Response::default();
#     match (req.method(), req.uri().path()) {
// Yet another route inside our match block...
(&Method::POST, "/echo/uppercase") => {
    // This is actually a new `futures::Stream`...
    let mapping = req
        .into_body()
        .map_ok(|chunk| {
            chunk.iter()
                .map(|byte| byte.to_ascii_uppercase())
                .collect::<Vec<u8>>()
        });

    // Use `Body::wrap_stream` to convert it to a `Body`...
    *response.body_mut() = Body::wrap_stream(mapping);
},
#         _ => unreachable!(),
#     }
#     response
# }
# fn main() {}
```

And like that, we have two echo routes: `/echo` which does no transformation,
and `/echo/uppercase` which returns all bytes after converting them to ASCII
uppercase.

## Buffering the Request Body

What if we want our echo service to reverse the data it received and send it
back to us? We can't really stream the data as it comes in, since we need to
find the end before we can respond. To do this, we can explore how to easily
collect the full body.

In this case, we can't really generate a `Response` immediately. Instead, we
must wait for the full request body to be received.

We want to concatenate the request body, and map the result into our `reverse`
function, and return the eventual result. We can make use of the
`hyper::body::to_bytes` utility function to make this easy.

> Note: You must always be careful not to buffer without a max bounds. We'll
> set a 64kb maximum here.

```rust
# extern crate hyper;
# use hyper::{body::HttpBody, Body, Method, Request, Response};
# async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
#     let mut response = Response::default();
#     match (req.method(), req.uri().path()) {
// Yet another route inside our match block...
(&Method::POST, "/echo/reverse") => {
    // Protect our server from massive bodies.
    let upper = req.body().size_hint().upper().unwrap_or(u64::MAX);
    if upper > 1024 * 64 {
        let mut resp = Response::new(Body::from("Body too big"));
        *resp.status_mut() = hyper::StatusCode::PAYLOAD_TOO_LARGE;
        return Ok(resp);
    }

    // Await the full body to be concatenated into a single `Bytes`...
    let full_body = hyper::body::to_bytes(req.into_body()).await?;

    // Iterate the full body in reverse order and collect into a new Vec.
    let reversed = full_body.iter()
        .rev()
        .cloned()
        .collect::<Vec<u8>>();

    *response.body_mut() = reversed.into();
},
#         _ => unreachable!(),
#     }
#     Ok(response)
# }
# fn main() {}
```

You can see a compiling [example here][example].

[example]: {{ site.legacy_examples_url }}/echo.rs
[future-crate]: https://github.com/rust-lang-nursery/futures-rs

---

## File: _legacy/server/graceful-shutdown.md

---
title:  Gracefully Shutdown a Server
layout: guide
---

hyper `Server`s have the ability to "gracefully" shutdown. This means stopping to accept new requests, and shutting down once all in-progress requests have completed.

We're going to assume you already have server code working, such as from following the [Hello World](hello-world.md) or [Echo](echo.md) guides.

The `Server` type has a `with_graceful_shutdown` method that is passed a `Future` of your choosing. Once that `Future` completes, the `Server` will start the shutdown process. It could be any `Future`, such as a `oneshot` channel. In this guide, we'll setup a signal handler to listen for the user pressing `CTRL+C`.

First, let's create a `shutdown_signal` async function:

```rust
# extern crate tokio;
async fn shutdown_signal() {
    // Wait for the CTRL+C signal
    tokio::signal::ctrl_c()
        .await
        .expect("failed to install CTRL+C signal handler");
}
# fn main() {}
```

Next, we can plug this into an existing server:

```rust
# extern crate hyper;
# extern crate tokio;
# mod no_run {
# use std::convert::Infallible;
# use std::net::SocketAddr;
# use hyper::{Body, Request, Response, Server};
# use hyper::service::{make_service_fn, service_fn};
# async fn hello_world(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
#     Ok(Response::new("Hello, World".into()))
# }
# async fn shutdown_signal() {}
#[tokio::main]
async fn main() {
#    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
#    let make_svc = make_service_fn(|_conn| async {
#        Ok::<_, Infallible>(service_fn(hello_world))
#    });
    // Constructed `addr` and `make_svc` from your app above..

    // And construct the `Server` like normal...
    let server = Server::bind(&addr).serve(make_svc);

    // And now add a graceful shutdown signal...
    let graceful = server.with_graceful_shutdown(shutdown_signal());

    // Run this server for... forever!
    if let Err(e) = graceful.await {
        eprintln!("server error: {}", e);
    }
}
# }
# fn main() {}
```

---

## File: _legacy/server/hello-world.md

---
title:  Getting Started with a Server
layout: guide
redirect_from: 
    - /guides/server/hello-world
---

Let's start by making a "Hello, World!" server, and expand from there.

First, we need our dependencies. Let's tell Cargo about our dependencies by having this in the `Cargo.toml`.

```toml
[dependencies]
hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }
```

Now lets start on our `main.rs`, and add some imports:

```rust
# extern crate hyper;
use std::convert::Infallible;
use std::net::SocketAddr;
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
# fn main() {}
```

## Creating a Service

A [`Service`][service] lets you define how to respond to incoming requests.
While it is possible to implement the trait directly, there are a few patterns
that are common when using Hyper. We've included some helpers for when these
patterns fit our needs.

In this example, we don't have any state to carry around, so we really just
need a simple `async` function:

```rust
# extern crate hyper;
# use std::convert::Infallible;
# use hyper::{Body, Request, Response};
# fn main() {}
async fn hello_world(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
    Ok(Response::new("Hello, World".into()))
}
```

As soon as we get a request, nothing is stopping us from knowing the response
immediately! That function will be used when starting our server.

That new `Response` will by default have a `200 OK` status code, and the `Body`
is able to tell that it is made from a static string, and is able to add a
`Content-Length` header for us automatically.

## Starting the Server

Lastly, we need to hook up our `hello_world` service into a running hyper
Server.

We'll dive in to the specifics of some of these things in another guide.

```rust
# extern crate hyper;
# extern crate tokio;
# mod no_run {
# use std::convert::Infallible;
# use std::net::SocketAddr;
# use hyper::{Body, Request, Response, Server};
# use hyper::service::{make_service_fn, service_fn};
# async fn hello_world(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
#     Ok(Response::new("Hello, World".into()))
# }
#[tokio::main]
async fn main() {
    // We'll bind to 127.0.0.1:3000
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

    // A `Service` is needed for every connection, so this
    // creates one from our `hello_world` function.
    let make_svc = make_service_fn(|_conn| async {
        // service_fn converts our function into a `Service`
        Ok::<_, Infallible>(service_fn(hello_world))
    });

    let server = Server::bind(&addr).serve(make_svc);

    // Run this server for... forever!
    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}
# }
# fn main() {}
```

To see all the snippets put together, check out the [full example][example]!

[service]: {{ site.legacy_docs_url }}/hyper/service/trait.Service.html
[example]: {{ site.legacy_examples_url }}/hello.rs

---

## File: _legacy/server/index.md

---
title: Server Guides
permalink: /0.14/server
redirect_from: 
    - /guides/server/
---

This is just placeholder page. It should probably become a table of
contents for the server guides.

---

## File: _posts/2021-05-06-welcome-anthony-ramine.md

---
title: "Welcome Anthony Ramine"
---

I'm excited to announce that Anthony Ramine ([@nox](https://github.com/nox)) has joined the team of maintainers for hyper!

- Implemented `CONNECT` support over HTTP/2
- Added HTTP/0.9 optional support
- Greater support for preserving header name cases
- Issue triage and PR reviews ❤️

Thank so much for the fantastic support so far!

---

## File: _posts/2022-04-08-welcome-adam-foltzer.md

---
title: "Welcome Adam Foltzer"
---

We'd like to welcome Adam Foltzer ([@acfoltzer](https://github.com/acfoltzer)) as a hyper Collaborator. He has done some great work improving edge-case HTTP/1 support, planning, and most importantly, brings a kind attitude. For instance:

- [Ignore obs-text in HTTP/1 reason phrases](https://github.com/seanmonstar/httparse/pull/84)
- [Refactor the httparse benchmarks to better identify performance changes](https://github.com/seanmonstar/httparse/pull/112)
- [Allow multiple spaces in request and status lines](https://github.com/seanmonstar/httparse/pull/110)
- [Add hyper extension to access `ReasonPhrase`](https://github.com/hyperium/hyper/pull/2792)

Thanks for all you do for us, we're excited to have you aboard!

---

## File: _posts/2024-02-28-welcome-noah-kennedy.md

---
title: "Welcome Noah Kennedy"
---

We'd like to welcome Noah Kennedy ([@Noah-Kennedy](https://github.com/Noah-Kennedy)) as a hyper Collaborator. Noah has paid special attention to security issues in hyper, such as:

- [Jumping in immediately with a surprise CVE for h2](https://seanmonstar.com/blog/coe-surpise-hyper-cve/)
- [Rapid Reset Attack testing to determine hyper was unaffected](https://seanmonstar.com/blog/hyper-http2-rapid-reset-unaffected/)
- [Fixing Reset Floods for h2](https://mastodon.despise.computer/@noah/111773455336054987)


Thanks for helping keep us all secure!

---

## File: _posts/2024-03-04-welcome-dswij.md

---
title: "Welcome dswij"
---

We're excited to announce that [@dswij](https://github.com/dswij) is now a hyper Collaborator. dswij has been helping in a versatile way:

- [Fixing a tricky h2 flow control hang](https://github.com/hyperium/h2/pull/730) (and a couple others)
- [A guide to bringing your own runtime or using Tokio](https://github.com/hyperium/hyperium.github.io/pull/121)
- Providing kind and helpful feedback in issues and pull requests


Thanks for raising the bar!

---

## File: _posts/2024-03-08-welcome-tottoto.md

---
title: "Welcome tottoto"
---

We're priviledged to share that [@tottoto](https://github.com/tottoto) is now a hyper Collaborator. tottoto has been cleaning up and refactoring in a big way:

- [Improving the code quality and CI](https://github.com/hyperium/hyper/commits?author=tottoto)
- [Thorough and kind reviews](https://github.com/hyperium/hyper/pull/3375)


Thanks for proactively improving hyper all over!

---

## File: _posts/2025-04-21-welcome-katelyn-martin.md

---
title: "Welcome katelyn martin"
---

We're thrilled to welcome katelyn martin ([@cratelyn](https://github.com/cratelyn)) as a hyper Collaborator. katelyn first contributed back in 2020, and more recently has been improving various utilities and documentation. Some highlights:

- [Implementing `http_body_util::Channel`](https://github.com/hyperium/http-body/pull/140) and `Fused`
- [Adding new `hyper-util` additive IO adapters](https://github.com/hyperium/hyper-util/pull/170)
- Kind reviews that are based on hyper's VISION.

Thank you for helping the project and ecosystem!

---

## File: _stable/index.md

---
title:  Getting Started
layout: guide
permalink: /guides/1/
redirect_from:
    - /guides/
---

hyper is an HTTP library for the Rust language.

If this is your **first time** here, take a look at [how to
setup](init/setup).

- If building a web server, continue with the [Server guide][].
- If trying to talk to a server, continue with the [Client guide][].

You could also look at the [generated API documentaton][docs].

[docs]: {{ site.hyper_docs_url }}
[Server guide]: server/hello-world
[Client guide]: client/basic

---

## File: _stable/upgrading.md

---
title:  Upgrade from v0.14 to v1
layout: guide
permalink: /guides/1/upgrading/
---

This guide is meant to help you upgrade from v0.14 of hyper to v1.

> Were you looking for the [v0.14 guides](/guides/0.14/)?

## Prepare with Backports and Deprecations

Before upgrading, you can start preparing your 0.14 code base by enabling the
`backports` and `deprecated` features of hyper in your `Cargo.toml`. Like
this:

```toml
[dependencies]
hyper = { version = "0.14", features = ["etc", "backports", "deprecated"] }
```

The `backports` feature brings several of the new types from 1.0 to 0.14. If
you enable `deprecated` feature as well, it will add deprecation warnings to
any of hyper's types that have direct backports available.

> **NOTE**: This won't give you warnings about changes where backports were not
able to be provided.

> **NOTE**: You should upgrade `http-body` to version `0.4.6` or newer to be
> able to access methods in some suggestions.

## Read the Changelog

As a general rule, we tried hard to mark every possible breaking change in the
[changelog][]. Read through the "breaking changes" section of the 1.0 releases
(including the RC 1-4), which will provide suggestions on how to overcome each
one.

## `Body`

The `Body` type has changed to be a trait (what used to be `HttpBody`).

The 0.14 `Body` could be multiple variants, and in v1 they have been split into
[distinct types][http-body-util]. You'll benefit from analzying each place you
use `hyper::Body` to decide which solution to switch to.

- In general, if you don't need a specific variant, consider making your usage
  generic, accepting an `impl Body` (or `where B: Body`).
- If you want a type that can be any variant, you could use `BoxBody`.
- Otherwise, the [more specific variants][http-body-util] allow for a more
  explicit API in your code.

## `Client`

The higher-level pooling `Client` was removed from hyper 1.0. A similar type
was added to [`hyper-util`][], called [`client::legacy::Client`][legacy]. It's
mostly a drop-in replacement.

## `Server`

The v0.14 `hyper::Server` does not have a drop-in replacement, since it had
problems.

For a server type that can handle both HTTP/1 and HTTP/2 at the same time,
use the [`server::conn::auto::Builder`][auto] from [`hyper-util`][].

The listening server acceptor can be replaced with a simple loop.

## `Service`/`service_fn`

Previously, hyper depended on `tower` for the `Service` trait. Because
`tower` is not yet 1.0, hyper could not publicly depend on it. So, its
`Service` trait and the helper function `service_fn` are defined in
`hyper::service`. Check [middleware](https://hyper.rs/guides/1/server/middleware/) for more details.

[changelog]: https://github.com/hyperium/hyper/blob/master/CHANGELOG.md#v100-2023-11-15
[`hyper-util`]: https://crates.io/crates/hyper-util
[http-body-util]: https://docs.rs/http-body-util
[legacy]: https://docs.rs/hyper-util/latest/hyper_util/client/legacy/struct.Client.html
[auto]: https://docs.rs/hyper-util/latest/hyper_util/server/conn/auto/struct.Builder.html

---

## File: _stable/client/basic.md

---
title: Getting Started with a Client
layout: guide
---

To start with, we'll just get a simple `GET` request to a webpage working,
so we can see all the moving parts. First, we need our dependencies.
Let's tell Cargo about our dependencies by having this in the Cargo.toml.

## Dependencies

```toml
[dependencies]
hyper = { version = "1", features = ["full"] }
tokio = { version = "1", features = ["full"] }
http-body-util = "0.1"
hyper-util = { version = "0.1", features = ["full"] }
```

Now, we need to import pieces to use from our dependencies:

```rust
# extern crate http_body_util;
# extern crate hyper;
# extern crate tokio;
# extern crate hyper_util;
use http_body_util::Empty;
use hyper::Request;
use hyper::body::Bytes;
use hyper_util::rt::TokioIo;
use tokio::net::TcpStream;
# fn main() {}
```

## Runtime

Now, we'll make a request in the `main` of our program. This may seem
like a bit of work just to make a simple request, and you'd be correct,
but the point here is just to show all the setup required. Once you have this,
you are set to make thousands of client requests efficiently.

We have to setup some sort of runtime. You can use whichever async runtime you'd
like, but for this guide we're going to use tokio. If you've never used futures
in Rust before, you may wish to read through [Tokio's guide on Futures][Tokio-Futures].

```rust
# extern crate tokio;
# mod no_run {
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    // This is where we will setup our HTTP client requests.

    Ok(())
}
# }
# fn main() {}
```

## Setup

To get started we'll need to get a few things setup. For this guide we're
going to send a GET [`Request`][Request] to [http://httpbin.org/ip](http://httpbin.org/ip),
which will return a `200 OK` and the Requester's IP address in the body.

We need to open a TCP connection to the remote host using a hostname and port,
which in this case is `httpbin.org` and the default port for HTTP: `80`. With our
connection opened, we pass it in to the `client::conn::http1::handshake` function,
performing a handshake to verify the remote is ready to receive our requests.

A successful handshake will give us a [Connection][Connection] future that processes
all HTTP state, and a [SendRequest][SendRequest] struct that we can use to send our
`Request`s on the connection.

To start driving the HTTP state we have to poll the `Connection`, so to finish our
setup we'll spawn a `tokio::task` and `await` it.

```rust
# extern crate http_body_util;
# extern crate hyper;
# extern crate hyper_util;
# extern crate tokio;
# use http_body_util::Empty;
# use hyper::body::Bytes;
# use hyper::Request;
# use hyper_util::rt::TokioIo;
# use tokio::net::TcpStream;
# async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Parse our URL...
let url = "http://httpbin.org/ip".parse::<hyper::Uri>()?;

// Get the host and the port
let host = url.host().expect("uri has no host");
let port = url.port_u16().unwrap_or(80);

let address = format!("{}:{}", host, port);

// Open a TCP connection to the remote host
let stream = TcpStream::connect(address).await?;

// Use an adapter to access something implementing `tokio::io` traits as if they implement
// `hyper::rt` IO traits.
let io = TokioIo::new(stream);

// Create the Hyper client
let (mut sender, conn) = hyper::client::conn::http1::handshake(io).await?;

// Spawn a task to poll the connection, driving the HTTP state
tokio::task::spawn(async move {
    if let Err(err) = conn.await {
        println!("Connection failed: {:?}", err);
    }
});
# let authority = url.authority().unwrap().clone();
# let req = Request::builder()
#     .uri(url)
#     .header(hyper::header::HOST, authority.as_str())
#     .body(Empty::<Bytes>::new())?;
# let mut res = sender.send_request(req).await?;
# Ok(())
# }
# fn main() {}
```

## GET

Now that we've set up our connection, we're ready to construct and send our first `Request`!
Since `SendRequest` doesn't require absolute-form `URI`s we are required to include a `HOST`
header in our requests. And while we can send our `Request` with an empty `Body`, we need to
explicitly set it, which we'll do with the [`Empty`][Empty] utility struct.

All we need to do now is pass the `Request` to `SendRequest::send_request`, this returns a
future which will resolve to the [`Response`][Response] from `httpbin.org`. We'll print the
status of the response to see that it returned the expected `200 OK` status.

```rust
# extern crate http_body_util;
# extern crate hyper;
# extern crate hyper_util;
# extern crate tokio;
# use http_body_util::Empty;
# use hyper::body::Bytes;
# use hyper::Request;
# use hyper_util::rt::TokioIo;
# use tokio::net::TcpStream;
# async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
# let url = "http://httpbin.org/ip".parse::<hyper::Uri>()?;
# let host = url.host().expect("uri has no host");
# let port = url.port_u16().unwrap_or(80);
# let addr = format!("{}:{}", host, port);
# let stream = TcpStream::connect(addr).await?;
# let io = TokioIo::new(stream);
# let (mut sender, conn) = hyper::client::conn::http1::handshake(io).await?;
# tokio::task::spawn(async move {
# if let Err(err) = conn.await {
# println!("Connection failed: {:?}", err);
# }
# });
// The authority of our URL will be the hostname of the httpbin remote
let authority = url.authority().unwrap().clone();

// Create an HTTP request with an empty body and a HOST header
let req = Request::builder()
    .uri(url)
    .header(hyper::header::HOST, authority.as_str())
    .body(Empty::<Bytes>::new())?;

// Await the response...
let mut res = sender.send_request(req).await?;

println!("Response status: {}", res.status());
# Ok(())
# }
# fn main() {}
```

## Response bodies

We know that sending a GET `Request` to `httpbin.org/ip` will return our IP address in
the `Response` body. To see the returned body, we'll simply write it to `stdout`.

Bodies in hyper are asynchronous streams of [`Frame`][Frame]s, so we don't have to wait for the
whole body to arrive, buffering it into memory, and then writing it out. We can simply
`await` each `Frame` and write them directly to `stdout` as they arrive!

In addition to importing `stdout`, we'll need to make use of the `BodyExt` trait:

```rust
# extern crate http_body_util;
# extern crate tokio;
use http_body_util::BodyExt;
use tokio::io::{AsyncWriteExt as _, self};
```

```rust
# extern crate http_body_util;
# extern crate hyper;
# extern crate hyper_util;
# extern crate tokio;
# use http_body_util::{BodyExt, Empty};
# use hyper::body::Bytes;
# use hyper::Request;
# use hyper_util::rt::TokioIo;
# use tokio::net::TcpStream;
# use tokio::io::{self, AsyncWriteExt as _};
# async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
# let url = "http://httpbin.org/ip".parse::<hyper::Uri>()?;
# let host = url.host().expect("uri has no host");
# let port = url.port_u16().unwrap_or(80);
# let addr = format!("{}:{}", host, port);
# let stream = TcpStream::connect(addr).await?;
# let io = TokioIo::new(stream);
# let (mut sender, conn) = hyper::client::conn::http1::handshake(io).await?;
# tokio::task::spawn(async move {
#     if let Err(err) = conn.await {
#         println!("Connection failed: {:?}", err);
#     }
# });
# let authority = url.authority().unwrap().clone();
# let req = Request::builder()
# .uri(url)
# .header(hyper::header::HOST, authority.as_str())
# .body(Empty::<Bytes>::new())?;
# let mut res = sender.send_request(req).await?;
// Stream the body, writing each frame to stdout as it arrives
while let Some(next) = res.frame().await {
    let frame = next?;
    if let Some(chunk) = frame.data_ref() {
        io::stdout().write_all(chunk).await?;
    }
}
# Ok(())
# }
# fn main() {}
```
And that's it! You can see the [full example here][example].

[Tokio]: https://tokio.rs
[Tokio-Futures]: https://tokio.rs/tokio/tutorial/async
[StatusCode]: {{ site.hyper_docs_url }}/hyper/struct.StatusCode.html
[Response]: {{ site.http_docs_url }}/http/response/struct.Response.html
[Request]: {{ site.http_docs_url }}/http/request/struct.Request.html
[Connection]: {{ site.hyper_docs_url }}/hyper/client/conn/http1/struct.Connection.html
[SendRequest]: {{ site.hyper_docs_url }}/hyper/client/conn/http1/struct.SendRequest.html
[Frame]: {{ site.hyper_docs_url }}/hyper/body/struct.Frame.html
[Empty]: {{ site.http_body_util_url }}/http_body_util/struct.Empty.html

[example]: {{ site.examples_url }}/client.rs

---

## File: _stable/client/connectors.md

---
title: Connectors, Pools, and HTTPS
layout: guide
---

> **Unstable**: The code discussed in this guide is in `hyper-util`,
> which is not as stable as that which is in `hyper`. It is production
> ready, but changes may come more frequently.

_TODO_

## What is a connector?

_TODO_

## Connection Pools

_TODO_

## HTTPS

hyper allows you to bring your own IO, so it can work on top of any TLS
implementation. (TODO: link to runtime guide)

There are also crates that provide "connectors" which result in
easy-to-use HTTPS for the legacy client in `hyper-util`. Each has their
own reason for existing, and pros and cons, but this list is provided to
help you get started[^tls-list]:

- [hyper-tls](https://crates.io/crates/hyper-tls)
- [hyper-rustls](https://crates.io/crates/hyper-rustls)
- [hyper-openssl](https://crates.io/crates/hyper-openssl)

[^tls-list]: This isn't an endorsement for any of the crates, and they all are maintained separately from hyper.

---

## File: _stable/client/index.md

---
title: Client Guides
layout: guide
permalink: /guides/1/client/
---

This is just placeholder page. It should probably become a table of
contents for the client guides.

---

## File: _stable/client/post.md

---
title: Post Request Guides
layout: guide
---

## POST
Now that we've seen how to make a GET request, let's look at how to make a POST request. This is useful when you need to send data to the server, such as when submitting a form or uploading a file.

To make a POST request, we'll need to change a few things from our GET request:

1. We'll set the method to POST.
2. We'll need to provide a request body.
3. We'll need to specify the type of data in our body by adding a `hyper::header::CONTENT_TYPE` header. 

For the body, we have a couple of options. We can use a simple string, a JSON string, or we can use raw bytes. Let's look at all three:

```rust
# extern crate http_body_util;
# extern crate hyper;
# extern crate hyper_util;
# extern crate tokio;
# use http_body_util::{Empty, Full};
# use hyper::body::Bytes;
# use hyper::Request;
# use hyper_util::rt::TokioIo;
# use tokio::net::TcpStream;
# async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
# let url = "http://httpbin.org/ip".parse::<hyper::Uri>()?;
# let host = url.host().expect("uri has no host");
# let port = url.port_u16().unwrap_or(80);
# let addr = format!("{}:{}", host, port);
# let stream = TcpStream::connect(addr).await?;
# let io = TokioIo::new(stream);
# let (mut sender, conn) = hyper::client::conn::http1::handshake(io).await?;
# tokio::task::spawn(async move {
# if let Err(err) = conn.await {
# println!("Connection failed: {:?}", err);
# }
# });

// The authority of our URL will be the hostname of the httpbin remote
let authority = url.authority().unwrap().clone();

// For plain text
let req_body = Full::<Bytes>::from("Some plain text as a body.");
let req = Request::builder()
    .method(hyper::Method::POST)
    .header(hyper::header::HOST, authority.as_str())
    .header(hyper::header::CONTENT_TYPE, "text/plain")
    .body(req_body)?;

// For JSON data
let json_data = r#"{"key": "value"}"#;
let req_body = Full::<Bytes>::from(json_data);
let req = Request::builder()
    .method(hyper::Method::POST)
    .header(hyper::header::HOST, authority.as_str())
    .header(hyper::header::CONTENT_TYPE, "application/json")
    .body(req_body)?;

// For binary data
let binary_data = vec![0u8; 128]; // Example binary data
let req_body = Full::<Bytes>::from(binary_data);
let req = Request::builder()
    .method(hyper::Method::POST)
    .header(hyper::header::HOST, authority.as_str())
    .header(hyper::header::CONTENT_TYPE, "application/octet-stream")
    .body(req_body)?;


let res = sender.send_request(req).await?;

println!("Response status: {}", res.status());
# Ok(())
# }
# fn main() {}
```

---

## File: _stable/init/runtime.md

---
title:  Runtime
layout: guide
permalink: /guides/1/init/runtime/
---

With hyper v1.0 removing `tokio` as runtime dependency, a new runtime trait `hyper::rt` is introduced. If you still want to use `tokio`, a `tokio` implementation for `hyper::rt` is provided by `hyper-util` crate.

## Building your own `hyper::rt` implementations with `Tokio`

Let's build a simple `hyper::rt` implementations with the help of tokio. First, make sure you have `tokio` as a dependency in your `Cargo.toml`:

```toml
[dependencies]
tokio = { version = "1", features = ["full"] }
```

Now, let's try to write a simple executor `hyper::rt::Executor`, we'll call it `TokioExecutor`:

```rust
# extern crate hyper;
/// Future executor that utilises `tokio` threads.
#[non_exhaustive]
#[derive(Default, Debug, Clone)]
pub struct TokioExecutor {}
```

the trait `hyper::rt::Executor` expects an `execute` method that asks the runtime to execute futures. `tokio` allows this easily with `tokio::spawn`

```rust
# extern crate hyper;
# extern crate tokio;

use std::future::Future;

use hyper::rt::Executor;

# #[non_exhaustive]
# #[derive(Default, Debug, Clone)]
# pub struct TokioExecutor {}

impl<Fut> Executor<Fut> for TokioExecutor
where
    Fut: Future + Send + 'static,
    Fut::Output: Send + 'static,
{
    fn execute(&self, fut: Fut) {
        tokio::spawn(fut);
    }
}
```

We now have a working `hyper::rt::Executor` with Tokio, and is ready to be supplied to anything that requires `Executor`. For example, with the auto connection from hyper-util:

```rust
# extern crate hyper;
# extern crate hyper_util;
# extern crate tokio;

use std::future::Future;

use hyper_util::server::conn::auto;
use hyper::rt::Executor;

# #[non_exhaustive]
# #[derive(Default, Debug, Clone)]
# pub struct TokioExecutor {}

# impl<Fut> Executor<Fut> for TokioExecutor
# where
#     Fut: Future + Send + 'static,
#     Fut::Output: Send + 'static,
# {
#     fn execute(&self, fut: Fut) {
#         tokio::spawn(fut);
#     }
# }

impl TokioExecutor {
    pub fn new() -> Self {
        Self {}
    }
}

auto::Builder::new(TokioExecutor::new());
```

## Using `hyper::rt` implementations with tokio in hyper-util

The crate `hyper-util` provides implementations for `hyper::rt` traits with Tokio. To use, we'll need to have `hyper-util` as a dependency.

```toml
[dependencies]
hyper-util = { version = "0.1", features = ["full"] }
```

Then you'll simply need to import and use it as in the example above

```rust
# extern crate hyper;
# extern crate hyper_util;

use hyper::rt::Executor;
use hyper_util::rt::TokioExecutor;
use hyper_util::server::conn::auto;

auto::Builder::new(TokioExecutor::new());
```

There are more implementations in the hyper_util crate. Check out the docs on [`hyper_util::rt`][] for more details.

[`hyper_util::rt`]: https://docs.rs/hyper-util/latest/hyper_util/rt/index.html

---

## File: _stable/init/setup.md

---
title:  Initial Setup
layout: guide
permalink: /guides/1/init/setup/
---

This will help get your initial setup ready to be able to try out the
lessons in the guides.

## Dependencies

To make things simple, you can add the follow crates to your
`Cargo.toml`:

```toml
[dependencies]
hyper = { version = "1", features = ["full"] }
tokio = { version = "1", features = ["full"] }
http-body-util = "0.1"
hyper-util = { version = "0.1", features = ["full"] }
```

And with that, you're good to go! Depending on what you want to
accomplish, you can move on to either the [client][] or [server][]
guides.

[client]: ../../client/basic
[server]: ../../server/hello-world/

---

## File: _stable/server/echo.md

---
title: Echo, echo, echo
layout: guide
---

You already have a [Hello World server](../hello-world)? Excellent! Usually,
servers do more than just spit out the same body for every request. To
exercise several more parts of hyper, this guide will go through
building an echo server.

An echo server will listen for incoming connections and send back the
request body as the response body on `POST` requests.

## Routing

First thing we will do, beyond renaming our service to `echo`, is setup some
routing. We want to have a route explaining instructions on how to use
our server, and another for receiving data. Oh, and we should also
handle the case when someone asks for a route we don't know!

Before we get started we need to add some new imports:

```rust
# extern crate hyper;
# extern crate http_body_util;
use hyper::body::Frame;
use hyper::{Method, StatusCode};
use http_body_util::{combinators::BoxBody, BodyExt};
# fn main() {}
```

Next, we need to make some changes to our `Service` function, but as you can see
it's still just an async function that takes a `Request` and returns a `Response`
future, and you can pass it to your server just like we did for the `hello` service.

Unlike our `hello` service where we didn't care about the request body and 
we always returned a single chunk of bytes containing our greeting, we're now
going to want a bit more freedom in how we shape our response `Body`. To achieve
this we will change the type of the `Body` in our `Response` to a boxed trait object. 
We only care that the response body implements the [Body](https://docs.rs/http-body/1.0.0-rc1/http_body/trait.Body.html) trait, that its data is `Bytes` and its error is a `hyper::Error`.

```rust
# extern crate hyper;
# extern crate http_body_util;
# use hyper::body::Bytes;
# use http_body_util::{combinators::BoxBody, BodyExt, Empty, Full};
# use hyper::{Method, Request, Response, StatusCode};
async fn echo(
    req: Request<hyper::body::Incoming>,
) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
    match (req.method(), req.uri().path()) {
        (&Method::GET, "/") => Ok(Response::new(full(
            "Try POSTing data to /echo",
        ))),
        (&Method::POST, "/echo") => {
            // we'll be back
# Ok(Response::new(req.into_body().boxed()))
        },

        // Return 404 Not Found for other routes.
        _ => {
            let mut not_found = Response::new(empty());
            *not_found.status_mut() = StatusCode::NOT_FOUND;
            Ok(not_found)
        }
    }
}

// We create some utility functions to make Empty and Full bodies
// fit our broadened Response body type.
fn empty() -> BoxBody<Bytes, hyper::Error> {
    Empty::<Bytes>::new()
        .map_err(|never| match never {})
        .boxed()
}
fn full<T: Into<Bytes>>(chunk: T) -> BoxBody<Bytes, hyper::Error> {
    Full::new(chunk.into())
        .map_err(|never| match never {})
        .boxed()
}
# fn main() {}
```

We built a super simple routing table just by matching on the `method` and `path` 
of an incoming `Request`. If someone requests `GET /`, our service will let them 
know they should try our echo powers out. We also check for `POST /echo`, but 
currently don't do anything about it.

Our third rule catches any other method and path combination, and changes the 
`StatusCode` of the `Response`. The default status of a `Response` is HTTP’s 
`200 OK` (`StatusCode::OK`), which is correct for the other routes. But the third 
case will instead send back `404 Not Found`.

## Body Streams

Now let's get that echo in place. An HTTP body is a stream of `Frames`, each 
[Frame](https://docs.rs/http-body/1.0.0-rc1/http_body/struct.Frame.html) containing 
parts of the `Body` data or trailers. So rather than reading the entire `Body` 
into a buffer before sending our response, we can stream each frame as it arrives. 
We'll start with the simplest solution, and then make alterations exercising more complex 
things you can do with the `Body` streams.

First up, plain echo. Both the `Request` and the `Response` have body streams,
and by default, you can easily pass the `Body` of the `Request` into a `Response`.

```rust
# extern crate hyper;
# extern crate http_body_util;
# use hyper::body::Bytes;
# use http_body_util::{combinators::BoxBody, BodyExt, Empty, Full};
# use hyper::{Method, Request, Response, StatusCode};
# async fn echo(
#    req: Request<hyper::body::Incoming>,
# ) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
#    match (req.method(), req.uri().path()) {
// Inside the match from before
(&Method::POST, "/echo") => Ok(Response::new(req.into_body().boxed())),
#        _ => unreachable!(),
#    }
# }
# fn main() {}
```

Running our server now will echo any data we `POST` to `/echo`. That was easy.
What if we wanted to uppercase all the text? We could use a `map` on our streams.

## Body mapping

Every data `Frame` of our body stream is a chunk of bytes, which we can conveniently
represent using the `Bytes` type from hyper. It can be easily converted into other
typical containers of bytes.

Next, let's add a new `/echo/uppercase` route, mapping each byte in the data `Frame`s
of our request body to uppercase, and returning the stream in our `Response`:

```rust
# extern crate hyper;
# extern crate http_body_util;
# use hyper::body::Bytes;
# use http_body_util::{combinators::BoxBody, BodyExt, Empty, Full};
# use hyper::body::Frame;
# use hyper::{Method, Request, Response, StatusCode};
# async fn echo(
#    req: Request<hyper::body::Incoming>,
# ) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
#    match (req.method(), req.uri().path()) {
// Yet another route inside our match block...
(&Method::POST, "/echo/uppercase") => {
    // Map this body's frame to a different type
    let frame_stream = req.into_body().map_frame(|frame| {
        let frame = if let Ok(data) = frame.into_data() {
            // Convert every byte in every Data frame to uppercase
            data.iter()
                .map(|byte| byte.to_ascii_uppercase())
                .collect::<Bytes>()
        } else {
            Bytes::new()
        };

        Frame::data(frame)
    });

    Ok(Response::new(frame_stream.boxed()))
},
#         _ => unreachable!(),
#     }
# }
# fn full<T: Into<Bytes>>(chunk: T) -> BoxBody<Bytes, hyper::Error> {
#     Full::new(chunk.into())
#         .map_err(|never| match never {})
#         .boxed()
# }
# fn main() {}
```

And like that, we have two echo routes: `/echo` which does no transformation,
and `/echo/uppercase` which returns all bytes after converting them to ASCII
uppercase.

## Buffering the Request Body

What if we want our echo service to reverse the data it received and send it
back to us? We can't really stream the data as it comes in, since we need to
find the end before we can respond. To do this, we can explore how to easily
collect the full body.

We want to collect the entire request body and map the result into our `reverse` 
function, then return the eventual result. If we import the `http_body_util::BodyExt`
extension trait, we can call the `collect` method on our body, which will drive the
stream to completion, collecting all the data and trailer frames into a `Collected` type.
We can easily turn the `Collected` body into a single `Bytes` by calling its `into_bytes` 
method.

> Note: You must always be careful not to buffer without a max bounds. We'll
> set a 64kb maximum here.

```rust
# extern crate hyper;
# extern crate http_body_util;
# use hyper::body::Bytes;
# use http_body_util::{combinators::BoxBody, BodyExt, Empty, Full};
# use hyper::{body::Body, Method, Request, Response, StatusCode};
# async fn echo(
#    req: Request<hyper::body::Incoming>,
# ) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
#    match (req.method(), req.uri().path()) {
// Yet another route inside our match block...
(&Method::POST, "/echo/reversed") => {
    // Protect our server from massive bodies.
    let upper = req.body().size_hint().upper().unwrap_or(u64::MAX);
    if upper > 1024 * 64 {
        let mut resp = Response::new(full("Body too big"));
        *resp.status_mut() = hyper::StatusCode::PAYLOAD_TOO_LARGE;
        return Ok(resp);
    }

    // Await the whole body to be collected into a single `Bytes`...
    let whole_body = req.collect().await?.to_bytes();

    // Iterate the whole body in reverse order and collect into a new Vec.
    let reversed_body = whole_body.iter()
        .rev()
        .cloned()
        .collect::<Vec<u8>>();

    Ok(Response::new(full(reversed_body)))
},
#         _ => unreachable!(),
#     }
# }
# fn full<T: Into<Bytes>>(chunk: T) -> BoxBody<Bytes, hyper::Error> {
#     Full::new(chunk.into())
#         .map_err(|never| match never {})
#         .boxed()
# }
# fn main() {}
```

You can see a compiling [example here][example].

[example]: {{ site.examples_url }}/echo.rs

---

## File: _stable/server/graceful-shutdown.md

---
title:  Gracefully Shutdown a Server
layout: guide
redirect_from:
    - /guides/server/graceful-shutdown
---

hyper's server connections have the ability to initiate a graceful shutdown. A common desire is to coordinate graceful shutdown across all active connections. This is what we'll tackle in this guide.

> A **graceful shutdown** is when a connection stops allowing _new_ requests, while allowing currently in-flight requests to complete.

In order to do, we'll need several pieces:

1. A signal for when to start the shutdown.
2. An accept loop handling newly received connections.
3. A watcher to coordinate the shutdown.

## Determine a shutdown signal

You can use any mechanism to signal that graceful shutdown should begin. That could be an process signal handler, a timer, a special HTTP request, or anything else.

We're going to use a `CTRL+C` signal handler for this guide. Tokio has simple support for making one, let's try:

```rust
# extern crate tokio;
async fn shutdown_signal() {
    // Wait for the CTRL+C signal
    tokio::signal::ctrl_c()
        .await
        .expect("failed to install CTRL+C signal handler");
}
# fn main() {}
```

## Modify your server accept loop

> **Unstable**: The code discussed in this guide is in `hyper-util`,
> which is not as stable as that which is in `hyper`. It is production
> ready, but changes may come more frequently.

We're assuming you have an accept loop for your server, similar to what was shown in the [Hello World](hello-world.md) guide. So, we're just going to modify it here:

```rust
# extern crate hyper;
# extern crate http_body_util;
# extern crate hyper_util;
# extern crate tokio;
# mod no_run {
# use std::convert::Infallible;
# use std::net::SocketAddr;
#
# use http_body_util::Full;
# use hyper::body::Bytes;
# use hyper::server::conn::http1;
# use hyper::service::service_fn;
# use hyper::{Request, Response};
# use hyper_util::rt::TokioIo;
# use tokio::net::TcpListener;
# async fn shutdown_signal() {}
# async fn hello(
#     _: Request<hyper::body::Incoming>,
# ) -> Result<Response<Full<Bytes>>, Infallible> {
#     Ok(Response::new(Full::new(Bytes::from("Hello World!"))))
# }
# async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
# let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let listener = TcpListener::bind(addr).await?;
// specify our HTTP settings (http1, http2, auto all work)
let http = http1::Builder::new();
// the graceful watcher
let graceful = hyper_util::server::graceful::GracefulShutdown::new();
// when this signal completes, start shutdown
let mut signal = std::pin::pin!(shutdown_signal());

// Our server accept loop
loop {
    tokio::select! {
        Ok((stream, _addr)) = listener.accept() => {
            let io = TokioIo::new(stream);
            let conn = http.serve_connection(io, service_fn(hello));
            // watch this connection
            let fut = graceful.watch(conn);
            tokio::spawn(async move {
                if let Err(e) = fut.await {
                    eprintln!("Error serving connection: {:?}", e);
                }
            });
        },

        _ = &mut signal => {
            drop(listener);
            eprintln!("graceful shutdown signal received");
            // stop the accept loop
            break;
        }
    }
}

// Now start the shutdown and wait for them to complete
// Optional: start a timeout to limit how long to wait.

tokio::select! {
    _ = graceful.shutdown() => {
        eprintln!("all connections gracefully closed");
    },
    _ = tokio::time::sleep(std::time::Duration::from_secs(10)) => {
        eprintln!("timed out wait for all connections to close");
    }
}
# Ok(())
# }
# }
# fn main() {}
```

---

## File: _stable/server/hello-world.md

---
title:  Getting Started with a Server
layout: guide
---

Let's start by making a "Hello, World!" server, and expand from there.

First, we need to declare our dependencies, let's add the following to our `Cargo.toml`:

```toml
[dependencies]
hyper = { version = "1", features = ["full"] }
tokio = { version = "1", features = ["full"] }
http-body-util = "0.1"
hyper-util = { version = "0.1", features = ["full"] }
```

Next, we need to add some imports in our `main.rs` file:

```rust
# extern crate tokio;
# extern crate hyper;
# extern crate http_body_util;
# extern crate hyper_util;
use std::convert::Infallible;
use std::net::SocketAddr;

use http_body_util::Full;
use hyper::body::Bytes;
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper::{Request, Response};
use hyper_util::rt::TokioIo;
use tokio::net::TcpListener;
# fn main() {}
```

## Creating a Service

A [`Service`][service] lets us define how our server will respond to 
incoming requests. It represents an async function that takes a 
[`Request`][request] and returns a `Future`. When the processing of this
future is complete, it will resolve to a [`Response`][response] or an error.

Hyper provides a utility for creating a `Service` from a function that should 
serve most use cases: [`service_fn`][service_fn]. We will use this to create 
a service from our `hello` function below when we're ready to start our 
server.

```rust
# extern crate hyper;
# extern crate http_body_util;
# use std::convert::Infallible;
# use http_body_util::Full;
# use hyper::body::Bytes;
# use hyper::{Request, Response};
# fn main() {}
async fn hello(_: Request<hyper::body::Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
    Ok(Response::new(Full::new(Bytes::from("Hello, World!"))))
}
```

Using this function as a service, we tell our server to respond to all requests 
with a default `200 OK` status. The response `Body` will contain our friendly
greeting as a single chunk of bytes, and the `Content-Length` header will be 
set automatically.

## Starting the Server

Lastly, we need to hook up our `hello` service into a running Hyper server.

We'll dive in to the specifics of some of these things in another guide.

```rust
# extern crate tokio;
# extern crate hyper;
# extern crate http_body_util;
# extern crate hyper_util;
# mod no_run {
# use std::convert::Infallible;
# use std::net::SocketAddr;
# 
# use http_body_util::Full;
# use hyper::body::Bytes;
# use hyper::server::conn::http1;
# use hyper::service::service_fn;
# use hyper::{Request, Response};
# use hyper_util::rt::TokioIo;
# use tokio::net::TcpListener;
# async fn hello(
#     _: Request<hyper::body::Incoming>,
# ) -> Result<Response<Full<Bytes>>, Infallible> {
#     Ok(Response::new(Full::new(Bytes::from("Hello World!"))))
# }
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

    // We create a TcpListener and bind it to 127.0.0.1:3000
    let listener = TcpListener::bind(addr).await?;

    // We start a loop to continuously accept incoming connections
    loop {
        let (stream, _) = listener.accept().await?;

        // Use an adapter to access something implementing `tokio::io` traits as if they implement
        // `hyper::rt` IO traits.
        let io = TokioIo::new(stream);

        // Spawn a tokio task to serve multiple connections concurrently
        tokio::task::spawn(async move {
            // Finally, we bind the incoming connection to our `hello` service
            if let Err(err) = http1::Builder::new()
                // `service_fn` converts our function in a `Service`
                .serve_connection(io, service_fn(hello))
                .await
            {
                eprintln!("Error serving connection: {:?}", err);
            }
        });
    }
}
# }
# fn main() {}
```

To see all the snippets put together, check out the [full example][example]!

Also, if `service_fn` doesn't meet your requirements and you'd like to implement 
`Service` yourself, see this [example][impl service].

## HTTP/2

This example uses the `http1` module to create a server that speaks HTTP/1.
In case you want to use HTTP/2, you can use the `http2` module with a few changes to the
http1 server. The http2 builder requires an executor to run. Executor should implement the `hyper::rt::Executor` trait.

To implement the Executor, check out the runtime [example][runtime].
To see the full example with HTTP/2, check out the [full example][example_http2]!

[service]: {{ site.hyper_docs_url }}/hyper/service/trait.Service.html
[service_fn]: {{ site.hyper_docs_url }}/hyper/service/fn.service_fn.html
[request]: {{ site.hyper_docs_url }}/hyper/struct.Request.html
[response]: {{ site.hyper_docs_url }}/hyper/struct.Response.html
[parts]: {{ site.http_docs_url }}/http/response/struct.Parts.html
[example]: {{ site.examples_url }}/hello.rs
[example_http2]: {{ site.examples_url }}/hello-http2.rs 
[runtime]: ../init/runtime.md
[impl service]: {{ site.examples_url }}/service_struct_impl.rs

---

## File: _stable/server/index.md

---
title: Server Guides
layout: guide
permalink: /guides/1/server/
---

This is just placeholder page. It should probably become a table of
contents for the server guides.

---

## File: _stable/server/middleware.md

---
title: Getting Started with a Server Middleware
layout: guide
---

As [Upgrade][upgrading] mentioned, hyper v1 does not depend on tower for the `Service` trait. When we want to add tower-like middleware, there are 2 kinds of approach to make it.

Let's create a Logger middleware in [hello-world server][hello-world] for instance:

Add tower dependency first

```toml
[dependencies]
hyper = { version = "1", features = ["full"] }
tokio = { version = "1", features = ["full"] }
http-body-util = "0.1"
hyper-util = { version = "0.1", features = ["full"] }
tower = "0.4" # here
```

## Option 1: Use hyper Service trait

Implement hyper Logger middleware

```rust
# extern crate hyper;
use hyper::{Request, body::Incoming, service::Service};

#[derive(Debug, Clone)]
pub struct Logger<S> {
    inner: S,
}
impl<S> Logger<S> {
    pub fn new(inner: S) -> Self {
        Logger { inner }
    }
}
type Req = Request<Incoming>;

impl<S> Service<Req> for Logger<S>
where
    S: Service<Req>,
{
    type Response = S::Response;
    type Error = S::Error;
    type Future = S::Future;
    fn call(&self, req: Req) -> Self::Future {
        println!("processing request: {} {}", req.method(), req.uri().path());
        self.inner.call(req)
    }
}
# fn main() {}
```

Then this can be used in server:

```rust
# extern crate tower;
# extern crate hyper;
# extern crate http_body_util;
# extern crate tokio;
# extern crate hyper_util;
# mod no_run {
use std::{convert::Infallible, net::SocketAddr};
use hyper::{
    service::Service,
    body::{Bytes, Incoming},
    server::conn::http1,
    Request, Response,
};
use http_body_util::Full;
use hyper_util::rt::TokioIo;
use tokio::net::TcpListener;
use tower::ServiceBuilder;

# #[derive(Debug, Clone)]
# pub struct Logger<S> {
#     inner: S,
# }
# impl<S> Logger<S> {
#    pub fn new(inner: S) -> Self {
#        Logger { inner }
#    }
# }
# type Req = Request<Incoming>;

# impl<S> Service<Req> for Logger<S>
# where
#     S: Service<Req>,
# {
#     type Response = S::Response;
#     type Error = S::Error;
#     type Future = S::Future;
#     fn call(&self, req: Req) -> Self::Future {
#         println!("processing request: {} {}", req.method(), req.uri().path());
#         self.inner.call(req)
#     }
# }
async fn hello(_: Request<Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
    Ok(Response::new(Full::new(Bytes::from("Hello, World!"))))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    let listener = TcpListener::bind(addr).await?;
    loop {
        let (stream, _) = listener.accept().await?;
        let io = TokioIo::new(stream);
        tokio::spawn(async move {
            // N.B. should use hyper service_fn here, since it's required to be implemented hyper Service trait!
            let svc = hyper::service::service_fn(hello);
            let svc = ServiceBuilder::new().layer_fn(Logger::new).service(svc);
            if let Err(err) = http1::Builder::new().serve_connection(io, svc).await {
                eprintln!("server error: {}", err);
            }
        });
    }
}
# }
# fn main() {}
```

## Option 2: use hyper TowerToHyperService trait

[hyper_util::service::TowerToHyperService][adapter-trait] trait is an adapter to convert tower Service to hyper Service.

Now implement a tower Logger middleware

```rust
# extern crate tower;
# extern crate hyper;
use hyper::{Request, body::Incoming};
use tower::Service;

#[derive(Debug, Clone)]
pub struct Logger<S> {
    inner: S,
}
impl<S> Logger<S> {
    pub fn new(inner: S) -> Self {
        Logger { inner }
    }
}
type Req = Request<Incoming>;
impl<S> Service<Req> for Logger<S>
where
    S: Service<Req> + Clone,
{
    type Response = S::Response;

    type Error = S::Error;

    type Future = S::Future;

    fn poll_ready(
        &mut self,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Result<(), Self::Error>> {
        self.inner.poll_ready(cx)
    }

    fn call(&mut self, req: Req) -> Self::Future {
        println!("processing request: {} {}", req.method(), req.uri().path());
        self.inner.call(req)
    }
}
# fn main() {}
```

Then use it in the server:

```rust
# extern crate hyper;
# extern crate http_body_util;
# extern crate hyper_util;
# extern crate tokio;
# extern crate tower;
# mod no_run {
use std::{convert::Infallible, net::SocketAddr};

use hyper::{
    body::{Bytes, Incoming},
    server::conn::http1,
    Request, Response,
};

use http_body_util::Full;
use hyper_util::{rt::TokioIo, service::TowerToHyperService};
use tokio::net::TcpListener;
use tower::{ServiceBuilder, Service};

# #[derive(Debug, Clone)]
# pub struct Logger<S> {
#     inner: S,
# }
# impl<S> Logger<S> {
#     pub fn new(inner: S) -> Self {
#         Logger { inner }
#     }
# }
# type Req = Request<Incoming>;
# impl<S> Service<Req> for Logger<S>
# where
#     S: Service<Req> + Clone,
# {
#     type Response = S::Response;

#     type Error = S::Error;

#     type Future = S::Future;

#     fn poll_ready(
#         &mut self,
#         cx: &mut std::task::Context<'_>,
#     ) -> std::task::Poll<Result<(), Self::Error>> {
#         self.inner.poll_ready(cx)
#     }

#     fn call(&mut self, req: Req) -> Self::Future {
#         println!("processing request: {} {}", req.method(), req.uri().path());
#         self.inner.call(req)
#     }
# }

async fn hello(_: Request<Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
    Ok(Response::new(Full::new(Bytes::from("Hello, World!"))))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    let listener = TcpListener::bind(addr).await?;
    loop {
        let (stream, _) = listener.accept().await?;
        let io = TokioIo::new(stream);
        tokio::spawn(async move {
            // N.B. should use tower service_fn here, since it's required to be implemented tower Service trait before convert to hyper Service!
            let svc = tower::service_fn(hello);
            let svc = ServiceBuilder::new().layer_fn(Logger::new).service(svc);
            // Convert it to hyper service
            let svc = TowerToHyperService::new(svc);
            if let Err(err) = http1::Builder::new().serve_connection(io, svc).await {
                eprintln!("server error: {}", err);
            }
        });
    }
}
# }
# fn main() {}
```

[hello-world]: {{ site.url }}/guides/1/server/hello-world/
[upgrading]: {{ site.url }}/guides/1/upgrading/
[adapter-trait]: {{ site.hyper_util_url }}/latest/hyper_util/service/struct.TowerToHyperService.html

---

## File: .github/workflows/CI.yml

name: CI
on:
  pull_request:
  push:
    branches:
      - master

env:
  RUST_BACKTRACE: 1

permissions:
  contents: read # to fetch code (actions/checkout)

jobs:
  ci-pass:
    name: CI is green
    runs-on: ubuntu-latest
    needs:
      - test
    steps:
      - run: exit 0

  test:
    name: Test ${{ matrix.rust }} on ${{ matrix.os }}
    strategy:
      matrix:
        rust:
          - stable
          - beta

        os:
          - ubuntu-latest

    runs-on: ${{ matrix.os }}

    steps:
      - name: Checkout
        uses: actions/checkout@v7

      - name: Install Rust (${{ matrix.rust }})
        uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ matrix.rust }}

      - name: Test
        run: ./.github/workflows/check_guides.sh

---

## File: .github/workflows/contrib.yml

name: contrib
on:
  schedule:
    - cron: '15 3 * * *'
  workflow_dispatch:

permissions:
  contents: write # to update _contrib
  pull-requests: write # to send the updated _contrib PRs

jobs:
  update-contrib:
    name: Update _contrib
    runs-on: ubuntu-latest

    steps:
      - name: Checkout website
        uses: actions/checkout@v7
        with:
          persist-credentials: false

      - name: Checkout hyper
        uses: actions/checkout@v7
        with:
          persist-credentials: false
          path: hyper

      - name: Copy CONTRIBUTING.md into docs
        run: |
          sed -i -e 's|./docs/||g' hyper/CONTRIBUTING.md
          cp -a hyper/CONTRIBUTING.md hyper/docs/CONTRIBUTING.md

      - name: Generate HIP index
        run: |
          index=hyper/docs/hips/index.md
          printf '# hyper Improvement Proposals\n\n' > "$index"
          for f in hyper/docs/hips/[0-9][0-9][0-9][0-9]-*.md; do
            if [[ "$(basename "$f")" == '0000-template.md' ]]; then
              continue
            fi

            title=$(sed -n '1s/^# //p' "$f")
            path=$(basename "$f" .md)
            printf -- '- [%s](./%s/)\n' "$title" "$path" >> "$index"
          done

      # Insert frontmatter borders, replace markdown header with
      # frontmatter title and insert: 
      #   - layout: guide
      #   - hyper_path: {path}
      - name: Convert doc titles to frontmatter 
        run: |
          find hyper/docs -mindepth 1 -maxdepth 2 -type f -name '*.md' -print0 |
          while IFS= read -r -d '' f; do
            sed -i -e '1i ---' \
            -e '1s/^# /title: >-\n  /' \
            -e '2i layout: guide' \
            -e "2i hyper_path: ${f#hyper/}" \
            -e '2i ---' "$f"
          done

      # CONTRIBUTING.md is uniquely copied into the docs folder.
      # This adjustment links the correct source file.
      - name: Retain correct CONTRIBUTING.md path
        run: |
          sed -i -e '4s/docs\///' hyper/docs/CONTRIBUTING.md

      # Use the hyper docs readme as the index page of contrib,
      # and insert permalink: /contrib/ in the frontmatter
      - name: Convert readme to index
        run: |
          sed -i -e '4i permalink: /contrib/' hyper/docs/README.md
          mv hyper/docs/README.md hyper/docs/index.md
          sed -i -e '/^hyper_path:/d' hyper/docs/hips/index.md
          sed -i -e '4i permalink: /contrib/hips/' hyper/docs/hips/index.md


      # Lowercase the internal links and replace underscores with
      # hyphens, so they will point to the correct file.
      - name: Lowercase internal links
        run: |
          mapfile -d '' markdown_files < <(
            find hyper/docs -mindepth 1 -maxdepth 2 -type f -name '*.md' -print0
          )

          for filename in "${markdown_files[@]}"; do
            # since we move some docs from hyper root into the docs folder,
            # fix links to them
            if [[ "$filename" != hyper/docs/hips/* ]]; then
              sed -i -e 's|\.\./|\./|g' "$filename"
            fi

            # cut `.md` from the filename before search and replace
            filename=${filename::-3};

            for file in "${markdown_files[@]}"; do
              # filename without parent path
              filename=${filename##*/}

              # don't lowercase MSRV
              if [[ "${filename}" == 'MSRV' ]]; then
                continue
              fi

              # lowercase filenames outside frontmatter
              sed -i -e "1,/^---$/!s|${filename}|${filename,,}|g" "$file"

              # match on the lowercased filename from here on
              lowercased=${filename,,}

              hyphenated=${lowercased//_/-}

              # replace underscores in internal links with hyphens
              sed -i -e "s|${lowercased}|${hyphenated}|g" "$file"
            done
          done

      - name: Lowercase filenames and replace underscores
        run: |
          find hyper/docs -mindepth 1 -maxdepth 2 -type f -print0 |
          while IFS= read -r -d '' f; do
            directory=$(dirname "$f")
            filename=$(basename "$f" | tr '[:upper:]' '[:lower:]' | tr '_' '-')
            mv -vn "$f" "$directory/$filename" || true
          done

      - name: Copy the hyper docs to contrib
        run: |
          mkdir -p _contrib
          cp -a hyper/docs/. _contrib/

      - uses: gr2m/create-or-update-pull-request-action@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          author: github-actions <github-actions@github.com>
          branch: actions/update-contrib
          title: 'doc: update contrib docs'
          body: >
            The _contrib docs are likely out of date. This is an automatically 
            generated PR by the `contrib.yml` GitHub workflow, which clones the docs
            from the main repo, implements the changes in _contrib then submits a new 
            PR or updates an existing PR.
          commit-message: 'doc: update contrib docs'
          path: _contrib/