<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>seanmonstar</title>
    <description>My name is Sean McArthur, and here I blabber on about Rust, networking, open source, and a better web.
</description>
    <link>https://seanmonstar.com/</link>
    <atom:link href="https://seanmonstar.com/rss" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 23 Jul 2026 15:39:07 +0000</pubDate>
    <lastBuildDate>Thu, 23 Jul 2026 15:39:07 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
    
      <item>
        <title>Micro: Accessors can reveal internal representation</title>
        <description>&lt;p&gt;As a library maintainer, it’s common to receive requests from users to add a “simple accessor”. The data is &lt;em&gt;right there&lt;/em&gt;. But that accessor can end up revealing internal representation details that you can no longer change.&lt;/p&gt;

&lt;p&gt;This is one reason why it could be a better practice to return an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Iterator&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;[T]&lt;/code&gt;. The latter freezes you in place to always storing the data in consecutive memory. (Such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String::as_bytes()&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;View types might help too, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ref&amp;lt;&apos;_&amp;gt;&lt;/code&gt;. Returning a reference requires the data already exist in that shape in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt;. You can’t change its shape in the accessor and return a reference to &lt;em&gt;that&lt;/em&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 21 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://seanmonstar.com/micro/20260721-accessors-reveal-internal-repr/</link>
        <guid isPermaLink="true">https://seanmonstar.com/micro/20260721-accessors-reveal-internal-repr/</guid>
        
        <category>rust</category>
        
        
      </item>
    
      <item>
        <title>Micro: Rust Errors generally shouldn&apos;t be PartialEq</title>
        <description>&lt;p&gt;Errors might have internal details that don’t make sense to compare. Like positional data, or a source chain. Even if you don’t have those details yet, committing to a public API of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PartialEq&lt;/code&gt; can restrict you from internal refactoring.&lt;/p&gt;

&lt;p&gt;The common reason to want this is for testing purposes. People want to assert an error case matches what they expect. But that doesn’t need equality. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;matches!&lt;/code&gt; , &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind()&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_*()&lt;/code&gt; patterns fit better.&lt;/p&gt;

&lt;p&gt;A public, exhaustive, flat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt; could choose differently. But those look more like a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind()&lt;/code&gt;. If you have private error details, I don’t think they make sense for comparing.&lt;/p&gt;

&lt;p&gt;Some interesting discussion a &lt;a href=&quot;https://www.reddit.com/r/rust/comments/n12uf9/is_there_a_good_reason_not_to_impl_eqpartialeq/&quot;&gt;few years ago&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Mon, 13 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://seanmonstar.com/micro/20260713-errors-not-partialeq/</link>
        <guid isPermaLink="true">https://seanmonstar.com/micro/20260713-errors-not-partialeq/</guid>
        
        
      </item>
    
      <item>
        <title>Micro: Owning my microblog with POSSE</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://indieweb.org/POSSE&quot;&gt;POSSE&lt;/a&gt; is the practice of publishing on your own site first, and pushing that out to other services. To get the content where people are, while linking back to the original owned post.&lt;/p&gt;

&lt;p&gt;I now have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/micro&lt;/code&gt; blog on my own website, and automation (a GH action) to break up new posts and send them to Mastodon and Bluesky as threads. It even has it’s own &lt;a href=&quot;https://seanmonstar.com/micro/rss&quot;&gt;rss feed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This new setup lets me nudge people more towards my own property. As various other properties come and go, my online identity and content lasts longer.&lt;/p&gt;

&lt;p&gt;And it solves one of my &lt;a href=&quot;https://masto.ai/@seanmonstar/109319880660929327&quot;&gt;longer-standing concerns&lt;/a&gt; about microblogging: it feels like they can be more important content now, because they’re &lt;em&gt;mine&lt;/em&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://seanmonstar.com/micro/20260623-owning-my-microblog-with-posse/</link>
        <guid isPermaLink="true">https://seanmonstar.com/micro/20260623-owning-my-microblog-with-posse/</guid>
        
        
      </item>
    
      <item>
        <title>hyper User Survey 2025 Results</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; is the widely-used HTTP library for Rust. We ran the first &lt;a href=&quot;https://seanmonstar.com/blog/hyper-user-survey-2025/&quot;&gt;user survey for hyper in November 2025&lt;/a&gt;. Here’s the results and some analysis.&lt;sup id=&quot;fnref:burnout&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:burnout&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h2 id=&quot;why-did-we-do-a-survey&quot;&gt;Why did we do a survey?&lt;/h2&gt;

&lt;p&gt;We ran a survey to make sure we focus on the right things. It’s part of being user-driven, working backwards.&lt;/p&gt;

&lt;p&gt;The amount of work required to get &lt;em&gt;some&lt;/em&gt; data has an outsized return on your investment. When you know nothing, just a little bit of work means you now know &lt;em&gt;something&lt;/em&gt;. And knowing what users need is a requirement to making an actually useful tool.&lt;/p&gt;

&lt;p&gt;I keep &lt;a href=&quot;https://seanmonstar.com/retainer&quot;&gt;high-touch, high-context relationships&lt;/a&gt; with some users that greatly informs me on what is needed. And reported issues also provide a way to see what is wrong. But a survey provides a new lens for identifying what is needed.&lt;/p&gt;

&lt;p&gt;Sure, surveys have their own biases to deal with, such as self-selection. And voting in a survey costs very little, so each individual answer has less weight. But it helps quantify things we supposedly know from just a few users. Does this problem only show up in weird circumstances, or do most people run into it? Are there things that many people want, but generally don’t get a chance to tell me?&lt;/p&gt;

&lt;h2 id=&quot;the-results&quot;&gt;The results&lt;/h2&gt;

&lt;p&gt;We had a total of 206 unique respondents. I’ve broken up the results by theme and question below.&lt;/p&gt;

&lt;h3 id=&quot;current-usage&quot;&gt;Current usage&lt;/h3&gt;

&lt;p&gt;Many of the questions were about current usage patterns. To get more context on answers, to see what works, and also to see what people &lt;em&gt;don’t&lt;/em&gt; mention using.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Versions&lt;/strong&gt;: Nearly every single respondent is using hyper v1.x, but about 13% also continue to use the end-of-life v0.14.x.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Roles&lt;/strong&gt;: Over 80% said they use hyper in a server, and the same amount in a client. 30% said they use both modes together as a proxy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Runtimes&lt;/strong&gt;: Unsurprisingly, 99% use hyper with the Tokio runtime. But 10% said they &lt;em&gt;also&lt;/em&gt; at times use a different runtime. Most commonly that’s with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;smol&lt;/code&gt;, but io-uring runtimes made up a couple percent points.&lt;sup id=&quot;fnref:byor&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:byor&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLS&lt;/strong&gt;: hyper provides the HTTP, and asks users to bring the S. 93% said they use rustls. 30% make use of native-tls, 15% openssl specifically, and it trails off from there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On top of hyper&lt;/strong&gt;: regarding the rest of the local ecosystem, 86% use reqwest, and 79% use Axum. About half selected Tower. For future surveys, it’d be very helpful to know if people use Tower without Axum or reqwest, or perhaps mentioned it because they just know its a dependency of Axum. A few wrote-in Tonic, which in hindsight, duh of course.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Number of engineers&lt;/strong&gt;: half of respondents said they (and possibly a colleague) are the only ones at their company using hyper. Another 22% said 4-10, 12% said 11-50, and 17% said 50 or more. It’s likely some places focus on higher levels, but many other companies have a lot of engineers working with hyper!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Years of usage&lt;/strong&gt;: Nearly half of respondents have been using hyper for 1-3 years. 12% for less than a year, 30% for 4-6 years. And 11% said they’ve been using hyper for forever. Me too, me too…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Industries&lt;/strong&gt;: 111 responses, which I grouped and sorted from most common to least. Software, cloud infrastructure, security. Finance, healthcare. Robotics, automotive, space, EV charging. Embedded. Media, streaming, events. Databases. Education. Government. Telecom, radio, chat. Geospatial. AI. Browsers. Games. Rust compiler.&lt;/p&gt;

&lt;p&gt;It’s just so humbling to think this code is helping in so many different places.&lt;/p&gt;

&lt;h3 id=&quot;future-work&quot;&gt;Future work&lt;/h3&gt;

&lt;p&gt;Another set of questions were related to work we &lt;em&gt;could&lt;/em&gt; do in the future. This helps inform prioritization, and things we may not have thought of.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feature requests&lt;/strong&gt;: One of the questions came preloaded with common feature requests, and asked the respondents to rank them. Here’s the accumulated ranking:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Metrics/Tracing/Events API&lt;/li&gt;
  &lt;li&gt;HTTP/2 Performance&lt;/li&gt;
  &lt;li&gt;Better Middleware&lt;/li&gt;
  &lt;li&gt;Add HTTP/3 Support&lt;/li&gt;
  &lt;li&gt;Documentation and guides&lt;/li&gt;
  &lt;li&gt;io-uring support&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Write-in features&lt;/strong&gt;: the follow-up question was a blank text box to write in any feature requests not in the above list. I grouped the common answers and sorted: legacy-client successor, original header casing/ordering, buffer control, improved errors.&lt;/p&gt;

&lt;p&gt;One write-in suggestion wasn’t really about a new feature, but keeps popping back up in my mind: how to get releases that are more stable.&lt;sup id=&quot;fnref:stable-releases&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:stable-releases&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The hard parts&lt;/strong&gt;: We also asked what was hard about hyper. Grouped and sorted answers: integrating TLS, upgrading to v1, middleware complexity, advanced body streaming, combining all pieces for production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Topic ideas&lt;/strong&gt;: we asked for suggestions for topics for future blog posts and talks. This certainly doesn’t need to be only from me, so if you see something interesting, fill the need! But after grouping the topics, they are: hyper internals, best practices, testimonials and success stories, security, tower usage, retries.&lt;/p&gt;

&lt;h3 id=&quot;contributing&quot;&gt;Contributing&lt;/h3&gt;

&lt;p&gt;We also asked about some general contribution questions, to look at the contributor health of the project.&lt;/p&gt;

&lt;p&gt;The standout here was: &lt;strong&gt;what would help you to contribute more?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The top response, a little over half of all respondents, said an improved contributing guide. Just a few percent under that want an updated roadmap. 20% said more responsive triage and reviews. And 15% said they could use increased mentoring.&lt;/p&gt;

&lt;h2 id=&quot;the-insights&quot;&gt;The insights&lt;/h2&gt;

&lt;p&gt;Looking it all over, this was awesome. I definitely to take some specific things with me. Well, sure, there’s goodies all throughout the above results. But, at a high level, here’s some thoughts, especially after combining it with other conversations I’ve had.[^not-everthing]&lt;/p&gt;

&lt;p&gt;Of the technical things, I suspect I’ll be spelunking in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; first, eking out performance refactors. It can use some love. Metrics is requested all the time, and it looks like I can collaborate on a design and review, but I believe there’s a couple other contributors interested in the implementation. I do keep thinking about ways to configure a buffer pool or something. I think the extended testing idea has some potential.&lt;sup id=&quot;fnref:stable-releases:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:stable-releases&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; And I’d &lt;em&gt;love&lt;/em&gt; to see HTTP/3 finally land in hyper proper this year, at least as an unstable feature. I want the other things too, but… time, y’know? Though, as mentioned in the next paragraph, it’d be a win to onboard &lt;em&gt;others&lt;/em&gt; to work on and &lt;em&gt;own&lt;/em&gt; those things.&lt;/p&gt;

&lt;p&gt;Improving contribution health, sustainable personnel of hyper, is high on my list this year. I’ve started working on a collaborator guide. I’m considering some new collaborators that have already been doing good work. I want to try GitHub’s rotating auto-assign reviewers, to improve review times and spread review load. And I welcome help linking up our existing &lt;a href=&quot;https://hyper.rs/contrib/roadmap/&quot;&gt;ROADMAP&lt;/a&gt; into some more concrete and mentored issues.&lt;/p&gt;

&lt;h2 id=&quot;outro&quot;&gt;Outro&lt;/h2&gt;

&lt;p&gt;There it is. The hyper user survey 2025 results. Thank you to everyone who responded!&lt;/p&gt;

&lt;p&gt;Does any of this interest you? Want to run with one of the ideas? &lt;a href=&quot;https://hyper.rs/contrib/contributing/&quot;&gt;Join us&lt;/a&gt;!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:burnout&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This took a bit longer to write up than I meant. I have to admit, I felt some strong burnout at the beginning of the year. Sometimes being a maintainer is lonely. New year contract negotiations don’t help. But I’m feeling better now. &lt;a href=&quot;#fnref:burnout&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:byor&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Did you know you can &lt;a href=&quot;https://hyper.rs/guides/1/init/runtime/&quot;&gt;bring your own runtime&lt;/a&gt;? Also, this is one reason I don’t believe the FUD about a single runtime. Also also, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper::rt&lt;/code&gt; works fine, I don’t see any need for the types to be in libstd. That wouldn’t unblock anything. &lt;a href=&quot;#fnref:byor&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:stable-releases&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I can write this up more later, but initially, I’ve learned the slow way about feature windows. On top of those, I’d love to talk to customers who would be interested in having their test suites try hyper &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; before a release. &lt;a href=&quot;https://seanmonstar.com/retainer&quot;&gt;Talk to me&lt;/a&gt;. &lt;a href=&quot;#fnref:stable-releases&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:stable-releases:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 26 May 2026 09:02:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-user-survey-2025-results/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-user-survey-2025-results/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>survey</category>
        
        <category>open-source</category>
        
        
      </item>
    
      <item>
        <title>2025 in review</title>
        <description>&lt;p&gt;Come along with me as I review the past year. Heh, I often start these kinds of posts right at the start of the year, but it takes a few weeks longer than I ever expect to think them through.&lt;sup id=&quot;fnref:past&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:past&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h2 id=&quot;two-years-of-being-independent&quot;&gt;Two years of being independent&lt;/h2&gt;

&lt;p&gt;After a second year of operating as an &lt;a href=&quot;https://seanmonstar.com/blog/independent-open-source-maintainer/&quot;&gt;independent open source maintainer&lt;/a&gt;, it’s starting to feel more normal.&lt;/p&gt;

&lt;p&gt;In terms of personal execution, it felt pretty fantastic, actually. Thanks to high-touch conversations from my &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;retainers&lt;/a&gt;, I knew what was needed; there was an underlying trend. And I was able to spec out a grant that made a project out of that trend. All while managing to do the necessary maintenance work that the ecosystem requires. Granted, it did occasionally feel like a conflict of priorities, but that’s life.&lt;/p&gt;

&lt;p&gt;Honestly, though, I wasn’t so sure when trying to plan this all out initially.&lt;/p&gt;

&lt;h2 id=&quot;maintaining-hyper&quot;&gt;Maintaining hyper&lt;/h2&gt;

&lt;p&gt;Perhaps the biggest deal for &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; this year was launching our first user survey. I’ve thought of doing it a few times over the years, but finally remembered in Q4 to launch it. Thanks to all who answered! I’ve looked through the results, and I think this will be extremely useful. Some stats real quick: 96% of respondents have upgraded to hyper v1.x, most commonly combine it with Tokio (99%) and rustls (92%).&lt;sup id=&quot;fnref:survey&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:survey&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; A proper analysis coming soon!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://hyper.rs/blog/2025/04/21/welcome-katelyn-martin/&quot;&gt;katelyn martin&lt;/a&gt; joined us as a collaborator, and has continued to be a multiplier with kind reviews and maintenance glue. And general maintenance doesn’t stop, including growing security reports (more below).&lt;sup id=&quot;fnref:maintenance&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:maintenance&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Besides all that, I took on a larger project for the year. You see, after updating the roadmap at the end of the previous year, I started to focus on one of the four defined areas: improved &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper-util&lt;/code&gt;. This lined up with what many have been asking for.&lt;/p&gt;

&lt;p&gt;I did that by modularizing parts out of reqwest.&lt;/p&gt;

&lt;h2 id=&quot;modularizing-reqwest&quot;&gt;Modularizing reqwest&lt;/h2&gt;

&lt;p&gt;Most of my year was spent on &lt;a href=&quot;https://seanmonstar.com/blog/modular-reqwest/&quot;&gt;modularizing reqwest&lt;/a&gt;. Or, from another angle, giving back the building blocks that reqwest has accumulated over the years. A lot of functionality that people rely on in reqwest started life as internal glue, and this was the year I finally pulled many of those pieces out into places where the rest of the ecosystem could use them too. Between reqwest and hyper‑util, that work ended up producing quite a few releases: 14 for reqwest itself, and 8 for hyper‑util.&lt;/p&gt;

&lt;p&gt;Ages ago, I added a bunch of features that you expect any client to have directly into reqwest. Later, as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt; grew, it copied some of those same features. Meanwhile, reqwest was used in weirder and weirder places, so we hardened those features, and tossed in some tests to check for the weird. But &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt; never saw any of that.&lt;/p&gt;

&lt;p&gt;This year, we completely tossed the redirect and decompression code from reqwest, depended on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt; pieces, and then allowed the test suite to find the difference. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt; layers got those fixes backported, and now everyone benefits.&lt;/p&gt;

&lt;p&gt;We also created &lt;em&gt;new&lt;/em&gt; things, but still modular.&lt;/p&gt;

&lt;p&gt;Easier &lt;a href=&quot;https://seanmonstar.com/blog/reqwest-retries/&quot;&gt;retries&lt;/a&gt; were added to reqwest, making use of the lower-level pieces in tower. I’m still interested in ways to improve the feature, so more people can use retries more safely.&lt;/p&gt;

&lt;p&gt;reqwest has grown extensive support for connection proxies. But an increasingly common pattern was people using reqwest &lt;em&gt;only&lt;/em&gt; for the proxy support; they didn’t need any other feature. So I extracted proxy &lt;a href=&quot;https://docs.rs/hyper-util/latest/hyper_util/client/proxy/matcher/index.html&quot;&gt;matchers&lt;/a&gt; and proxy &lt;a href=&quot;https://docs.rs/hyper-util/latest/hyper_util/client/legacy/connect/proxy/index.html&quot;&gt;connectors&lt;/a&gt; (tunnel, socks) into hyper-util.&lt;/p&gt;

&lt;p&gt;The largest piece was designing and implementing composable &lt;a href=&quot;https://seanmonstar.com/blog/hyper-util-composable-pools/&quot;&gt;pools&lt;/a&gt; for hyper-util. In many ways, this was my &lt;strong&gt;highlight of the year&lt;/strong&gt;. It’s a problem I’ve been thinking about since … 2018? I’d done a lot of research throughout the years, and never found anything quite like it. Now, it’s not quite “done”, but it’s a base that allows a lot of new layers and compositions to be explored.&lt;/p&gt;

&lt;p&gt;To end the year, we released v0.13 with &lt;a href=&quot;https://seanmonstar.com/blog/reqwest-v013-rustls-default/&quot;&gt;rustls as default&lt;/a&gt;. It’s a big improvement for &lt;em&gt;most&lt;/em&gt; people. But. I am not currently happy with how difficult it is to build the defaults on some other targets (Windows, Cranelift, cross-compiling). I want that fixed. Maybe that’s improvements to upstream aws-lc-rs; it looks like it’s already been improved to not need cmake. Or maybe we use a different default crypto provider on some targets.&lt;/p&gt;

&lt;h2 id=&quot;the-value-of-deadlines&quot;&gt;The value of deadlines&lt;/h2&gt;

&lt;p&gt;The work on composable pools was hard. The reason it had taken me years to finally try was that I wasn’t sure about some of the design. After staring hard at it during the summer, I did solve some of the questions. But there was &lt;a href=&quot;https://seanmonstar.com/blog/hyper-util-composable-pools/#real-world-usage-in-reqwest&quot;&gt;one problem&lt;/a&gt; towards the end that consumed another month or so of staring. And this time, I couldn’t stop staring.&lt;/p&gt;

&lt;p&gt;With a hard deadline set, however, there was no possibility of waiting longer. Instead, I had to settle with shipping what I had, and accepting that it can always be better.&lt;/p&gt;

&lt;p&gt;And that’s also the beauty of deadlines: they keep you user-driven. As long as I’m staring hard at a problem, holding back shipping, users have &lt;em&gt;nothing&lt;/em&gt;. But software doesn’t need to be shipped all at once. It’s a lesson I’ve learned before, and yet it pops up to, uh, &lt;em&gt;delight&lt;/em&gt; me over and over.&lt;/p&gt;

&lt;p&gt;I feel like I go through waves: I hate setting a deadline, and many times feel disappointed at not shipping all the glory that was in my head. But I always appreciate that at least they got &lt;em&gt;something&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;security-takes-time&quot;&gt;Security takes time&lt;/h2&gt;

&lt;p&gt;We take security seriously, and the amount of reports we receive is slowly increasing. This past year, we had a 8 in total, including our first AI slop report (yay!).&lt;/p&gt;

&lt;p&gt;The biggest one resulted in a large coordinated disclosure event. But &lt;a href=&quot;https://seanmonstar.com/blog/hyper-http2-didnt-madeyoureset/&quot;&gt;hyper was just fine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That didn’t stop it from being stressful trying to handle reports while simultaneously sticking to feature deadlines.&lt;/p&gt;

&lt;p&gt;It is a reminder, though, that this is often urgent and important work that must be handled, but that traditional pay-for-features doesn’t support. Sponsorships and retainers make this sort of maintenance much more sustainable.&lt;/p&gt;

&lt;h2 id=&quot;talks&quot;&gt;Talks&lt;/h2&gt;

&lt;p&gt;On the 10th anniversary of Rust 1.0, I gave a talk for the &lt;a href=&quot;https://www.youtube.com/watch?v=1PpdNu0Weas&quot;&gt;Rust for Lunch&lt;/a&gt; meetup. It was sort of ‘lessons using Rust for 10 years’, but also ‘why you should consider Rust’.&lt;/p&gt;

&lt;p&gt;And I did a podcast episode on &lt;a href=&quot;https://seanmonstar.com/blog/podcast-netstackfm/&quot;&gt;Netstack.FM&lt;/a&gt;, discussing the history of Rust’s networking ecosystem.&lt;/p&gt;

&lt;h2 id=&quot;pondering&quot;&gt;Pondering&lt;/h2&gt;

&lt;p&gt;Last year, I liked just sharing some questions I’m thinking about. It wasn’t a promise to work on them actively, but I look at them from time to time to see if there’s something that I can tackle soon.&lt;/p&gt;

&lt;p&gt;Here’s just a few things I’m thinking about at the start of 2026:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How do I balance keeping up with LLM advances while keeping my mind and skills sharp?&lt;/li&gt;
  &lt;li&gt;How far can one reasonably go with typestate builders, considering ergonomics and correctness?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wonder.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:past&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;See some previous yearly reviews: &lt;a href=&quot;https://seanmonstar.com/blog/2024-in-review&quot;&gt;2024&lt;/a&gt;, &lt;a href=&quot;https://seanmonstar.com/blog/2023-in-review&quot;&gt;2023&lt;/a&gt;, &lt;a href=&quot;https://seanmonstar.com/blog/hyper-ish-2022-in-review&quot;&gt;2022&lt;/a&gt;, &lt;a href=&quot;https://seanmonstar.com/blog/hyper-ish-2021-in-review&quot;&gt;2021&lt;/a&gt;. &lt;a href=&quot;#fnref:past&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:survey&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Though a significant amount also use other runtimes and TLS libraries. As mentioned, more coming soon. &lt;a href=&quot;#fnref:survey&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:maintenance&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;There were three feature releases of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper&lt;/code&gt; and two of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;, bringing support for things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_informational&lt;/code&gt; and constants for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EARLY_HINTS&lt;/code&gt;. There was also five bug fix releases of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt;, hardening the HTTP/2 story for Rust. &lt;a href=&quot;#fnref:maintenance&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 27 Jan 2026 11:32:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/2025-in-review/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/2025-in-review/</guid>
        
        <category>yearly</category>
        
        <category>rust</category>
        
        <category>open-source</category>
        
        <category>hyper</category>
        
        <category>hyper-util</category>
        
        <category>reqwest</category>
        
        
      </item>
    
      <item>
        <title>reqwest v0.13 - rustls by default</title>
        <description>&lt;p&gt;To end out the year, here comes a new major release of &lt;a href=&quot;https://crates.io/crates/reqwest&quot;&gt;reqwest&lt;/a&gt;, the opinionated higher-level HTTP client for Rust.&lt;/p&gt;

&lt;p&gt;We don’t really need major breaking versions to keep providing value. Improvements keep coming all the time. But we did need one to make one particular big adjustment, and we’ve taken the opportunity to clean up other things too. At the same time, we strove make it disrupt as little as possible, especially if you stick to the defaults.&lt;/p&gt;

&lt;p&gt;reqwest &lt;a href=&quot;https://github.com/seanmonstar/reqwest/releases/tag/v0.13.0&quot;&gt;v0.13.0&lt;/a&gt; is out now! Read on for why.&lt;/p&gt;

&lt;h2 id=&quot;rustls-is-now-the-default-tls-backend&quot;&gt;rustls is now the default TLS backend&lt;/h2&gt;

&lt;p&gt;The biggest deal is that reqwest now sets its default TLS feature to use &lt;a href=&quot;https://rustls.dev/&quot;&gt;rustls&lt;/a&gt;, instead of native-tls.&lt;/p&gt;

&lt;p&gt;Granted, native-tls has its place. It provides a unified library that uses the “native” TLS implementation on each target. SecureTransport on macOS, schannel on Windows, and OpenSSL on Linux (as the most likely already installed). It was the right choice several years, while rustls was young. But rustls is now &lt;a href=&quot;https://docs.rs/rustls/latest/rustls/manual/_01_impl_vulnerabilities/index.html&quot;&gt;safer&lt;/a&gt; and &lt;a href=&quot;https://rustls.dev/perf/&quot;&gt;faster&lt;/a&gt; than most choices.&lt;sup id=&quot;fnref:windows-i686-gnu&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:windows-i686-gnu&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; Seems like an obvious &lt;a href=&quot;https://github.com/seanmonstar/reqwest/issues/2025#issuecomment-2913873836&quot;&gt;improvement&lt;/a&gt;. But would people want the better choice?&lt;/p&gt;

&lt;p&gt;A recent hyper user survey found that 93% of respondants already use rustls. 30% said they also use native-tls at times, so we will continue to provide that option. And while a survey is already biased, it’s also most certainly true that the vast majority of users just allow the default options, and it works for them. That will continue to be true for most everyone.&lt;/p&gt;

&lt;p&gt;So, if you use the default options, things just got better for you.&lt;/p&gt;

&lt;h2 id=&quot;certificate-verification-features-are-consolidated&quot;&gt;Certificate verification features are consolidated&lt;/h2&gt;

&lt;p&gt;Previously, reqwest had many crate features to enable various ways to load sources of root certificates. Too many. It’s a bit of a mess.&lt;/p&gt;

&lt;p&gt;We consolidate the options into just a few simple choices:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Defaults to using the native platform verifier.&lt;/li&gt;
  &lt;li&gt;If the target supports it, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls_certs_merge()&lt;/code&gt; can add additional certificates. If it doesn’t, a builder error is returned.&lt;/li&gt;
  &lt;li&gt;If you really need a specific certificate, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls_certs_only()&lt;/code&gt;, which will always work, and doesn’t include native verification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These basic options should allow for any use case, while reducing complexity within reqwest. For instance, if an application really needs to use the webpki-roots, they can be configured with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls_certs_only(your_roots)&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;soft-deprecation-to-improve-option-naming&quot;&gt;Soft-deprecation to improve option naming&lt;/h2&gt;

&lt;p&gt;While in there, most &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientBuilder&lt;/code&gt; methods were given better names. The previous methods have been soft-deprecated. That means that you can keep using the old names, without warnings, but they are documented as deprecated, and they will eventually be removed in a later breaking change.&lt;/p&gt;

&lt;p&gt;But in most cases, the improved name is mostly to help with understanding. It doesn’t help to trigger a bunch of additional warnings when you upgrade. Perhaps we’ll add a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deprecations&lt;/code&gt; crate feature for those who want to clean up.&lt;/p&gt;

&lt;p&gt;The upside is that all the methods now start with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls_&lt;/code&gt;. They are grouped together in the docs, but it will also help exploration with autocomplete.&lt;/p&gt;

&lt;h2 id=&quot;other-crate-feature-adjustments&quot;&gt;Other crate feature adjustments&lt;/h2&gt;

&lt;p&gt;As this is a breaking change version, we did include one making the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RequestBuilder::query()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;form()&lt;/code&gt; methods optional features, disabled by default. With these as optional, it is now possible to build reqwest without serde.&lt;/p&gt;

&lt;p&gt;We also made &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;native-tls&lt;/code&gt; imply ALPN automatically. This will mean most people who don’t think about it will now get HTTP/2 upgrades. The reason it was opt-in previously is because older native libraries might not have the symbols required. They are quite old at this point. If you still need the previous behavior, there is now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;native-tls-no-alpn&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;thanks&quot;&gt;Thanks!&lt;/h2&gt;

&lt;p&gt;Thanks to all who contribute, use, &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsor&lt;/a&gt;, fix, complain, and help reqwest be what it is! Here’s &lt;a href=&quot;https://github.com/seanmonstar/reqwest/releases/tag/v0.13.0&quot;&gt;v0.13.0&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:windows-i686-gnu&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This does drop &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i686-pc-windows-gnu&lt;/code&gt; support for the default features. The reality is that a &lt;em&gt;lot&lt;/em&gt; of things don’t work for that target. Even Rust itself has it as a Tier 2 target. We do still support it with native-tls, though. &lt;a href=&quot;#fnref:windows-i686-gnu&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 30 Dec 2025 10:48:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/reqwest-v013-rustls-default/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/reqwest-v013-rustls-default/</guid>
        
        <category>rust</category>
        
        <category>reqwest</category>
        
        <category>open-source</category>
        
        <category>programming</category>
        
        
      </item>
    
      <item>
        <title>hyper-util Composable Pools</title>
        <description>&lt;p&gt;I’m so excited to announce &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;’s new composable pool layers!&lt;sup id=&quot;fnref:excited&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:excited&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;As part of &lt;a href=&quot;https://seanmonstar.com/blog/modular-reqwest/&quot;&gt;making reqwest more modular&lt;/a&gt;, we’ve designed a new connection pool, and made the pieces available in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper_util::client::pool&lt;/code&gt;. But this is more than just a “hey, we have a Pool, it moved over there.” We’ve literally pulled apart the pool, in a way I haven’t found elsewhere.&lt;/p&gt;

&lt;p&gt;Building a purpose‑specific pool is now straightforward. Add the features you want, even custom ones, and skip the bloat, no forks required.&lt;/p&gt;

&lt;p&gt;Read on to see what exactly we solved, how, and what comes next. If you just want to use them, &lt;a href=&quot;https://docs.rs/hyper-util/0.1.x/hyper_util/client/pool/&quot;&gt;here’s the docs&lt;/a&gt;. Everyone else, let’s dive in.&lt;/p&gt;

&lt;h2 id=&quot;we-started-with-the-users&quot;&gt;We started with the users&lt;/h2&gt;

&lt;p&gt;We started with the users, looking back over past issues filed, common questions in chat, and private conversations explaining what they needed to do. Boiled down, that got us to these requirements:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A full-featured pool, like the one in &lt;a href=&quot;https://docs.rs/hyper-util/0.1.x/hyper_util/client/legacy/struct.Client.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;legacy&lt;/code&gt;&lt;/a&gt;, must be possible.&lt;/li&gt;
  &lt;li&gt;Microservices shouldn’t have to handle multiple protocols or hostnames.&lt;/li&gt;
  &lt;li&gt;Some clients need custom keys for the pool.&lt;/li&gt;
  &lt;li&gt;Others need to limit new connections made at a time.&lt;/li&gt;
  &lt;li&gt;Or cap the total number of connections.&lt;/li&gt;
  &lt;li&gt;Customize connection expiration based on idle time, max lifetime, or even &lt;a href=&quot;https://docs.rs/hyper-util/0.1.x/hyper_util/client/legacy/connect/struct.Connected.html#method.poison&quot;&gt;poisoning&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;And importantly, allow custom logic not already thought of.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From past experience combining middleware, I had a strong feeling the pool requirements could be broken up into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower&lt;/code&gt; layers. But what would that even &lt;em&gt;look&lt;/em&gt; like? Would it be horrible to use?&lt;/p&gt;

&lt;p&gt;To answer that, we took the requirements and considered the developer experience of using layers. It had to feel nice. Not just to write, but also to come back to and read.&lt;/p&gt;

&lt;p&gt;I then sketched out several of these layers to make sure they could actually work. Once most of it was working, the &lt;a href=&quot;https://github.com/hyperium/hyper/issues/3948&quot;&gt;proposal&lt;/a&gt; was ready.&lt;/p&gt;

&lt;h2 id=&quot;the-initial-4-working-pools&quot;&gt;The initial 4 working pools&lt;/h2&gt;

&lt;p&gt;No plan survives contact with the enemy. We originally proposed five pool types, but launch with just the following four: singleton, cache, negotiate, map.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;singleton&lt;/code&gt; pool wraps a connector&lt;sup id=&quot;fnref:mksvc&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:mksvc&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; that should only produce a single active connection. It bundles all concurrent calls so only one connection is made. All calls to the singleton will return a clone of the inner service once established. This fits the HTTP/2 case well.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cache&lt;/code&gt; pool maintains a list of cached services produced by a connector. Calling the cache returns either an existing service, or makes a new one. When dropped, the cached service is returned to the cache if possible. Importantly for performance, the cache supports connection racing, just like the legacy pool.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;negotiate&lt;/code&gt; pool allows for a service that can decide between two service types based on an intermediate return value. Unlike typical routing, it makes decisions based on the response (the connection) rather than the request. The main use case is supporting ALPN upgrades to HTTP/2, with a fallback to HTTP/1. And its design allows combining two different pooling strategies.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; pool isn’t a typical service like the other pools, but rather is a stand-alone type that maps requests to keys and connectors. As a kind of router, it cannot determine which inner service to check for backpressure until the request is made. The map implementation allows customization of extracting a key, and how to construct a connector for that key.&lt;/p&gt;

&lt;h2 id=&quot;ineffably-unstable&quot;&gt;Ineffably unstable&lt;/h2&gt;

&lt;p&gt;I knew this work would land in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper-util&lt;/code&gt; first, because it’s not stable yet. Being so freshly designed, changes are expected after some more real-world usage. Still, I wanted to shield earlier adopters from breaking changes. At the same time, valuing performance and flexibility, I wanted to push as much as reasonably possible into the type system.&lt;/p&gt;

&lt;p&gt;When initially tinkering during the summer, I had one of &lt;em&gt;those&lt;/em&gt; thoughts. The kind that clangs like a giant lock snapping open: what about type-state builders and unnameable types? I took a side quest, and tackled the &lt;a href=&quot;https://seanmonstar.com/blog/warp-v04/&quot;&gt;warp v0.4 upgrade&lt;/a&gt;, to test out this API design. That post explains it a bit more.&lt;/p&gt;

&lt;p&gt;The various threads were all coming together.&lt;/p&gt;

&lt;p&gt;With each pool concept a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower&lt;/code&gt; service, once composed, a user shouldn’t care what it is beyond being some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Service&lt;/code&gt;. I tested this out in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest&lt;/code&gt;, and yea, I don’t need to name the types. While I did need &lt;em&gt;a&lt;/em&gt; type, I was able to store a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dyn Service&lt;/code&gt;, and inference handled the rest.&lt;/p&gt;

&lt;h2 id=&quot;real-world-usage-in-reqwest&quot;&gt;Real world usage: in reqwest&lt;/h2&gt;

&lt;p&gt;Once those main pieces seemed ready, I needed a real example to test drive them. Tool-makers that don’t use their tools make bad tools, after all.&lt;/p&gt;

&lt;p&gt;I started by replacing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;legacy&lt;/code&gt; pool inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest&lt;/code&gt;. Part of the larger diff in reqwest is handling all of reqwest’s different pool configuration options.&lt;/p&gt;

&lt;p&gt;But, putting the default case together is pretty self-explanatory:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Note: some noise has been trimmed&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;http1_request_target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;http1_set_host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;MyMetaIdleAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;http1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;singleton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;http2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool_layers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;layer_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;negotiate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;.fallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http1&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;.upgrade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http2&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;.inspect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_negotiated_h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;.connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;.build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Uri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;scheme_and_auth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_dst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;pool_layers&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connector&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And it works! Making the full-featured pool was one of the requirements: check. But, the next part was even more important.&lt;/p&gt;

&lt;p&gt;As I mentioned before, I punted one of the proposed types: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expire&lt;/code&gt;. Expiration is a necessary concept to a pool. But try as I might to fit the various generic shapes, it just wasn’t happening. Thankfully, this work had a hard deadline. And deadlines keep you user-driven: let them have &lt;em&gt;something&lt;/em&gt; now, it can always be better later.&lt;/p&gt;

&lt;p&gt;To prove the general design allowed expiration, I implemented a specific version of it directly in reqwest.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;tokio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;tokio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idle_dur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.await&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Instant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool_map&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.upgrade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.unwrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.retain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.fallback_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.retain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_closed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idle_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.idle_at&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idle_at&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idle_dur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.upgrade_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.retain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_closed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.fallback_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.upgrade_mut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The ease of adding it helped solidify to me that this was definitely the right design. I was able to slot in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meta&lt;/code&gt; layer tracking idle time, and then use that to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;retain&lt;/code&gt; services. I placed that layer in right next to some of the other HTTP/1-specific layers. Easy!&lt;/p&gt;

&lt;h2 id=&quot;being-modular-opens-up-customization&quot;&gt;Being modular opens up customization&lt;/h2&gt;

&lt;p&gt;With the ability to build a stack for your pool, consider an example of how we can start to solve other requirements listed earlier.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ServiceBuilder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// cached connections are unaware of the limit&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// in-flight handshakes are limited&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.concurrency_limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    
    &lt;span class=&quot;nf&quot;&gt;.layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;http1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It also allows adding in layers we don’t currently have, such as per-host connection semaphores, or a few layers up over all hosts. Adding new functionality isn’t blocked on us, and no one has to “pay” for features they don’t need.&lt;/p&gt;

&lt;p&gt;I can’t wait to see what else is done with the design!&lt;/p&gt;

&lt;h2 id=&quot;pools-ready&quot;&gt;Pools ready&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper_util::client::pool&lt;/code&gt; module is now available in &lt;a href=&quot;https://github.com/hyperium/hyper-util/releases/tag/v0.1.19&quot;&gt;v0.1.19&lt;/a&gt;. Go check the &lt;a href=&quot;https://docs.rs/hyper-util/0.1.x/hyper_util/client/pool/&quot;&gt;docs&lt;/a&gt;, and try to build cool things. Please file issues if parts are missing, we’ll keep iterating.&lt;/p&gt;

&lt;p&gt;I’ve been working on this feature set for long time. It’s something I started thinking about years ago, and after months of work this year, it feels awesome to finally be able to release it.&lt;/p&gt;

&lt;p&gt;Thanks to my &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsors&lt;/a&gt;, retainers, and grants for making this all possible!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:excited&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I mean, who isn’t excited to announce anything? /s &lt;a href=&quot;#fnref:excited&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:mksvc&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;All “connectors” are actually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MakeService&lt;/code&gt;s, which are jsut a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt; that produces a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt;. It doesn’t &lt;em&gt;have&lt;/em&gt; to create a connection, but it reads better when talking about pools. &lt;a href=&quot;#fnref:mksvc&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 03 Dec 2025 08:48:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-util-composable-pools/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-util-composable-pools/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>hyper-util</category>
        
        <category>tower</category>
        
        <category>open-source</category>
        
        <category>programming</category>
        
        <category>bestof</category>
        
        
      </item>
    
      <item>
        <title>hyper User Survey 2025</title>
        <description>&lt;p&gt;I’m excited to announce the inaugural hyper user survey! (&lt;em&gt;Update: it ended.&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;Part of being user-driven is &lt;a href=&quot;https://hyper.rs/contrib/governance/#making-decisions&quot;&gt;knowing what our users want&lt;/a&gt;, what they’re trying to do, and then we can figure out how best to help.&lt;/p&gt;

&lt;p&gt;This survey should only take about 5 minutes, no questions are required, and responses are anonymous. The survey will be open for a month, until December 17th, and then we’ll analyze the results and share with you all what we find.&lt;/p&gt;

&lt;p&gt;Thanks for taking the time to help make &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; better!&lt;/p&gt;

&lt;p&gt;&lt;del&gt;Take the hyper user survey for 2025.&lt;/del&gt;&lt;/p&gt;

</description>
        <pubDate>Tue, 18 Nov 2025 10:20:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-user-survey-2025/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-user-survey-2025/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>survey</category>
        
        <category>open-source</category>
        
        
      </item>
    
      <item>
        <title>Podcast: Netstack.fm, story of Rust&apos;s networking with hyper</title>
        <description>&lt;p&gt;Last week I was a &lt;a href=&quot;https://netstack.fm/episodes/hyper-with-sean-mcarthur-ep-2-remastered&quot;&gt;guest on the Netstack podcast&lt;/a&gt;. We talked abit about how I got into Rust, how async Rust developed, and the story behind &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; and its surrounding ecoystem.&lt;/p&gt;

&lt;p&gt;We started (and ended) with my goal of better software:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;On your about page, you say that “Rust is the least bad option.” Can you elaborate a bit on that?&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;Yeah, I love Rust. I think Rust solves a ton of problems, but I also don’t want to be stuck when something better comes along, which it inevitably will. Then yeah, I’ll move to that.
To me, all these tools are the means to an end, which is to make better software.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The rest of the conversation was really fun to talk about:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;7:54&lt;/em&gt;: beginning of hyper, async Rust&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;13:20&lt;/em&gt;: hyper as something bigger&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;15:36&lt;/em&gt;: splitting off hyper-util&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;17:35&lt;/em&gt;: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;headers&lt;/code&gt; crates&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;22:51&lt;/em&gt;: motivation behind &lt;a href=&quot;/blog/warp-v04&quot;&gt;warp&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;29:00&lt;/em&gt;: &lt;a href=&quot;/blog/modular-reqwest&quot;&gt;reqwest&lt;/a&gt; as the opinionated layer&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;30:17&lt;/em&gt;: open source &lt;a href=&quot;/blog/independent-open-source-maintainer&quot;&gt;independence&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;31:31&lt;/em&gt;: HTTP/3 in hyper and reqwest&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;39:40&lt;/em&gt;: hyper in 5 years, contributors, ownership&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Tue, 02 Sep 2025 09:24:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/podcast-netstackfm/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/podcast-netstackfm/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>podcast</category>
        
        <category>open-source</category>
        
        
      </item>
    
      <item>
        <title>hyper HTTP/2 (Didn&apos;t) MadeYouReset</title>
        <description>&lt;p&gt;A new HTTP/2 attack vector was disclosed today called MadeYouReset. &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; is negligably affected, weathering the attack well. But, we have provided patches just in case. We published patches weeks ago, so if you’ve been keeping up-to-date, you’re fine! If not, you’re most likely fine, but you can upgrade now. No CVE or security advisory is included with this.&lt;/p&gt;

&lt;p&gt;This sort of work is supported &lt;strong&gt;exclusively&lt;/strong&gt; through &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;retainers&lt;/a&gt;, get in contact to support.&lt;/p&gt;

&lt;p&gt;Follow along for the background information, if you’re curious!&lt;/p&gt;

&lt;h2 id=&quot;what-is-the-attack&quot;&gt;What is the attack&lt;/h2&gt;

&lt;p&gt;The attack is quite similar to the previous &lt;a href=&quot;https://seanmonstar.com/blog/hyper-http2-rapid-reset-unaffected/&quot;&gt;Rapid Reset&lt;/a&gt; attack from a couple years ago. That is, it starts new requests up to the limit imposed by the server. And then instead of &lt;em&gt;sending&lt;/em&gt; explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RST_FRAMES&lt;/code&gt;, it sends malformed frames that force the &lt;em&gt;server&lt;/em&gt; to reset the stream.&lt;/p&gt;

&lt;p&gt;So far, the described behavior is normal HTTP/2 flow. The problem occurs in some implementations that don’t respond well to quick cancelation.&lt;/p&gt;

&lt;p&gt;As the attack describes, in some implementations it allows for more stream concurrency than might have been configured. See more in &lt;a href=&quot;https://www.kb.cert.org/vuls/id/767506&quot;&gt;VU#767506&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-hyper-does&quot;&gt;What hyper does&lt;/h2&gt;

&lt;p&gt;A couple years ago, we added a defense mechanism to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; that keeps count of how many times a frame from the remote causes a local reset, and once a configurable limit is reached, the connection is abruptly closed. This mechanism caught nearly all variants of the attack.&lt;/p&gt;

&lt;p&gt;We had forgotten one code path dealing with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WINDOW_UPDATE&lt;/code&gt; frames. But what happens when new streams are created and then a bad window frame is received?&lt;/p&gt;

&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt;, the reset is sent to user code. Check the request body will notice the error. Additionally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper&lt;/code&gt;’s server code using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; is essentially waiting simultaneously on the user’s service to reply, and for any reset to be received. Once the reset is received, the service future is canceled.&lt;sup id=&quot;fnref:react&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:react&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;So, not much. When a simple hello world server example was tested against the attack, the only thing that happened was increased CPU usage. Which makes sense, it’s receiving and canceling more streams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stream concurrency is enforced&lt;/strong&gt;, since all futures are canceled immediately, and a signal is sent to anything listening for longer.&lt;/p&gt;

&lt;p&gt;All of this before any additional patch.&lt;/p&gt;

&lt;h2 id=&quot;what-we-did&quot;&gt;What we did&lt;/h2&gt;

&lt;p&gt;We received a report&lt;sup id=&quot;fnref:ghsa&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ghsa&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; about the attack from security researchers&lt;sup id=&quot;fnref:researchers&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:researchers&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; on May 23, 2025. The attack includes many variants, so we set out trying to determine if hyper was vulnerable. We knew that hyper already added a defense mechanism for this exact sort of abuse. Only one of the variants did not get cut off, but saw increased CPU usage, so we dug in. It turns out the original feature forgot to check the limit when WINDOW_UPDATE frames were bad.&lt;/p&gt;

&lt;p&gt;We determined that while the variants was not caught, it also did not break any guarantees. The increase in CPU usage was obvious, since it was necessarily handling more requests in general. Also important to our determination: the attack is &lt;em&gt;observable&lt;/em&gt; by user code, so any user code can react however they wish.&lt;/p&gt;

&lt;p&gt;The researchers did a great job of explaining the concept behind the attack, providing a proof-of-concept script that we could test with, and conversed respectfully and thoughtfully as we went through the investigation.&lt;/p&gt;

&lt;p&gt;Because the code of the aforementioned mechanism was already public, and the damage quite benign, we decided to release a patch weeks before the general embargo. It was just a refactor, converting it from logic-based to utilizing the type system more, so no other cases are “forgotten”. That patch was released on June 30, 2025.&lt;/p&gt;

&lt;p&gt;For similar reasons, we also determined there was no need for a CVE or security advisory.&lt;/p&gt;

&lt;p&gt;The researchers came back a little afterwards showing that in some cases, servers using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; under this attack could be forced to crash. They even brough a new reproducible proof-of-concept. After analyzing it, we determined that the problem was not that of hyper/h2, but that of user code which might have unbounded queues and does not react to cancelation.&lt;/p&gt;

&lt;p&gt;We decided to stick with our original determination.&lt;/p&gt;

&lt;h2 id=&quot;what-you-can-do&quot;&gt;What you can do&lt;/h2&gt;

&lt;p&gt;After reading all that, what more can you do? Again, you’re likely fine! But here’s some good ideas, regardless:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you’ve been staying up-to-date, you’re already done!&lt;/li&gt;
  &lt;li&gt;If you have a server running hyper, it would be wise to make sure your server handlers really can cancel easily.&lt;/li&gt;
  &lt;li&gt;You can run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo update -p h2&lt;/code&gt; to upgrade to the latest versions (at least &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.4.11&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.3.27&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;If you’re running hyper v0.14 (so h2 v0.3.x), it’s time to upgrade to v1. After nearly 2 years, patches likely won’t be backported anymore.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s one more thing you can consider: set up a &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;retainer&lt;/a&gt; to make sure security reports get taken care of. This was a considerable amount of important work. This was several months of higher-stress but important work which doesn’t look like shipping a new feature.&lt;sup id=&quot;fnref:psirt&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:psirt&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Besides funding that important work, I’m also happy to provide pre-disclosure and hands-on guidance to those with a retainer.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:react&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This difference from Rapid Reset is also important. In Rapid Reset, the resets were not observable by user code, so they could not react to the wasting of resources. With MadeYouReset, however, users can if they need to. &lt;a href=&quot;#fnref:react&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ghsa&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I just realized today that I cannot publish the GHSA as an informational, since it does not include a severity or CVE. GitHub, please? &lt;a href=&quot;#fnref:ghsa&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:researchers&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The original reporters were &lt;a href=&quot;https://galbarnahum.com/made-you-reset&quot;&gt;Gal Bar Nahum&lt;/a&gt;, Anat Bremler-Barr, and Yaniv Harel of Tel Aviv University. I primarily interacted with Gal, which was a 5/5 experience, would repeat. &lt;a href=&quot;#fnref:researchers&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:psirt&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;On top of what has been outlined here, there’s a lot of coordination work involved, dealing with &lt;a href=&quot;https://www.kb.cert.org/vuls/id/767506&quot;&gt;VINCE&lt;/a&gt; and other vendors. &lt;a href=&quot;#fnref:psirt&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 13 Aug 2025 08:25:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-http2-didnt-madeyoureset/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-http2-didnt-madeyoureset/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>http2</category>
        
        <category>security</category>
        
        
      </item>
    
      <item>
        <title>warp v0.4</title>
        <description>&lt;p&gt;Yesterday, warp &lt;a href=&quot;https://github.com/seanmonstar/warp/releases/tag/v0.4.0&quot;&gt;v0.4&lt;/a&gt; was released. &lt;a href=&quot;https://crates.io/crates/warp&quot;&gt;warp&lt;/a&gt; is a Rust web server framework, with a focus on functional programming and type system routing.&lt;/p&gt;

&lt;p&gt;Upgrading is likely pretty simple, the main API stayed very similar. The biggest deal is that it should be easier for you to stay up-to-date on dependencies. You could stop there. But if you want to know what else happened, off we go!&lt;/p&gt;

&lt;h2 id=&quot;filters-remain-the-focus&quot;&gt;Filters remain the focus&lt;/h2&gt;

&lt;p&gt;The biggest &lt;em&gt;raison d’être&lt;/em&gt; of warp is its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Filter&lt;/code&gt; system. It was why I made a &lt;a href=&quot;https://seanmonstar.com/blog/warp/&quot;&gt;different web framework originally&lt;/a&gt;, and it remains &lt;em&gt;the reason&lt;/em&gt; to consider warp even now.&lt;/p&gt;

&lt;p&gt;Should &lt;em&gt;you&lt;/em&gt; use warp? That depends. If you just want a &lt;em&gt;standard&lt;/em&gt;, super fast, featureful Rust server framework, one that looks like ways you’ve coded servers before, you probably want &lt;a href=&quot;https://crates.io/crates/axum&quot;&gt;Axum&lt;/a&gt;. But, if you like functional programming, and (ab)using the type system, I think warp is pretty cool.&lt;/p&gt;

&lt;p&gt;Consider an example:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;warp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;path!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;todos&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;warp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;accept&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;warp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
       &lt;span class=&quot;c1&quot;&gt;// ... &lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Every filter extracts something from the request (even if that’s just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;). They can all be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.and()&lt;/code&gt;ed together in any order, it will result in natural, typed arguments you can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can build up layers of filters by just putting another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.and()&lt;/code&gt; on anything. You can make a group of filters with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.or()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you have combined all into a master filter, you can convert them into a &lt;a href=&quot;https://crates.io/crates/tower&quot;&gt;tower&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt;, which you can then add any other middleware from other libraries, and serve with an HTTP implementation, such as &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;upgraded-to-hyper-v1&quot;&gt;Upgraded to hyper v1&lt;/h2&gt;

&lt;p&gt;The underlying HTTP dependencies, those which are public, have been upgraded to &lt;a href=&quot;https://seanmonstar.com/blog/hyper-v1&quot;&gt;hyper v1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This should improve interoperability if used with other libraries such as &lt;a href=&quot;https://crates.io/crates/reqwest&quot;&gt;reqwest&lt;/a&gt; or &lt;a href=&quot;https://crates.io/crates/tower-http&quot;&gt;tower-http&lt;/a&gt;. Their latest versions depend on v1 of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;. So adding in more middleware, or using a higher-level HTTP client should mean less dependencies compiled, and no conversion required between types.&lt;/p&gt;

&lt;p&gt;It also means warp users will be able to stay on maintained versions of hyper and its dependencies.&lt;sup id=&quot;fnref:v014&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:v014&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h2 id=&quot;crate-features-on-a-diet&quot;&gt;Crate features on a diet&lt;/h2&gt;

&lt;p&gt;In previous versions, a few heavy features were enabled by default. Now, the default features are much slimmer.&lt;/p&gt;

&lt;p&gt;Keeping with filters being the focus, the default features only include the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Filter&lt;/code&gt; system, and a way to convert them into an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Service&lt;/code&gt;. You can take that service and use it with your own build of hyper, with HTTP/1 or 2 or whatever enabled, and warp won’t care.&lt;/p&gt;

&lt;p&gt;If you want the simple server runner, just enable the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt; feature, and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;warp::serve(filters)&lt;/code&gt; is back, along with all the hyper implementation to run it.&lt;/p&gt;

&lt;p&gt;Likewise, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;warp::test&lt;/code&gt; helpers have been put behind a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; feature. You can enable it in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev-dependencies&lt;/code&gt; for testing, and while keeping that code out when building for release.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls&lt;/code&gt; feature was dropped completely. It existed previously as a simple way to add TLS to your server, but it’s not strictly required in a server framework, and it adds a bit of maintenance churn to stay up-to-date and safe. Anyone wanting TLS with their warp server can make an accept loop using the TLS implementation of their choice, and use warp’s filters as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;multipart&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;websocket&lt;/code&gt; features were removed from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt;, but are still available to enable. This was a planned change once they became features in the first place, since they enable a lot of code that you might not need.&lt;/p&gt;

&lt;h2 id=&quot;iterating-on-the-server-builder&quot;&gt;Iterating on the Server builder&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Server&lt;/code&gt; API was, uh, iterated on.&lt;/p&gt;

&lt;p&gt;Before, it had a whole bunch of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bind_*&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run_*&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;serve_*&lt;/code&gt; methods that slowly grew as people wanted more options to configure the server. Now, most all of them are gone.&lt;/p&gt;

&lt;p&gt;Part of the reason is because it’s not the focus of warp. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Filter&lt;/code&gt; system is. I figured the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Server&lt;/code&gt; is meant to be a simple way to get your filters serving requests. If you wanted more customization, make your own.&lt;/p&gt;

&lt;p&gt;But there’s another reason, too.&lt;/p&gt;

&lt;p&gt;I’ve been noticing &lt;a href=&quot;https://github.com/seanmonstar/reqwest/pull/2763&quot;&gt;more&lt;/a&gt; and &lt;a href=&quot;https://github.com/hyperium/hyper/issues/3849&quot;&gt;more places&lt;/a&gt; where I wish the API of some crate was at the same time simpler, and also more powerful, putting options into the type system. The warp &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Server&lt;/code&gt; was an excellent place to iterate on this.&lt;/p&gt;

&lt;p&gt;It is now an unnameable builder making use of expandable type state.&lt;/p&gt;

&lt;p&gt;It encodes as generics into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Server&amp;lt;F, A, R, Etc...&amp;gt;&lt;/code&gt; various parts of how the server works. The filter, the acceptor, the runner loop. Depending on what methods you call, new ones get unlocked. For instance, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bind()&lt;/code&gt; will make the acceptor a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TcpListener&lt;/code&gt;, but once one is set, it doesn’t make sense to be able to call it again.&lt;/p&gt;

&lt;p&gt;The type is rendered in the docs, but otherwise not publicly exported, so you can’t &lt;em&gt;name&lt;/em&gt; it. There’s a benefit to this, as the API designer and maintainer. I can add more options, needing more generics, without it being a breaking change. As long as add a default that keeps it all compiling, there are now instances of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Server&amp;lt;F, A, R&amp;gt;&lt;/code&gt; that need to be updated to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Server&amp;lt;F, A, R, E&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And the reality is that the name of the type is not generally interesting to you as a user. You just need a fluid way to add options, and once it’s all combined away, you just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; a future.&lt;/p&gt;

&lt;p&gt;I’m hopeful this pattern carries over well to other builders as well.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:v014&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’ve backported important bug fixes to hyper v0.14 (and dependencies like h2), but I think that’s about done. It’s been almost 2 years, time to focus on v1. (If you need help, reach out to me!) &lt;a href=&quot;#fnref:v014&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 06 Aug 2025 11:05:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/warp-v04/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/warp-v04/</guid>
        
        <category>rust</category>
        
        <category>http</category>
        
        <category>warp</category>
        
        <category>open-source</category>
        
        <category>programming</category>
        
        
      </item>
    
      <item>
        <title>reqwest retries</title>
        <description>&lt;p&gt;One part of working on a more &lt;a href=&quot;https://seanmonstar.com/blog/modular-reqwest/&quot;&gt;modular &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest&lt;/code&gt;&lt;/a&gt; was adding support for retries.&lt;/p&gt;

&lt;p&gt;Intermittent failures are a fact of life, and a simple retry could have made things so much better. It’s a somewhat frequent feature request for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest&lt;/code&gt;. It’s also a very common pattern to implement manually, and far too easy to do incorrectly. Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest&lt;/code&gt;’s internals are shifting more and more to a stack of services, it felt like an ideal time to explore this.&lt;/p&gt;

&lt;p&gt;While skeleton pieces do exist in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower::retry&lt;/code&gt;, they require Expert Mode. Doing things right is tricky. We can do better.&lt;/p&gt;

&lt;h2 id=&quot;policy-composition&quot;&gt;Policy composition&lt;/h2&gt;

&lt;p&gt;A retry policy is several things at once. But each of those things often is only one of a few choices. So what if we made it easier to compose your choices? That is, we can provide the common choices, and a builder to combine them.&lt;/p&gt;

&lt;h3 id=&quot;budgets-by-default&quot;&gt;Budgets by default&lt;/h3&gt;

&lt;p&gt;Retry counts alone are insufficient, but absurdly common. Please don’t do this. We can educate and document and warn and wave our hands, but we can only plead so much.&lt;/p&gt;

&lt;p&gt;Budgets will be default on. Sure, there’s an escape hatch if you absolutely must. But this way we can help you fall into the pit of success.&lt;/p&gt;

&lt;p&gt;And to help users better understand what the budget results in, configuration looks like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.max_extra_load(0.3)&lt;/code&gt;, instead of implementation parameters of the windowed bucket.&lt;/p&gt;

&lt;h3 id=&quot;scoped-retries&quot;&gt;Scoped retries&lt;/h3&gt;

&lt;p&gt;Budgets are basically a must. But budgets also don’t make sense across different targets. Just because requests to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frobnica.te&lt;/code&gt; start failing doesn’t mean retries should also be disabled to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;storali.ze&lt;/code&gt;. This dichotomy perturbed me quite a bit, actually, and so I put off trying to solve the whole thing for a few months. But after letting my mind rest, looking at the exact same problem revealed an obvious solution: scopes.&lt;sup id=&quot;fnref:scopes&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:scopes&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;I believe the most likely use of scopes is based on hostname. So that’s the easiest constructor to start a builder: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;retry::for_host(host)&lt;/code&gt;. But it’s actually a sealed trait, to allow continued exploration. Maybe a closure is needed by some people? We’ll find out!&lt;/p&gt;

&lt;h3 id=&quot;cloning-requests&quot;&gt;Cloning requests&lt;/h3&gt;

&lt;p&gt;In many languages, this isn’t even a consideration. You can just share a pointer, and &lt;em&gt;wave hands&lt;/em&gt; mostly reuse it.&lt;/p&gt;

&lt;p&gt;In Rust, with ownership, we need to keep a clone of the request for a potential retry.&lt;/p&gt;

&lt;p&gt;At the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper&lt;/code&gt; level, we don’t know enough about the request body to automatically clone it. At &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest&lt;/code&gt;’s level, we &lt;em&gt;do&lt;/em&gt; know enough: we can absolutely clone when it’s a simple non-streaming body. (Even possibly more, discussed below.)&lt;/p&gt;

&lt;h3 id=&quot;classifiers&quot;&gt;Classifiers&lt;/h3&gt;

&lt;p&gt;You might have a very custom combination of routes and responses. Or an API where every idempotent request has standard status codes. Or you might need a deeper understanding of specific connection or protocol errors.&lt;/p&gt;

&lt;p&gt;So to start, there’s a simpler &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;classify_fn&lt;/code&gt; option, where you provide a closure to determine whether to retry or not.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;.classify_fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req_rep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req_rep&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req_rep&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SERVICE_UNAVAILABLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req_rep&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.retryable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// or check req_rep.error()?&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req_rep&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another possible avenue to explore is the composition of classifiers. For example, what if you combined something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;protocol_nacks.or(idempotent.and(service_unavailable))&lt;/code&gt;? Is this a good idea? Would people want this? If you want to &lt;em&gt;use&lt;/em&gt; something like that, file an issue or PR.&lt;/p&gt;

&lt;h3 id=&quot;probable-enhancements&quot;&gt;Probable enhancements&lt;/h3&gt;

&lt;p&gt;Besides the above, there’s a few other things we could add to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest::retry&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Backoffs:&lt;/strong&gt; They’re pretty easy to add, though the benefit they bring is only really noticeable in specific situations. This is why they aren’t included yet or would not even be enabled by default.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Replayable Body:&lt;/strong&gt; Retrying needs to clone the request, and a streaming body is not freely able to be cloned and restarted. But it’s desirable by users, so we could make it an easy configurable option, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.max_replay_body_bytes()&lt;/code&gt;. We could likely learn a bit from &lt;a href=&quot;https://linkerd.io/2021/10/26/how-linkerd-retries-http-requests-with-bodies/&quot;&gt;how Linkerd implemented it&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Per-Request Retries:&lt;/strong&gt; More and more, users ask for configuration for a specific request that differs from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Client&lt;/code&gt;. We’ve been working on &lt;a href=&quot;https://github.com/seanmonstar/reqwest/issues/2641&quot;&gt;general per-request config system&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;exploring-and-upstreaming&quot;&gt;Exploring and upstreaming&lt;/h2&gt;

&lt;p&gt;We’re exploring these ideas in reqwest, with the goal of upstreaming the more generic ideas to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Maybe that’s a builder:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;tower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;retry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.clone_reqs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.matcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RETRY_AFTER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.max_extra_load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or maybe something closer to middleware, a trait to compose pieces, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;and()&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.or()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;tower_http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;retry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clone_replayable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8192&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;idempotent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;server_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.or&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;protocol_nack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;.and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;budget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Maybe a combination! Who knows?&lt;/p&gt;

&lt;h2 id=&quot;check-it-out&quot;&gt;Check it out&lt;/h2&gt;

&lt;p&gt;There’s a &lt;a href=&quot;https://github.com/seanmonstar/reqwest/pull/2763&quot;&gt;pull request&lt;/a&gt; implementing some of these ideas, and your feedback and usage will help us to keep refining it.&lt;/p&gt;

&lt;p&gt;The two-pronged goal is to allow you to easily get retries in reqwest, and to also be able to get that easier configuration in &lt;em&gt;any&lt;/em&gt; tower stack.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/seanmonstar/reqwest/pull/2763&quot;&gt;Give a whirl!&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:scopes&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Scoping budgets wouldn’t be something to care about if the client were already built for a specific endpoint. That’s a common way to build a stack of tower layers. But reqwest is open-ended, you can send requests to anywhere with an address. So, scopes felt required. &lt;a href=&quot;#fnref:scopes&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 15 Jul 2025 10:39:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/reqwest-retries/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/reqwest-retries/</guid>
        
        <category>rust</category>
        
        <category>http</category>
        
        <category>reqwest</category>
        
        <category>tower</category>
        
        <category>retries</category>
        
        <category>open-source</category>
        
        <category>programming</category>
        
        
      </item>
    
      <item>
        <title>Body::poll_progress</title>
        <description>&lt;p&gt;This describes a proposal for a cancelation problem with hyper’s request and response bodies. &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; is an HTTP library for the Rust language.&lt;/p&gt;

&lt;h2 id=&quot;background-what-is-the-body-trait&quot;&gt;Background: what is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Body&lt;/code&gt; trait?&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Body&lt;/code&gt; trait used by &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; is meant to represent a potentially streaming (asynchronous) body of a request or response. It sorta looks like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsyncIterator&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The biggest reason for a different trait was because we needed a stable trait for &lt;a href=&quot;https://seanmonstar.com/blog/hyper-v1/&quot;&gt;hyper v1&lt;/a&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsyncIterator&lt;/code&gt; were not going to be (and still aren’t) stable. With it being a separate trait, though, we also added some HTTP-body-specific methods to it.&lt;/p&gt;

&lt;p&gt;Its similarity to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsyncIterator&lt;/code&gt; means we run into a problem with forwarding into a sink. But that we own the trait also lends to a decent solution, which this post outlines.&lt;/p&gt;

&lt;p&gt;First though, piping woes.&lt;/p&gt;

&lt;h2 id=&quot;problem-backpressured-cancelation&quot;&gt;Problem: backpressured cancelation&lt;/h2&gt;

&lt;p&gt;Piping stream-like things into sink-like destinations feels natural, and looks quite simple. Elegant even. They can be piped together, and backpressure occurs naturally. However, they lack a mechanism to completely propagate cancelation. More specifically, cancelation while backpressure is currently applied.&lt;/p&gt;

&lt;p&gt;Consider an example:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.await&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// what if body (^) cancels while we wait here?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.await&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This simple loop is piping a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Body&lt;/code&gt; into some sort of sink. The way most streams and channels work, this mostly propagates backpressure. As long as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dst&lt;/code&gt; is not able to send a frame, we don’t poll for another one, and whatever is the source of the body will back up.&lt;/p&gt;

&lt;p&gt;However, it has a flaw. Those familiar with writing proxies may notice it immediately. The destination might not have space, and so we’ll wait for it to get more. But the body could give up during that time. Since the task is only waiting on when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dst&lt;/code&gt; is ready, it could wait a significant amount of time and never notice that the body (source) has canceled.&lt;/p&gt;

&lt;h3 id=&quot;why-not-just-timeouts&quot;&gt;Why not just timeouts?&lt;/h3&gt;

&lt;p&gt;One initial question was “why not just timeouts”. Like, why not just add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body_write_timeout()&lt;/code&gt; or something to hyper’s connection builders. Fair. That would work in some cases, for sure.&lt;/p&gt;

&lt;p&gt;The thing is, sometimes timeouts are inappropriate.&lt;/p&gt;

&lt;p&gt;For example, a transparent proxy may not want to force timeouts where they didn’t exist before. They’re willing to wait nearly forever. They just want to cancel the forwarding if the sender gives up.&lt;/p&gt;

&lt;p&gt;Additionally, a chain of potential timeouts means that cancelation propagation can be delayed longer and longer, as each hop in the chain has to wait its own timeout.&lt;/p&gt;

&lt;h3 id=&quot;more-generally-yet-not&quot;&gt;More generally, yet not&lt;/h3&gt;

&lt;p&gt;This issue can also exist for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsyncIterator&lt;/code&gt;. A &lt;a href=&quot;https://without.boats/blog/poll-progress/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll_progress&lt;/code&gt; idea was outlined by withoutboats&lt;/a&gt;, though it was solving a different problem.&lt;/p&gt;

&lt;p&gt;I do think there’s some crossover that may affect each other. But it’s also worth considering separately.&lt;/p&gt;

&lt;p&gt;I’m not talking about a concept that some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for await&lt;/code&gt; syntax could magically care for. I don’t want that. Like at all. In the above example, it’d be impossible for a compiler to determine which action I want to take. Maybe the source ended cleanly. I don’t want that to cancel sending the last item.&lt;/p&gt;

&lt;p&gt;Also, and this is a biggie: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Body&lt;/code&gt; will need to solve this problem quicker.&lt;/p&gt;

&lt;h2 id=&quot;solution-bodypoll_progress&quot;&gt;Solution: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Body::poll_progress()&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;We &lt;a href=&quot;https://github.com/hyperium/http-body/pull/90&quot;&gt;propose&lt;/a&gt; to add a method to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Body&lt;/code&gt; trait:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// existing methods ...&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;poll_progress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Pin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&apos;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The purpose of the method is allow for it to make any “progress” that might result in cancelation, while not producing another frame. The details:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’s a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll_*&lt;/code&gt; function, so it allows a body to poll something else async, like a timeout, or perhaps some shutdown channel.&lt;/li&gt;
  &lt;li&gt;Returning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ready(Ok(()))&lt;/code&gt; immediately is fine, it simply means there’s &lt;em&gt;nothing&lt;/em&gt; that the body would do before another frame could be made available.&lt;/li&gt;
  &lt;li&gt;However, returning an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Err&lt;/code&gt; would indicate that the body is canceled, and a piping task can interpret that to shutdown the forwarding operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We could provide some utilities to aid use of this function, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http_body_util::BodyExt::progress()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Consider an example, something that could be even be used in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper&lt;/code&gt; internals, but could also occur elsewhere:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// produce a frame&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;select!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.hup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// unexpected EOF&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// send it&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;select!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// continue&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.progress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.abort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;alternatives-not-poll_closed&quot;&gt;Alternatives: not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll_closed&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;An alternative we considered was making this method be a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll_closed&lt;/code&gt;. It had the welcome effect of meaning we could await &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body.closed()&lt;/code&gt;, and that is fairly self-documenting. However, it ran into several problems.&lt;/p&gt;

&lt;p&gt;Being an addition to an existing trait, it needs a default implementation. But a default for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll_closed&lt;/code&gt; would likely end up being confusing. If it returns closed by default, then existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Body&lt;/code&gt;s will suddenly start aborting early. If it returns not-closed, then any naive task that might await &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body.closed()&lt;/code&gt; would hang forever.&lt;/p&gt;

&lt;p&gt;The return value also felt confusing however we put it. Does &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;closed&lt;/code&gt; return a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt;? Both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ok&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Err&lt;/code&gt; would still mean the body had closed.&lt;/p&gt;

&lt;h2 id=&quot;request-for-comments&quot;&gt;Request for Comments&lt;/h2&gt;

&lt;p&gt;I wrote this up because it felt like a big enough change to a fundamental mechanism in the ecosystem that it’d could benefit from more eyes and comments. It kinda-sorta looks like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsyncIterator::poll_progress&lt;/code&gt;, but it’s also not. Still, are there things we should prepare for? Would wg-async have thoughts? Others who are using hyper deeply?&lt;/p&gt;

&lt;p&gt;Could it be simpler? Is it flexible enough?&lt;sup id=&quot;fnref:redesign&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:redesign&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Comments on the &lt;a href=&quot;https://github.com/hyperium/http-body/pull/90&quot;&gt;pull request are most welcome&lt;/a&gt;!&lt;sup id=&quot;fnref:thanks&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:thanks&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:redesign&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Calls for completely changing hyper’s design to not need such a function aren’t helpful. hyper is stable at v1. &lt;a href=&quot;#fnref:redesign&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:thanks&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Thanks to Steven Fackler and Oliver Gould for helping iterate on this design. &lt;a href=&quot;#fnref:thanks&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 22 Apr 2025 10:01:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/body-poll-progress/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/body-poll-progress/</guid>
        
        <category>rust</category>
        
        <category>http</category>
        
        <category>hyper</category>
        
        <category>open-source</category>
        
        <category>programming</category>
        
        
      </item>
    
      <item>
        <title>A More Modular reqwest</title>
        <description>&lt;p&gt;reqwest came out &lt;a href=&quot;https://seanmonstar.com/blog/introducing-reqwest/&quot;&gt;8 years ago&lt;/a&gt;. It was meant to be a higher-level HTTP client, with batteries and opinions included. And it continues to fulfill that role very well.&lt;/p&gt;

&lt;p&gt;To do so, reqwest combined or implemented a lot of features that weren’t easily accessible elsewhere in Rust. Things like redirect handling, connection proxies, and compression.&lt;/p&gt;

&lt;p&gt;People love it. It’s the most popular HTTP client used in Rust code. As of today, it gets downloaded 10 million times per month from crates.io (which doesn’t include any internal mirrors). It helps engineers all around the world.&lt;/p&gt;

&lt;p&gt;People also wish they could better customize it. They want to add in custom logic somewhere. This makes sense. And the ecosystem has gotten &lt;a href=&quot;https://tokio.rs/blog/2021-05-announcing-tower-http&quot;&gt;even better at reuse&lt;/a&gt;. It’s time for reqwest to help be more reusable.&lt;/p&gt;

&lt;p&gt;First, what is the goal?&lt;/p&gt;

&lt;h2 id=&quot;easy-and-modular&quot;&gt;Easy and modular&lt;/h2&gt;

&lt;p&gt;Top priority is that reqwest remain &lt;strong&gt;easy&lt;/strong&gt; to use. It should be the best default for most people. If you don’t know what customizations you want, you shouldn’t have to care.&lt;/p&gt;

&lt;p&gt;It should also be &lt;em&gt;possible&lt;/em&gt; to customize. To tinker. To grab just a single piece. To re-order the pieces. To add in completely new pieces.&lt;/p&gt;

&lt;h2 id=&quot;some-concrete-work&quot;&gt;Some concrete work&lt;/h2&gt;

&lt;p&gt;So, how do we get there? Well, here’s a start.&lt;/p&gt;

&lt;p&gt;The connection pool can be changed from a single Pool type into a series of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt;s that allow better composition, such as a racing cache pool, singleton pool for HTTP/2, an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt; pool to combine them. This allows people to use less complicated pools than one that includes connection racing. It makes way for using tower’s load balancing services directly within reqwest, even.&lt;/p&gt;

&lt;p&gt;The HTTP Proxy internals can be refactored to be another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt; which fits into the series of “connector” services reqwest uses. These include loading proxy data from environment variables, and providing HTTP/HTTPS/SOCKS proxies and tunneling. Other applications that only use reqwest for proxying can depend on only those utilities.&lt;/p&gt;

&lt;p&gt;reqwest supports some basic redirect policies, and allows for custom ones. Eventually, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt; added middleware to do that too. We can now use redirects from tower-http. It’d be better to update reqwest to depend on that middleware internally, allowing reqwest’s test suite to find any pieces lacking in the port.&lt;/p&gt;

&lt;p&gt;We can add &lt;em&gt;easy&lt;/em&gt; request retries. reqwest doesn’t really have retries, other than a very specific case: special HTTP/2 error cases. And conceptually, retries aren’t that different from redirects. Retrying requests is pretty common thing to ask for, and it’s pretty easy to do them wrong. There’s middleware in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower::retry&lt;/code&gt;, but it’s not easy. We could make it as easy as calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.retries(reqwest::retry::idempotent())&lt;/code&gt; on a client builder. Or a few other common policies.&lt;/p&gt;

&lt;p&gt;We can use decompression from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt;. reqwest has automatic response body decompression. Eventually, it was added as middleware in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt;. Instead of having the feature essentially duplicated, we can just depend on the modular version, and the test suite will keep the quality up. Doing it this way improves the middleware for everyone. For instance, when one user swapped from reqwest’s decompression to using tower-http, performance got worse. Eventually, a reused allocation was backported, bringing it back in line.&lt;/p&gt;

&lt;h2 id=&quot;better-default-tls&quot;&gt;Better default TLS&lt;/h2&gt;

&lt;p&gt;Initially, reqwest made use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;native-tls&lt;/code&gt; for HTTPS support. Eventually, we added optional support for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustls&lt;/code&gt;. But we’ve kept &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;native-tls&lt;/code&gt; as the default. The reason was because it worked for more users, and more sites. However, I think it’s time to change the defaults.&lt;/p&gt;

&lt;p&gt;At this point, reqwest’s defaults actually target the worst common denominator. It not longer feels right to make people opt-in to the better choice. As I said at the beginning, reqwest bundles opinions too.&lt;/p&gt;

&lt;p&gt;Our opinion is that reqwest should have the &lt;em&gt;best&lt;/em&gt; defaults for the most people. Those that need something different can opt-in to that.&lt;sup id=&quot;fnref:defaults&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:defaults&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;So, reqwest will be changing it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default-tls&lt;/code&gt; feature to rely on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustls&lt;/code&gt;. Likely with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aws-lc-rs&lt;/code&gt; as the crypto backend. Optional support for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;native-tls&lt;/code&gt; will remain, for now.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default-tls&lt;/code&gt; feature theoretically was designed to allow for such a change, since nothing should be exposed with it that isn’t supported by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustls&lt;/code&gt;. But they do have different build requirements, so it won’t be 100% smooth.&lt;/p&gt;

&lt;p&gt;But it will be better for most people.&lt;/p&gt;

&lt;h2 id=&quot;getting-to-work&quot;&gt;Getting to work&lt;/h2&gt;

&lt;p&gt;That’s the work. Keeping reqwest easy. Allowing more customization. Even letting people use fewer parts of it. While having strong opinions. Making it better for most people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to be part of it?&lt;/strong&gt; Help contribute code or documentation. Here’s &lt;a href=&quot;https://github.com/users/seanmonstar/projects/3&quot;&gt;the issue plan&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsor&lt;/a&gt; the work. Roadmaps and priorities like these come about from conversations with companies that keep retainers.&lt;/p&gt;

&lt;p&gt;All of it helps! To making HTTP requests better!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:defaults&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This could also be applied to other features too. I think there’s an argument to be made for switching the default DNS resolver to use hickory-dns instead &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getaddrinfo&lt;/code&gt;. &lt;a href=&quot;#fnref:defaults&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 04 Mar 2025 13:05:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/modular-reqwest/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/modular-reqwest/</guid>
        
        <category>rust</category>
        
        <category>reqwest</category>
        
        <category>tower</category>
        
        <category>http</category>
        
        <category>open-source</category>
        
        <category>programming</category>
        
        
      </item>
    
      <item>
        <title>2024 in review</title>
        <description>&lt;p&gt;I want to go through some highlights of the year. Thanks for coming along for the ride!&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h2 id=&quot;a-year-of-being-independent&quot;&gt;A year of being independent&lt;/h2&gt;

&lt;p&gt;This was my first entire year of my being an &lt;a href=&quot;https://seanmonstar.com/blog/independent-open-source-maintainer/&quot;&gt;independent open source maintainer&lt;/a&gt;. I’m very happy with how it turned out!&lt;/p&gt;

&lt;p&gt;I highly appreciate all who &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsor&lt;/a&gt; some amount each month, thank you all! It adds up. &amp;lt;3&lt;/p&gt;

&lt;p&gt;I’ve found setting up &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;advisor retainers&lt;/a&gt; to be very effective: I get to help engineers with private code, the higher context helps prioritize features or fixes that are needed, and the maintenance work that people don’t always want to think about is funded.&lt;/p&gt;

&lt;p&gt;I’m hopeful about this next year, and I’ll need your help to continue.&lt;/p&gt;

&lt;h2 id=&quot;hyper&quot;&gt;hyper&lt;/h2&gt;

&lt;p&gt;One of the things I’m most excited about is that in the beginning of the year, we added 3 new collaborators to hyper: &lt;a href=&quot;https://hyper.rs/blog/2024/02/28/welcome-noah-kennedy/&quot;&gt;@Noah-Kennedy&lt;/a&gt;, &lt;a href=&quot;https://hyper.rs/blog/2024/03/04/welcome-dswij/&quot;&gt;@dswij&lt;/a&gt;, and &lt;a href=&quot;https://hyper.rs/blog/2024/03/08/welcome-tottoto/&quot;&gt;@tottoto&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;More collaborators improve the health of the project, reduces review load, increase diversity of thought, etc. Some ask how they can be become one, so I spent some time writing &lt;a href=&quot;https://hyper.rs/contrib/governance#collaborator&quot;&gt;what a collaborator is&lt;/a&gt; in hyper’s contrib docs.&lt;/p&gt;

&lt;p&gt;There were 12 releases of &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;, not to mention explorations in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper-util&lt;/code&gt;, and maintenance in dependencies like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;httparse&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A few of the new features we got this year include support for sending and receiving HTTP/1.1 Trailers, improved connection selection with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try_send_request&lt;/code&gt;, and a server connection helper with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GracefulShutdown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Wrapping up the year, I &lt;a href=&quot;https://seanmonstar.com/blog/hyper-roadmap-2025/&quot;&gt;updated the roadmap&lt;/a&gt;, highlighting our focus after stabilizing v1. One area that’s already started to see improvements are the &lt;a href=&quot;https://hyper.rs/guides&quot;&gt;hyper docs and guides&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;reqwest&quot;&gt;reqwest&lt;/h2&gt;

&lt;p&gt;A lot of cool work was done in &lt;a href=&quot;https://github.com/seanmonstar/reqwest&quot;&gt;reqwest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://seanmonstar.com/blog/reqwest-v012/&quot;&gt;v0.12 was the big one&lt;/a&gt;, upgrading to hyper v1.0, back in March. But it didn’t end there, reqwest kept getting better and better throughout the year.&lt;/p&gt;

&lt;p&gt;An improved timeout option was added, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read_timeout&lt;/code&gt;, which better matches how many want to detect a broken connection, instead of an entire request deadline.&lt;/p&gt;

&lt;p&gt;HTTP/3 support returned, unstable but better, with IPv6 and content-length fixes.&lt;/p&gt;

&lt;p&gt;Integration with rustls gained support for the new aws-lc backend, and reqwest gained several cargo feature options to combine it with the various sources of certificate roots.&lt;/p&gt;

&lt;p&gt;To go along with that, reqwest also gained support for certificate revocation lists. I’m glad to hear that building rustls with aws-lc is getting easier, I hope to make that the default in reqwest this year.&lt;/p&gt;

&lt;p&gt;Near the end of the year, reqwest gained support to inject connector layers, which allow users to customize connection establishment much more than hard coded options.&lt;/p&gt;

&lt;p&gt;That last one is actually a taste of what is coming to reqwest. I’ve often mentioned a desire for making reqwest work even more as a stack of middleware, and I have much more of a plan now. Details in another blog post soon!&lt;/p&gt;

&lt;h2 id=&quot;security&quot;&gt;Security&lt;/h2&gt;

&lt;p&gt;Maintaining these libraries means keeping them secure. Over the past year, I dealt with various security reports, which are always quite &lt;strong&gt;expensive&lt;/strong&gt;. They require dropping what I am doing, digging in with research, and testing to fully understand the report quickly. Some were determined not an issue, others were bugs that we fixed but not worth yelling about.&lt;/p&gt;

&lt;p&gt;One of the more consuming reports was &lt;a href=&quot;https://seanmonstar.com/blog/hyper-http2-continuation-flood/&quot;&gt;HTTP/2 Continuation Flood&lt;/a&gt;. It wasn’t limited to hyper, instead affecting many implementations. hyper was somewhat affected, and we coordinated and got updates out on the coordinated disclosure date. Thanks to the &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsors&lt;/a&gt; I was able to do this work.&lt;/p&gt;

&lt;h2 id=&quot;podcast&quot;&gt;Podcast&lt;/h2&gt;

&lt;p&gt;I got to &lt;a href=&quot;https://seanmonstar.com/talks&quot;&gt;join&lt;/a&gt; Allen Wyma on the &lt;a href=&quot;https://seanmonstar.com/blog/podcast-rustacean-station-2/&quot;&gt;Rustacean Station&lt;/a&gt; again, and we talked about hyper reaching v1, access to advising from a maintainer, middleware, retry storms, and more.&lt;/p&gt;

&lt;h2 id=&quot;bye-curl&quot;&gt;bye curl&lt;/h2&gt;

&lt;p&gt;Back in 2020, we added support for hyper to be an HTTP backed in curl. It languished at “nearly complete”, and in November I put out a &lt;a href=&quot;https://seanmonstar.com/blog/hyper-in-curl-needs-a-champion/&quot;&gt;call for a champion&lt;/a&gt; to keep it alive.&lt;/p&gt;

&lt;p&gt;It seems we as an industry didn’t &lt;em&gt;really&lt;/em&gt; want it, so it has now been &lt;a href=&quot;https://daniel.haxx.se/blog/2024/12/21/dropping-hyper/&quot;&gt;removed as an option in curl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But that’s ok. Both projects were improved by the process. I appreciated being able to work with Daniel; he is an excellent maintainer that truly cares about quality.&lt;/p&gt;

&lt;p&gt;My focus is more on the audience that wants to write software &lt;em&gt;in Rust&lt;/em&gt;. More and more services and tools are popping up everyday that must be fast and secure as they talk to other computers. Teams pick Rust and hyper and its ecosystem to deliver their experiences. I’ll continue to empower them.&lt;/p&gt;

&lt;h2 id=&quot;questions-to-ponder-in-2025&quot;&gt;Questions to ponder in 2025&lt;/h2&gt;

&lt;p&gt;I wanted to share a few questions that I’m pondering as I head into 2025. It feels better than pretending to know more definite plans.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How can I encourage more collaborators? It’s normal for some to change focus, so we always need more.&lt;/li&gt;
  &lt;li&gt;What would a generic configuration builder look like? I imagine a zero-cost, injectable HList of properties to configure possibly unknown stacks of things. But how?&lt;/li&gt;
  &lt;li&gt;Can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::error&lt;/code&gt; ever be good? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E: Error&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Box&amp;lt;dyn Error&amp;gt;&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anyhow&lt;/code&gt; have too many sharp edges exposed.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;See some previous yearly reviews: &lt;a href=&quot;https://seanmonstar.com/blog/2023-in-review&quot;&gt;2023&lt;/a&gt;, &lt;a href=&quot;https://seanmonstar.com/blog/hyper-ish-2022-in-review&quot;&gt;2022&lt;/a&gt;, &lt;a href=&quot;https://seanmonstar.com/blog/hyper-ish-2021-in-review&quot;&gt;2021&lt;/a&gt;. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 15 Jan 2025 12:05:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/2024-in-review/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/2024-in-review/</guid>
        
        <category>yearly</category>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>open-source</category>
        
        <category>reqwest</category>
        
        <category>curl</category>
        
        
      </item>
    
      <item>
        <title>hyper Roadmap 2025</title>
        <description>&lt;p&gt;After a year since &lt;a href=&quot;https://seanmonstar.com/blog/hyper-v1/&quot;&gt;hyper 1.0&lt;/a&gt;, we’re updating the ROADMAP. &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; is an HTTP library written in Rust, used by many in production.&lt;/p&gt;

&lt;p&gt;The purpose of the &lt;a href=&quot;https://hyper.rs/contrib/roadmap/&quot;&gt;ROADMAP&lt;/a&gt; is to highlight what is highest priority in order to continue orienting hyper towards its VISION.&lt;/p&gt;

&lt;p&gt;It’s based on interviewing our users to see make sure what the most important things are. Writing it down is a way of letting users know what’s coming next.&lt;/p&gt;

&lt;h2 id=&quot;open-source-is-guiding&quot;&gt;Open source is guiding&lt;/h2&gt;

&lt;p&gt;Open source is not a company, and so people can work on and contribute whatever they want.&lt;/p&gt;

&lt;p&gt;But we &lt;em&gt;can&lt;/em&gt; guide contributions, by outlining what is most important for the project. Thus, a secondary purpose of the roadmap is to be a guide for those interested in contributing, but not sure what to do specifically.&lt;/p&gt;

&lt;h2 id=&quot;focus-areas&quot;&gt;Focus Areas&lt;/h2&gt;

&lt;p&gt;The roadmap breaks down &lt;a href=&quot;https://hyper.rs/contrib/roadmap/&quot;&gt;four focus areas&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: Invest in docs, guides, and examples to ensure users can learn how to use hyper.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;hyper-util&lt;/strong&gt;: Provide new helpers for use with hyper, and stabilize and graduate some into hyper itself.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;HTTP/3&lt;/strong&gt;: Harden the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; crate (&lt;a href=&quot;https://docs.rs/reqwest/latest/reqwest/#unstable-features&quot;&gt;reqwest&lt;/a&gt; uses this already!), and use it to power &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conn::http3&lt;/code&gt; in hyper.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Observability&lt;/strong&gt;: Improve visibility into hyper’s operations through stable support for events, tracing, and metrics.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;a-living-document&quot;&gt;A living document&lt;/h2&gt;

&lt;p&gt;The ROADMAP is a living document. As we make progress, or as priorities change, the document can too. Proposals for additions and edits are always welcome.&lt;/p&gt;

&lt;h2 id=&quot;contribute&quot;&gt;Contribute&lt;/h2&gt;

&lt;p&gt;If you’ve wanted to &lt;a href=&quot;https://github.com/hyperium/hyper/blob/master/CONTRIBUTING.md&quot;&gt;get started contributing&lt;/a&gt; to a Rust open source project, help us build hyper! Pick one of the focus areas that interest you, and reach out in an issue or Discord. We’d be thrilled to mentor you.&lt;/p&gt;

</description>
        <pubDate>Tue, 10 Dec 2024 11:48:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-roadmap-2025/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-roadmap-2025/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>open-source</category>
        
        <category>http</category>
        
        
      </item>
    
      <item>
        <title>hyper in curl Needs a Champion</title>
        <description>&lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; - hyper in curl is nearly complete, but it needs a champion. Without a partner actively engaged that wants to enable and ship, it’s now on the path for being deprecated and removed.&lt;/p&gt;

&lt;p&gt;It needs a champion, a backing vendor or distro. Will that be you?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE 2024-12-21&lt;/strong&gt;: &lt;a href=&quot;https://daniel.haxx.se/blog/2024/12/21/dropping-hyper/&quot;&gt;curl has dropped hyper&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;why-would-you-put-a-hyper-in-a-curl&quot;&gt;Why would you put a hyper in a curl?&lt;/h2&gt;

&lt;p&gt;Why would you? Memory safety.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/&quot;&gt;Company&lt;/a&gt; after &lt;a href=&quot;https://www.chromium.org/Home/chromium-security/memory-safety&quot;&gt;company&lt;/a&gt;, &lt;a href=&quot;https://security.googleblog.com/2019/05/queue-hardening-enhancements.html&quot;&gt;product&lt;/a&gt; after &lt;a href=&quot;https://hacks.mozilla.org/2019/02/rewriting-a-browser-component-in-rust/&quot;&gt;product&lt;/a&gt;,  &lt;a href=&quot;https://langui.sh/2019/07/23/apple-memory-safety/&quot;&gt;report&lt;/a&gt; after &lt;a href=&quot;https://googleprojectzero.blogspot.com/p/0day.html&quot;&gt;report&lt;/a&gt;. Memory &lt;em&gt;un&lt;/em&gt;-safety. Causes. Serious. Issues.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://curl.se&quot;&gt;curl&lt;/a&gt; is &lt;em&gt;everywhere&lt;/em&gt;. Billions of installations. It’s likely all humans accessing the internet use curl.&lt;/p&gt;

&lt;p&gt;A self-analysis of curl finds that &lt;a href=&quot;https://daniel.haxx.se/blog/2021/03/09/half-of-curls-vulnerabilities-are-c-mistakes/&quot;&gt;half of curl’s vulnerabilities are C mistakes&lt;/a&gt;. Memory safety.&lt;/p&gt;

&lt;p&gt;As I said when &lt;a href=&quot;https://aws.amazon.com/blogs/opensource/how-using-hyper-in-curl-can-help-make-the-internet-safer/&quot;&gt;when we told the world about it&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Considering how much curl is used, this was an opportunity to make the &lt;em&gt;internet&lt;/em&gt; safer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; is the most mature HTTP library written in Rust. By making hyper a possible HTTP backend for curl, the code used for the most ubiquituous protocol could be made safer. Certainly true for HTTP/1, even more so with the much bigger (code-wise) HTTP/2 and HTTP/3.&lt;/p&gt;

&lt;p&gt;So, why do this? Oh, right. Ahem. &lt;strong&gt;Memory safety&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;most-of-the-work-is-done&quot;&gt;Most of the work is done&lt;/h2&gt;

&lt;p&gt;Let me back up a little.&lt;/p&gt;

&lt;p&gt;In 2020, we started &lt;a href=&quot;https://www.memorysafety.org/blog/memory-safe-curl/&quot;&gt;exploring the idea&lt;/a&gt;. I designed and built a &lt;a href=&quot;https://docs.rs/hyper/latest/hyper/ffi/&quot;&gt;C API for hyper&lt;/a&gt;. Daniel refactored curl to allow for HTTP backends, and &lt;a href=&quot;https://daniel.haxx.se/blog/2021/05/28/taking-hyper-curl-further/&quot;&gt;integrated hyper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We got it nearly complete. Adventurous tinkerers were able to build and use it on their personal machines. Over 95% of curl’s large test suite was passing.&lt;/p&gt;

&lt;p&gt;I gave &lt;a href=&quot;https://seanmonstar.com/blog/curl-up-2022-hyper-in-curl/&quot;&gt;a talk for curl up 2022&lt;/a&gt; about the progress.&lt;sup id=&quot;fnref:since&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:since&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;We’re ready to finish, technically.&lt;/p&gt;

&lt;h2 id=&quot;over-the-finish-line&quot;&gt;Over the finish line&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.memorysafety.org/blog/memory-safe-curl/&quot;&gt;Funding for an engineer&lt;/a&gt; to complete the work is available.&lt;/p&gt;

&lt;p&gt;But the upkeep of the feature isn’t free, in both the curl and hyper repositories. Because of that, and without a commited organization wanting to ship it, it’s &lt;a href=&quot;https://github.com/curl/curl/blob/7b12c36ca972d9e9a14088cdd88232385e619d44/docs/DEPRECATE.md#Hyper&quot;&gt;planned to be removed&lt;/a&gt; at the start of 2025.&lt;/p&gt;

&lt;p&gt;So, what exactly could change that? What is needed?&lt;/p&gt;

&lt;h2 id=&quot;champion-required&quot;&gt;Champion required&lt;/h2&gt;

&lt;p&gt;A champion, if you want it.&lt;sup id=&quot;fnref:want&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:want&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A backing vendor or distro&lt;/strong&gt; that wants to enable and actively use the backend. A launch partner. Many people know what it’s like to work on a large new feature, ask people to try it out, and everyone is too busy, assuming someone &lt;em&gt;else&lt;/em&gt; will. A launch partner actively tests it and provides feedback.&lt;/p&gt;

&lt;p&gt;There’s &lt;a href=&quot;https://thenewstack.io/feds-critical-software-must-drop-c-c-by-2026-or-face-risk/&quot;&gt;more incentive&lt;/a&gt; to partner than ever, as we see companies &lt;a href=&quot;https://security.googleblog.com/2024/10/safer-with-google-advancing-memory.html&quot;&gt;successfully make code safer&lt;/a&gt;. And this project is so close, adopting now can have a large impact compared to the remaining effort.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://seanmonstar.com/about#contact&quot;&gt;Reach out to me&lt;/a&gt; if you want this to happen. Sooner rather than later. Let’s make the &lt;em&gt;internet&lt;/em&gt; safer!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE 2024-12-21&lt;/strong&gt;: &lt;a href=&quot;https://daniel.haxx.se/blog/2024/12/21/dropping-hyper/&quot;&gt;curl has dropped hyper&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:since&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Recently, a few more things have been improved on hyper’s side. For instance, @nnethercote and @jsha &lt;a href=&quot;https://github.com/hyperium/hyper/pull/3296&quot;&gt;significantly improved&lt;/a&gt; &lt;a href=&quot;https://github.com/hyperium/hyper/pull/3424&quot;&gt;the C docs&lt;/a&gt;, and  @hjr3 &lt;a href=&quot;https://github.com/hyperium/hyper/pull/3637&quot;&gt;added HTTP/1.1 trailers support&lt;/a&gt; that curl needed. &lt;a href=&quot;#fnref:since&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:want&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;People &lt;em&gt;always&lt;/em&gt; end up doing exactly what they want. There’s a loud rewrite-it-in-Rust sub-community. Here’s an opportunity. Actions show what people actually want. &lt;a href=&quot;#fnref:want&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 19 Nov 2024 09:48:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-in-curl-needs-a-champion/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-in-curl-needs-a-champion/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>curl</category>
        
        <category>memory-safety</category>
        
        
      </item>
    
      <item>
        <title>hyper HTTP/2 Continuation Flood</title>
        <description>&lt;p&gt;Patches are available for &lt;a href=&quot;https://crates.io/crates/h2&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt;&lt;/a&gt;, v0.4.4 and v0.3.26, to harden against a newly disclosed HTTP/2 attack vector, mostly for servers. If you need help, reach out for &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;support&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’re curious about more, read on.&lt;/p&gt;

&lt;h2 id=&quot;what-is-the-attack&quot;&gt;What is the attack?&lt;/h2&gt;

&lt;p&gt;In HTTP/2, there are a bunch of frame types. Some of those frames are related to sending headers (or fields). Since there is a maximum frame size, in order to send more headers than fit, a peer can send &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONTINUATION&lt;/code&gt; frames that indicate more headers for the message.&lt;/p&gt;

&lt;p&gt;That mechanism is the source of a new attack, trying to send an infinite number of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONTINUATION&lt;/code&gt; frames to starve or kill a server. This was a coordinated release, with various implementations involved. &lt;a href=&quot;https://www.kb.cert.org/vuls/id/421644&quot;&gt;VU#421664&lt;/a&gt; has details about the others.&lt;/p&gt;

&lt;h2 id=&quot;hypers-h2-is-somewhat-affected&quot;&gt;hyper’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; is somewhat affected&lt;/h2&gt;

&lt;p&gt;The HTTP/2 specification doesn’t state a default value for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SETTING_MAX_HEADER_LIST_SIZE&lt;/code&gt;. You should set that to something reasonable for your use case. But even if you don’t, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; picks an emergency default, which is fairly high so to as to not reject requests for users who need big requests.&lt;/p&gt;

&lt;p&gt;Once a stream of headers and continuation frames reach the limit, either configured or the large default, memory growth will cap there. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; will keep reading and decoding, but discarding any new headers. Really, it’s trying to keep the HPACK table in sync, and will send back a stream error once finished of “too big”.&lt;/p&gt;

&lt;p&gt;The problem is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; won’t stop reading as long each CONTINUATION frame says there are more coming. So the memory stays the same, but it will use CPU to read and discard. And since the headers are never “complete”, the application doesn’t get to know about the processing of frames.&lt;/p&gt;

&lt;p&gt;However, if deployed on Tokio (or some other runtime with a similar feature), the &lt;a href=&quot;https://tokio.rs/blog/2020-04-preemption&quot;&gt;task budget&lt;/a&gt; will prevent it from locking out other tasks. Other requests &lt;em&gt;can&lt;/em&gt; be served, and responded to. But it will make it slower.&lt;/p&gt;

&lt;p&gt;A degradation of service.&lt;sup id=&quot;fnref:cve&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:cve&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-we-did&quot;&gt;What we did&lt;/h2&gt;

&lt;p&gt;Besides testing and determining the above, we also worked on a fix.&lt;sup id=&quot;fnref:who&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:who&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;We realized that while a lower &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SETTING_MAX_HEADER_LIST&lt;/code&gt; does help, it’s not the only thing that needs to be checked. The reason for that is because a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONTINUATION&lt;/code&gt; frame could be sent with the smallest header value, and thus take longer to reach that maximum. That will still consume resources processing frames.&lt;/p&gt;

&lt;p&gt;We figured that a maximum needed to be set on the allowed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONTINUATION&lt;/code&gt; frames. But a naïve hard-coded number has its own problems.&lt;/p&gt;

&lt;p&gt;The maximum frame size isn’t usually changed, which means you’re stuck with 16kb frames. And if you &lt;em&gt;do&lt;/em&gt; want to allow message headers bigger than that, then you need to allow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONTINUATION&lt;/code&gt; frames. Since both frame size and header list size are configurable, a hard-coded limit wouldn’t work.&lt;/p&gt;

&lt;p&gt;We settled on calculating how many &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONTINUATION&lt;/code&gt; frames would be needed for a legitimate message to send up to the max header list size. We also add a little bit of padding to that number, to account for frames that may not be perfectly packed.&lt;/p&gt;

&lt;p&gt;The patch has been tried out on some production servers, and found no false positives.&lt;/p&gt;

&lt;h2 id=&quot;what-you-can-do&quot;&gt;What you can do&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;If you don’t use HTTP/2 on a server, then don’t worry.
    &lt;ul&gt;
      &lt;li&gt;If you do, but are not exposed to untrusted L7 traffic, also don’t worry.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;If you don’t set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SETTING_MAX_HEADER_LIST_SIZE&lt;/code&gt;, you should consider doing that.&lt;/li&gt;
  &lt;li&gt;You should run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo update -p h2&lt;/code&gt; in your application to pull in the latest versions with fixes (v0.4.4 and v0.3.26).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you need help, reach out for &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;support&lt;/a&gt;. Or send &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;thanks&lt;/a&gt;, so that months long security work like this can be done in the future.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:cve&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;For this reason, we didn’t create a CVE. I’m sure some well tell me I’m wrong. I’m already skeptical of CVEs for denial-of-service; it’s a big deal for some people, and not at all for others. I’m also very wary of alert fatigue. A &lt;em&gt;degradation&lt;/em&gt; of service, where things are just slower, does not feel like a “wake-up-your-team” moment. (We did submit a RustSec advisory to nudge people to upgrade.) &lt;a href=&quot;#fnref:cve&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:who&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://hyper.rs/blog/2024/02/28/welcome-noah-kennedy/&quot;&gt;Noah Kennedy&lt;/a&gt; and I have worked on this on and off for a few months, while waiting for the VINCE deadline. Thanks Noah! &lt;a href=&quot;#fnref:who&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 03 Apr 2024 14:11:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-http2-continuation-flood/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-http2-continuation-flood/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>http2</category>
        
        <category>security</category>
        
        
      </item>
    
      <item>
        <title>Podcast: Rustacean Station, hyper 1.0, and independent maintainership</title>
        <description>&lt;p&gt;I was recently a &lt;a href=&quot;https://rustacean-station.org/episode/sean-mcarthur/&quot;&gt;guest on the Rustacean Station podcast&lt;/a&gt;. It was nice to catch up after a couple years since &lt;a href=&quot;https://seanmonstar.com/blog/podcast-hyper-on-the-rustacean-station/&quot;&gt;my last appearance&lt;/a&gt; on the show. We spoke about hyper, how and why it became v1.0, becoming an independent maintainer, future work, and more.&lt;/p&gt;

&lt;p&gt;I thought I’d grab a few fun and interesting quotes, with their timestamps:&lt;/p&gt;

&lt;h2 id=&quot;sponsoring-is-not-the-mafia-1148&quot;&gt;Sponsoring is not the Mafia (11:48)&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;The lowest engagement is &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsorship&lt;/a&gt; where it’s like, what am I getting from your sponsorship? If you turn it around and think about, well, a lot of times open source is like this common good that everyone kind of benefits from and I don’t want to pay for it because someone else is going to pay for it, right? It’s kind of like this Russian roulette of like, well, if no one pays for it, then eventually that thing is going to go away.&lt;/p&gt;

  &lt;p&gt;So sometimes when I talk to the companies, I just ask them, hey, how much are you using this stuff? You’re using it a lot. Cool. How annoying or how much work would it be to have to maintain it yourself if I were to just disappear? Oh, then we’d have to put a whole engineer on that or something like that. Okay. So if you think of it as a business risk mitigation to sponsor, then I can keep doing it. And then it becomes like, okay, well, we would pay a full-time engineer to do this all year. We can pay a way smaller amount to just have the sanity check that this is not going away.&lt;/p&gt;

  &lt;p&gt;And so what do they get? They get a business risk mitigation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;You’ll have to excuse me, but I’ve been watching a lot of Sopranos. And so when you said, how bad would it be if this thing happened to go away? It sounded a little bit like a tactic they might use to secure the contract.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;(laughs) Yeah, it’s not like an insurance racket.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;access-to-the-maintainer--advising-1250&quot;&gt;Access to the maintainer / advising (12:50)&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;There’s &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;more things that I can offer&lt;/a&gt; and I do offer. Another one is people want to be able to ask, hey, we’re using your stuff and we want to know are we using it correctly or, hey, we’ve been trying to use it and we have this problem and we don’t understand why. Could you take a look?&lt;/p&gt;

  &lt;p&gt;If it’s a private project, people aren’t going to post their source code into a public issue. I’m not going to have the time to go and take a look unless it’s like, hey, let’s get a retainer and I can now sign an NDA. I’m not going to steal their code, all that legal stuff.&lt;/p&gt;

  &lt;p&gt;It’s like getting an &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;advisor&lt;/a&gt;, a reviewer, and then I can then take that knowledge and go back and be like, okay, so I now have knowledge that like company so-and-so is using this in a way that I didn’t expect. How can I make it better for them? So like, both sides benefit, but it’s only possible if I set up contracts and everyone’s legally happy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;breaking-people-not-kneecaps-3055&quot;&gt;Breaking people, not kneecaps (30:55)&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;If something would be a breaking change, then we label it with a breaking change. And it’s not something we can do right now. We can close it or postpone it or something. And then, you know, maybe three years from now, go and take a look at all the issues that are labeled that and say like, yeah, you know what, this would be worth breaking for. But at the same time, I’d love to not have to break people, even though, you know, the promise is only for three years. I’d love to not have to.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Did you just say break people? We did go back to the mafia reference, right? But no relation, right?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Exactly. Yeah. No breaking kneecaps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;client-middleware-3212&quot;&gt;Client middleware (32:12)&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;The other major thing is improving middleware. There’s all this stuff in &lt;a href=&quot;https://crates.io/crates/tower&quot;&gt;tower&lt;/a&gt;, and it’s great. Like there’s &lt;a href=&quot;https://crates.io/crates/axum&quot;&gt;Axum&lt;/a&gt;. You can use it to make really powerful servers. But the point of this middleware was actually that you could use it both ways. You could use it for servers, but you could also use it for clients. And that doesn’t work as well.&lt;/p&gt;

  &lt;p&gt;The most popular thing to use for clients is &lt;a href=&quot;https://crates.io/crates/reqwest&quot;&gt;reqwest&lt;/a&gt;. And it doesn’t fit in to tower middleware. It has a bunch of extra stuff like redirects and some other things that it does. Various kinds of timeouts, which would be great middleware, but it’s currently all just wrapped up in reqwest.&lt;/p&gt;

  &lt;p&gt;And then also, if you even just look at the middleware in the first place, it’s like opaque. You have to understand how to do service discovery to then use load balancing. You have to understand how to build a retry policy before you can fit in retries and understand what is a retry budget.&lt;/p&gt;

  &lt;p&gt;It’s complicated. And it’d be nice if people could just get, hey, this is better for 95% of use cases. And if you really want to go and tweak your retry policy, sure you can. There’s the escape hatch over there.&lt;/p&gt;

  &lt;p&gt;But that’s my other thing to work on. Make reqwest and like Tower’s client middleware merge together a whole lot nicer so you can have &lt;a href=&quot;https://seanmonstar.com/blog/reqwest-v012&quot;&gt;much better stacked clients&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;retry-storms-and-budgets-3350&quot;&gt;Retry storms and budgets (33:50)&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Since there wasn’t a really easy plug-in, then people implement retries themselves. And that includes making themselves vulnerable to retry storms and just not doing it in a safe way. And the thing is that we have this middleware and things that would protect you from that, but they’re just complicated enough that people are like, ah, I can just retry in a loop.&lt;/p&gt;

  &lt;p&gt;But then you smash the server once things start falling apart. And it’d be so much better if you just add in a retry layer. It’s going to do things wisely. And maybe you say, you know what, on this URL, never retry it, but otherwise do the default thing.&lt;/p&gt;

  &lt;p&gt;It’d be so much nicer if you didn’t have to understand how bad retries can go.&lt;/p&gt;

  &lt;p&gt;If you just do a simple counter, then you might have counters at various layers. And maybe your counters aren’t shared. And now even though you’re trying to be nice to the server, you’re still retrying on thousands of times, whereas a shared &lt;a href=&quot;https://docs.rs/tower/latest/tower/retry/budget/struct.Budget.html&quot;&gt;budget&lt;/a&gt; or something would notice after a few retries, hey, the server’s overloaded. Let’s stop pounding it. Because as long as we keep trying, it’s never going to get back up. That’s one of the problems with retry storms.&lt;/p&gt;

  &lt;p&gt;The &lt;a href=&quot;https://linkerd.io/2019/02/22/how-we-designed-retries-in-linkerd-2-2/#using-retry-budgets&quot;&gt;linkerd blog&lt;/a&gt; had a good post on how you can fix that using Tower middleware. But I’d prefer it if people didn’t have to read that to use it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;and-plenty-of-other-topics&quot;&gt;And plenty of other topics&lt;/h2&gt;

&lt;p&gt;Go &lt;a href=&quot;https://rustacean-station.org/episode/sean-mcarthur/&quot;&gt;have a listen&lt;/a&gt;, I hope you find it informative!&lt;/p&gt;

</description>
        <pubDate>Fri, 29 Mar 2024 10:09:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/podcast-rustacean-station-2/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/podcast-rustacean-station-2/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>podcast</category>
        
        <category>open-source</category>
        
        
      </item>
    
      <item>
        <title>reqwest v0.12</title>
        <description>&lt;p&gt;Today marks the &lt;a href=&quot;https://github.com/seanmonstar/reqwest/releases/tag/v0.12.0&quot;&gt;v0.12&lt;/a&gt; release of &lt;a href=&quot;https://crates.io/crates/reqwest&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest&lt;/code&gt;&lt;/a&gt;, a higher-level, batteries-included HTTP client for the Rust language.&lt;/p&gt;

&lt;h2 id=&quot;whats-new&quot;&gt;What’s new&lt;/h2&gt;

&lt;p&gt;The headline feature of reqwest v0.12 is the upgrade to &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; v1. reqwest does a lot of custom work to add features to hyper internally, but doesn’t need to expose too much of it publicly. This was what took the majority of the work to upgrade. Still, as outlined in the &lt;a href=&quot;/blog/hyper-v1&quot;&gt;the hyper v1 announcement&lt;/a&gt;, the parts that &lt;em&gt;are&lt;/em&gt; public have stabilized. The most obvious improvement to most users of reqwest will be the stable integration with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; v1 types. This should remove the last blocker for a lot of people to finish upgrading to hyper v1.&lt;/p&gt;

&lt;p&gt;With the breaking change, we made a few more improvements. Several optional features have been added which previously were required, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http2&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;charset&lt;/code&gt;. This allows disabling them and making the compilation time and size lower if not needed. We also converted all the implicit optional dependency features to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dep:&lt;/code&gt; syntax.&lt;/p&gt;

&lt;p&gt;We had to disable the HTTP/3 feature, but it was experimental anyways. It’s a goal to bring it back as soon as possible. We might also be able to add some other QUIC backends, such as s2n-quic.&lt;/p&gt;

&lt;p&gt;See the &lt;a href=&quot;https://github.com/seanmonstar/reqwest/releases/tag/v0.12.0&quot;&gt;release&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h2 id=&quot;coming-next&quot;&gt;Coming next&lt;/h2&gt;

&lt;p&gt;As mentioned a few times before on this blog, my focus next is to make a bunch of the powerful features in reqwest available as middleware. reqwest will &lt;strong&gt;remain easy to use&lt;/strong&gt;. But it will be &lt;em&gt;possible&lt;/em&gt; for people configure their own client stacks, without needed to fork or copy code. It will also mean even if you use the reqwest default easy stack, you can more easily integrate it with other tower middleware, such as retries or load balancing.&lt;/p&gt;

&lt;h2 id=&quot;thank-you&quot;&gt;Thank you!&lt;/h2&gt;

&lt;p&gt;reqwest usage keeps on growing, and it’s both humbling and exciting to watch! For example, &lt;a href=&quot;https://rust-lang.github.io/rustup/&quot;&gt;rustup&lt;/a&gt; uses reqwest as its default download backend, helping all Rust developers to keep their compiler up to date. &lt;a href=&quot;https://oxide.computer&quot;&gt;Oxide&lt;/a&gt; uses reqwest in their &lt;a href=&quot;https://github.com/oxidecomputer/progenitor&quot;&gt;Progenitor&lt;/a&gt; library that powers their OpenAPI clients.&lt;/p&gt;

&lt;p&gt;Thank you for all your contributions, both in reporting issues, and in helping fix them. &amp;lt;3&lt;/p&gt;

&lt;h2 id=&quot;sponsor-and-support&quot;&gt;Sponsor and Support&lt;/h2&gt;

&lt;p&gt;If your company uses reqwest, consider becoming a &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsor&lt;/a&gt;. Additionally, for private advice, reviews, security help, and access to the maintainer, get in touch for &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;support&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Wed, 20 Mar 2024 08:13:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/reqwest-v012/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/reqwest-v012/</guid>
        
        <category>rust</category>
        
        <category>reqwest</category>
        
        <category>hyper</category>
        
        <category>http3</category>
        
        
      </item>
    
      <item>
        <title>2023 in review</title>
        <description>&lt;p&gt;A year of change, and of stability. Let me briefly reminisce and highlight what happened in 2023.&lt;/p&gt;

&lt;h2 id=&quot;independent&quot;&gt;Independent&lt;/h2&gt;

&lt;p&gt;I became an &lt;a href=&quot;https://seanmonstar.com/blog/independent-open-source-maintainer/&quot;&gt;independent maintainer&lt;/a&gt; in June 2023.  This was a somewhat scary decision, but it did exactly what I hoped it would: my work-life balance feels fantastic. I’m also glad to be able to do similar to what I did at AWS—meeting with and advising teams with serious deployments—but with a wider variety of use cases. (Send me an &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;email&lt;/a&gt; if that interests you.)&lt;/p&gt;

&lt;h2 id=&quot;hyper&quot;&gt;hyper&lt;/h2&gt;

&lt;p&gt;First, some stats about &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; over the past year. There were 90 unique authors this year, which is 40% growth from 2022! We had two more people sign up to be &lt;a href=&quot;https://hyper.rs/contrib/governance#triager&quot;&gt;triagers&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;v1-&quot;&gt;v1 🚀&lt;/h3&gt;

&lt;p&gt;We released &lt;a href=&quot;https://seanmonstar.com/blog/hyper-v1/&quot;&gt;hyper v1&lt;/a&gt; in November. What a ride. It brought changes, moving the less stable side out into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper-util&lt;/code&gt;. But it also signaled a core that won’t be changing any time soon. Stability.&lt;/p&gt;

&lt;p&gt;The ecosystem caught up quickly. There were releases for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;headers&lt;/code&gt;, and  &lt;a href=&quot;https://tokio.rs/blog/2023-11-27-announcing-axum-0-7-0&quot;&gt;Axum&lt;/a&gt; ready to go just a couple weeks after.  It enabled some other cool things, like the &lt;a href=&quot;https://aws.amazon.com/about-aws/whats-new/2023/11/aws-sdk-rust/&quot;&gt;general availability of the AWS SDK for Rust&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We closed out the year with v1.1, bringing back core pieces needed to make graceful shutdown in servers easier again.&lt;/p&gt;

&lt;h3 id=&quot;security&quot;&gt;Security&lt;/h3&gt;

&lt;p&gt;I reviewed at least 10 security reports, perhaps a couple more I didn’t keep track of. This includes the wider &lt;a href=&quot;https://seanmonstar.com/blog/hyper-http2-rapid-reset-unaffected/&quot;&gt;HTTP/2 rapid reset attack&lt;/a&gt; that hyper wasn’t affected by. The amount of time I spend on security reports keeps on increasing. That makes sense, we announced stability of v1, which surely made more people take a look. It also is a sign of more production deployments, with companies wanting to audit their dependencies.&lt;/p&gt;

&lt;h2 id=&quot;http3&quot;&gt;HTTP/3&lt;/h2&gt;

&lt;p&gt;Another priority this year was to make progress on hyper’s HTTP/3 support, currently under development in the &lt;a href=&quot;https://github.com/hyperium/h3&quot;&gt;h3 crate&lt;/a&gt;. We released some initial 0.0.1 releases (and a few more subsequent ones), specifically to make it easier for people to use. &lt;strong&gt;&lt;a href=&quot;https://crates.io/crates/reqwest&quot;&gt;reqwest&lt;/a&gt; gained unstable HTTP/3 support&lt;/strong&gt;, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt;, and some brave users have enabled it, found it working well, and are now asking if we can make it stable. A couple of other fine folks worked to make the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3-webtransport&lt;/code&gt; crate, building on top of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;future-focus&quot;&gt;Future Focus&lt;/h2&gt;

&lt;p&gt;Doing a bit forward looking, what’s the plan for 2024?  Well, of course it could change at any moment, but these seem to be the things people most ask me for, and most need.&lt;/p&gt;

&lt;h3 id=&quot;http3-in-hyper&quot;&gt;HTTP/3 in hyper&lt;/h3&gt;

&lt;p&gt;I hope to make significant progress towards getting HTTP/3 support directly in hyper. I’ll work on a proper proposal, but here’s some unordered steps in that direction. Stabilizing the feature in reqwest. Set up an auto-updating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; server for interop testing. Dig away at the &lt;a href=&quot;https://hyper.rs/h3/ci/compliance/report.html&quot;&gt;compliance report&lt;/a&gt;, both by labeling more of the parts already working, and adding any missing parts. Propose how to expose it in hyper, which will be tricky so as to not tie hyper to any specific TLS library. And then get it actually added, likely as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper_unstable_h3&lt;/code&gt; feature to start.&lt;/p&gt;

&lt;h3 id=&quot;level-up-client-middleware&quot;&gt;Level up Client middleware&lt;/h3&gt;

&lt;p&gt;There’s a lot of great middleware now. But it can still feel like it requires an expert to use it properly. I’ve been hinting at for a while that I’d like to do for clients what &lt;a href=&quot;https://crates.io/crates/axum&quot;&gt;Axum&lt;/a&gt; has done for servers. I hope to do that with &lt;a href=&quot;https://crates.io/crates/reqwest&quot;&gt;reqwest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;reqwest does a lot of useful things, but if someone wants to customizing it beyond the options that reqwest exposes, they have to reimplement a lot (or live with a fork). I want to make most of reqwest’s features &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower&lt;/code&gt; middleware. reqwest will still have a standard “recommended” client. But it should be easier to build up your own custom stack.&lt;/p&gt;

&lt;p&gt;And while we’re at it, I hope to make some of the most important and yet most difficult middleware much easier to sprinkle in: retries, limits, and load balancing.&lt;/p&gt;

&lt;h3 id=&quot;on-going-maintenance&quot;&gt;On-going maintenance&lt;/h3&gt;

&lt;p&gt;I also must carve out explicit time for maintenance work. There’s bugs that need fixing. Reviewing and triage takes a lot of my energy. I want to improve the docs and guides.  The amount of security reports received is growing, and those take time to investigate and respond or patch and disclose, depending on their validity and severity. This also includes time with my &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsors&lt;/a&gt;, which helps identify maintenance work priorities.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://hyper.rs/contrib/contributing/&quot;&gt;Want to join us?&lt;/a&gt;&lt;/p&gt;

</description>
        <pubDate>Tue, 16 Jan 2024 08:29:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/2023-in-review/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/2023-in-review/</guid>
        
        <category>yearly</category>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>open-source</category>
        
        <category>http3</category>
        
        
      </item>
    
      <item>
        <title>hyper v1</title>
        <description>&lt;p&gt;I’m excited to announce &lt;a href=&quot;https://github.com/hyperium/hyper/releases/tag/v1.0.0&quot;&gt;v1.0&lt;/a&gt; of &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;, a protective and efficient HTTP library written in the Rust programming language. hyper provides asynchronous HTTP/1 and HTTP/2 server and client APIs, allowing you to bring your own IO and runtime.&lt;/p&gt;

&lt;p&gt;It’s been exciting and humbling to watch users build awesome things. &lt;a href=&quot;https://blog.cloudflare.com/introducing-oxy/&quot;&gt;Cloudflare&lt;/a&gt; uses hyper within Oxy, its next generation proxy framework to handle traffic at considerable scale. After &lt;a href=&quot;https://discord.com/blog/why-discord-is-switching-from-go-to-rust&quot;&gt;Discord&lt;/a&gt;’s 5x improvement to @mention response times a few years ago, they have moved most of their &lt;a href=&quot;https://discord.com/blog/how-discord-stores-trillions-of-messages&quot;&gt;critical systems&lt;/a&gt; to depend on Rust and hyper. curl has a currently &lt;a href=&quot;https://github.com/curl/curl/blob/master/docs/HYPER.md&quot;&gt;experimental HTTP backend&lt;/a&gt; built on hyper with the goal of &lt;a href=&quot;https://aws.amazon.com/blogs/opensource/how-using-hyper-in-curl-can-help-make-the-internet-safer/&quot;&gt;making the Internet safer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Marc Brooker, a Distinguished Engineer at &lt;a href=&quot;https://arxiv.org/pdf/2305.13162.pdf&quot;&gt;AWS&lt;/a&gt;, commented:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When building our new container-loading data plane for AWS Lambda, we expected to need a custom binary protocol. In production, we’ve found the overhead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper&lt;/code&gt; to be SO low that we are excited for it to continue powering our services.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Johan Andersson, CTO at &lt;a href=&quot;https://embark.dev&quot;&gt;Embark&lt;/a&gt;, said:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We have been using and relying on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper&lt;/code&gt; for the last 5 years for our gRPC and REST services, tools, libraries, and embedded in our next game built in Rust. It has been rock solid across all of our usages, and it really is a foundational library for the Rust ecosystem. Congrats on 1.0!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The best way to get started is to check out the &lt;a href=&quot;https://hyper.rs/guides/1&quot;&gt;guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;stability-here-we-come&quot;&gt;Stability here we come&lt;/h2&gt;

&lt;p&gt;Over the past 9 years, hyper has grown from a web developer’s side project into a solid library powering huge network applications. It’s time to grow up. After bringing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; support in v0.14, we focused on providing a set of basic APIs that would keep hyper safe, fast, and flexible. This meant removing some of the more opinionated “higher level” pieces. Those belong elsewhere, like &lt;a href=&quot;https://github.com/hyperium/hyper-util&quot;&gt;hyper-util&lt;/a&gt;, reqwest, Axum.&lt;/p&gt;

&lt;p&gt;This release signals some &lt;a href=&quot;https://hyper.rs/contrib/vision/#stability-promise&quot;&gt;stability&lt;/a&gt;. Major versions, like 1.0, are stable for at least 3 years.&lt;sup id=&quot;fnref:oops&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:oops&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; We also keep a &lt;a href=&quot;https://hyper.rs/contrib/msrv/&quot;&gt;MSRV&lt;/a&gt; that is at least 6 months old.&lt;sup id=&quot;fnref:msrv&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:msrv&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; We’ll add &lt;em&gt;new&lt;/em&gt; features, and we still have a couple places to experiment: in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper-util&lt;/code&gt; crate, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper_unstable&lt;/code&gt; compiler flags.&lt;/p&gt;

&lt;p&gt;Starting in &lt;a href=&quot;https://seanmonstar.com/blog/this-month-in-hyper-march-2023/&quot;&gt;v0.14.25&lt;/a&gt;, we added a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;backports&lt;/code&gt; feature which brings the new core APIs to you immediately. Combine that with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deprecated&lt;/code&gt; feature, and you’ll be guided to making your existing code ready for the upgrade to 1.0. Be sure to check out the &lt;a href=&quot;https://hyper.rs/guides/1/upgrading&quot;&gt;upgrade guide&lt;/a&gt;!&lt;/p&gt;

&lt;h2 id=&quot;next&quot;&gt;Next&lt;/h2&gt;

&lt;p&gt;The most immediate next steps are to update the other core parts of the ecosystem that depend on hyper: &lt;a href=&quot;https://crates.io/crates/reqwest&quot;&gt;reqwest&lt;/a&gt;, &lt;a href=&quot;https://crates.io/crates/axum&quot;&gt;Axum&lt;/a&gt;, &lt;a href=&quot;https://crates.io/crates/tonic&quot;&gt;Tonic&lt;/a&gt;. But after that, there’s plenty more to do. You’re welcome to come &lt;a href=&quot;https://hyper.rs/contrib/&quot;&gt;join us&lt;/a&gt;!&lt;/p&gt;

&lt;h3 id=&quot;http3&quot;&gt;HTTP/3&lt;/h3&gt;

&lt;p&gt;I would like this to be &lt;em&gt;my&lt;/em&gt; next focus. We’ve been building up the &lt;a href=&quot;https://github.com/hyperium/h3&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt;&lt;/a&gt; crate, and &lt;a href=&quot;https://docs.rs/reqwest/latest/reqwest/#unstable-features&quot;&gt;reqwest has unstable support&lt;/a&gt; now. I’d like to stabilize the feature in reqwest, and explore how we can make it available in hyper directly. Then we can have easy HTTP/3 servers, too!&lt;/p&gt;

&lt;p&gt;The trickiest question is making it available without being tied to a TLS/QUIC library. Then, users could choose to use quinn, or s2n-quic, or msquic, or any other.&lt;/p&gt;

&lt;h3 id=&quot;stabilize-in-curl&quot;&gt;Stabilize in curl&lt;/h3&gt;

&lt;p&gt;The biggest parts of making hyper work in curl are done. Someone with experience in Rust and C could make a huge dent in Internet safety &lt;a href=&quot;https://seanmonstar.com/blog/help-stabilize-hyper-in-curl/&quot;&gt;helping to get it over the finish line&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;middleware&quot;&gt;Middleware&lt;/h3&gt;

&lt;p&gt;There’s some excellent middleware available already in &lt;a href=&quot;https://crates.io/crates/tower&quot;&gt;tower&lt;/a&gt; and &lt;a href=&quot;https://crates.io/crates/tower-http&quot;&gt;tower-http&lt;/a&gt;. But several of the important ones are just a little (or a lottle) too difficult to add to a stack. I’d also love for there to be some recommended stacks for servers and clients, that bundle together the right middleware that most people would need. To that end, I’ve mentioned before breaking open &lt;a href=&quot;https://crates.io/crates/reqwest&quot;&gt;reqwest&lt;/a&gt; such that all of its features are middleware you can customize.&lt;/p&gt;

&lt;h3 id=&quot;tracing-and-metrics&quot;&gt;Tracing and Metrics&lt;/h3&gt;

&lt;p&gt;It’s possible to currently get a decent set of logs using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower_http::trace&lt;/code&gt;. It’d be better if you could get more fine-grained traces and metrics. Probably with some stabilized integration with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tracing&lt;/code&gt; directly in hyper. Maybe some sort of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper-metrics&lt;/code&gt;, similar to &lt;a href=&quot;https://tokio.rs/blog/2022-02-announcing-tokio-metrics&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tokio-metrics&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;io_uring&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io_uring&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Part of the reason we made hyper have its own &lt;a href=&quot;https://github.com/hyperium/hyper/issues/3110&quot;&gt;IO traits&lt;/a&gt; was to be able to adapt them for completion-based IO. I believe having decent support and benchmarks could be had pretty soon, by a motivated individual.&lt;/p&gt;

&lt;h2 id=&quot;thanks&quot;&gt;Thanks&lt;/h2&gt;

&lt;p&gt;A huge thank you to all our amazing contributors. You’ve made this project the success it is, and helped move hyper along the journey to 1.0. I’d like to follow up with a separate post specifically thanking you all.&lt;/p&gt;

&lt;p&gt;Thanks to the companies who have sponsored the creation of hyper: &lt;a href=&quot;https://aws.amazon.com/&quot;&gt;AWS&lt;/a&gt;, &lt;a href=&quot;https://buoyant.io&quot;&gt;Buoyant&lt;/a&gt;, &lt;a href=&quot;https://mozilla.org&quot;&gt;Mozilla&lt;/a&gt;, &lt;a href=&quot;https://foundation.rust-lang.org/news/announcing-the-rust-foundation-s-2023-fellows/&quot;&gt;Rust Foundation&lt;/a&gt;, &lt;a href=&quot;https://fly.io&quot;&gt;Fly.io&lt;/a&gt;, &lt;a href=&quot;https://embark.dev/&quot;&gt;Embark&lt;/a&gt; and &lt;a href=&quot;https://github.com/sponsors/seanmonstar#sponsors&quot;&gt;others&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Your company could also become a &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsor or get support&lt;/a&gt;!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:oops&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Besides some correctness mistake that &lt;em&gt;must&lt;/em&gt; be fixed ASAP. &lt;a href=&quot;#fnref:oops&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:msrv&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;We realize that some users just &lt;em&gt;cannot&lt;/em&gt; upgrade that fast, and we care about them. &lt;a href=&quot;#fnref:msrv&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 15 Nov 2023 16:44:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-v1/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-v1/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>open-source</category>
        
        <category>http</category>
        
        
      </item>
    
      <item>
        <title>hyper HTTP/2 Rapid Reset Attack: Unaffected</title>
        <description>&lt;p&gt;Today, the world has been made aware of a potential vulnerability affecting most HTTP/2 implementations, sending a rapid amount of streams and resets.&lt;/p&gt;

&lt;p&gt;If you use &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;, even just it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; dependency, you are safe. &lt;strong&gt;hyper is not affected&lt;/strong&gt;. Especially if you have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; v0.3.18 or newer. We manually verified that an example hyper server responds correctly. Big thanks to &lt;a href=&quot;https://github.com/Noah-Kennedy&quot;&gt;@Noah-Kennedy&lt;/a&gt; for all the help.&lt;/p&gt;

&lt;p&gt;If you want to read more, checkout &lt;a href=&quot;https://nvd.nist.gov/vuln/detail/CVE-2023-44487&quot;&gt;CVE-2023-44487&lt;/a&gt;, or these &lt;a href=&quot;https://cloud.google.com/blog/products/identity-security/how-it-works-the-novel-http2-rapid-reset-ddos-attack&quot;&gt;other&lt;/a&gt; &lt;a href=&quot;https://blog.cloudflare.com/technical-breakdown-http2-rapid-reset-ddos-attack/&quot;&gt;breakdowns&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That’s it!&lt;/p&gt;

&lt;p&gt;You’re still here. You want to know the “why”?&lt;/p&gt;

&lt;p&gt;Well, for two main reasons.&lt;/p&gt;

&lt;p&gt;We added in specific detection of &lt;a href=&quot;https://seanmonstar.com/post/715784167270596608/coe-surpise-hyper-cve&quot;&gt;this problem back in April&lt;/a&gt;. A related flaw was reported against hyper, with the added requirement of a consistently flooded network. We fixed that. It had a CVE and RUSTSEC advisory for it, so you should have upgraded, right?&lt;/p&gt;

&lt;p&gt;But even without that fix, the damage that could be done was local. The bigger concern of this newly announced vulnerability seems to be when the receipt of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEADERS&lt;/code&gt; frame triggers more work in the handlers that needs to then be canceled. The way hyper handles frames, it will cancel out the stream before ever making it available for handlers, so the cost is local. Without the fix, and only if the user can flood the network, then hyper could consume a lot of memory keeping track of all the suddenly reset streams. If they can’t flood the network, then no problem at all.&lt;/p&gt;

&lt;p&gt;So if you’ve upgraded since April, you’re safe. By the way…&lt;/p&gt;

&lt;p&gt;Handling security by dealing with reports, and working with coordinated disclosures like today are a significant part of maintaining hyper. &lt;strong&gt;If you appreciate that hyper is kept secure&lt;/strong&gt;, consider &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsoring&lt;/a&gt;. Being able to have more support during security disclosures is something that you can setup with me privately.&lt;/p&gt;

</description>
        <pubDate>Tue, 10 Oct 2023 15:07:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-http2-rapid-reset-unaffected/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-http2-rapid-reset-unaffected/</guid>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>http2</category>
        
        <category>security</category>
        
        
      </item>
    
      <item>
        <title>Was async fn a mistake?</title>
        <description>&lt;p&gt;This &lt;a href=&quot;https://github.com/rust-lang/rust/pull/115822&quot;&gt;stabilization PR for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async fn&lt;/code&gt; in traits&lt;/a&gt; made me think: was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async fn&lt;/code&gt; in Rust a mistake?&lt;/p&gt;

&lt;p&gt;I mean, &lt;a href=&quot;https://twitter.com/seanmonstar/status/1702423803698286951&quot;&gt;I dunno&lt;/a&gt;. &lt;a href=&quot;https://masto.ai/@seanmonstar/111065463310520732&quot;&gt;Maybe it wasn’t&lt;/a&gt;. But play along for a moment.&lt;/p&gt;

&lt;p&gt;By the way, I don’t mean that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; in Rust itself is a mistake. That’s a Big Deal. It allows companies to deploy some serious stuff to production. And &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; syntax is a huge save. I don’t want to lose that. Writing manual futures and poll functions is megasad.&lt;/p&gt;

&lt;p&gt;I’m specifically talking about the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async fn&lt;/code&gt; sugar. What if we didn’t have it, and instead just returned &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Future&lt;/code&gt;s, and used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt; blocks inside the functions?&lt;sup id=&quot;fnref:reading&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:reading&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async fn&lt;/code&gt; is really nice, if you fit the expected usage. If none of the differences with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Future&lt;/code&gt; ever cause you problems, then great! But I do run into them. Other people seem to also.&lt;/p&gt;

&lt;h2 id=&quot;whats-so-bad&quot;&gt;What’s so bad?&lt;/h2&gt;

&lt;p&gt;Some of these differences cause problems that don’t have decent solutions. (&lt;a href=&quot;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=beb7c7d6f540ca55c7d19795a023cdbe&quot;&gt;Do you know the differences?&lt;/a&gt;)&lt;sup id=&quot;fnref:me&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:me&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; If you have to deal with one of them, suddenly you need to use different syntax.&lt;/p&gt;

&lt;p&gt;And now, &lt;strong&gt;people need to understand both&lt;/strong&gt;. And keep the subtle differences in their head when they read. Does that make things better? Or worse?&lt;/p&gt;

&lt;p&gt;It’s the only place that has &lt;strong&gt;a magic return type&lt;/strong&gt;. It makes lifetimes weird. With &lt;a href=&quot;https://ibraheem.ca/posts/extending-the-async-fn-syntax/&quot;&gt;suggestions to reign them in&lt;/a&gt;. It leads to all sort of proposals about how to customize the return type. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[require_send]&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async(Send)&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service::call(): Send&lt;/code&gt;, and I’m sure there’s others.&lt;sup id=&quot;fnref:rtn&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:rtn&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; I also am thinking about generators and streams, since they could also end up with magic return values.&lt;/p&gt;

&lt;p&gt;So was it mistake? I think it may have been. Don’t worry, I don’t want to take it away from you, if you disagree!&lt;sup id=&quot;fnref:for&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:for&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-if-the-alternative-was-nicer&quot;&gt;What if the alternative was nicer?&lt;/h2&gt;

&lt;p&gt;But I did wonder about this. What if we had the following features ready:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://rust-lang.github.io/rfcs/2113-dyn-trait-syntax.html#rationale-and-alternatives&quot;&gt;Repurpose bare trait syntax&lt;/a&gt; to mean &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl Trait&lt;/code&gt;. It’s been enough editions, right?&lt;/li&gt;
  &lt;li&gt;Ability to forgo naming an associated type name.&lt;/li&gt;
  &lt;li&gt;Stealing the feature from Scala where functions can &lt;em&gt;equal&lt;/em&gt; a single expression.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then asynchronous functions could look like this:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’d be a nice improvement.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:reading&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Yea, I know, it’s a little more writing. But I am in the &lt;em&gt;optimize-for-reading&lt;/em&gt; camp. We read much more than we write. So if I have to write a few more characters at a function definition, but it makes the reading experience more understandable, that’s a massive win. &lt;a href=&quot;#fnref:reading&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:me&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’ve been involved in async Rust since the beginning. I know how it used to be, I was part of the group making it better, and I pay close attention to all the new proposals. I still mean what I said: &lt;em&gt;none&lt;/em&gt; of the solutions look nice. &lt;a href=&quot;#fnref:me&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:rtn&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Return Type Notation (RTN) syntax is probably the least gross. But it raises a bunch of  questions. Does it work for all functions? If not, why not? If so, do I check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I::Iter&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I::into_iter()&lt;/code&gt;. And also to consider: Rust’s &lt;a href=&quot;https://steveklabnik.com/writing/the-language-strangeness-budget&quot;&gt;strangeness budget&lt;/a&gt;! &lt;a href=&quot;#fnref:rtn&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:for&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I could see an argument that it’s sort of like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;while&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt;. A more convenient syntax when it works, and you can use the others when you need more control. That argument breaks down when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async fn&lt;/code&gt; is part of a trait definition. But anyways, I really just want the less-sugared way to be little nicer. &lt;a href=&quot;#fnref:for&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 28 Sep 2023 16:58:00 +0000</pubDate>
        <link>https://seanmonstar.com/blog/was-async-fn-a-mistake/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/was-async-fn-a-mistake/</guid>
        
        <category>rust</category>
        
        <category>opinion</category>
        
        <category>async</category>
        
        
      </item>
    
      <item>
        <title>I&apos;m an independent open source maintainer</title>
        <description>&lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; - I’m independent, &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsor&lt;/a&gt; me!&lt;/p&gt;

&lt;p&gt;I’m doing something new. I’m an independent open source maintainer! In the beginning of June, I left my &lt;a href=&quot;https://seanmonstar.com/blog/next-up-aws/&quot;&gt;position at AWS&lt;/a&gt;.&lt;sup id=&quot;fnref:aws&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:aws&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;I’m still focused on Rust, async, and HTTP stuff. Projects like &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;, reqwest, h3, tower, and any other new ideas that come along. I just won’t be doing so as an employee.&lt;/p&gt;

&lt;p&gt;So, then how do I get paid? Let me just clear up a couple ways I’m &lt;strong&gt;not&lt;/strong&gt;. I’m not making separate licenses. I’m not charging for features.&lt;sup id=&quot;fnref:features&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:features&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; I’m not selling prioritization on roadmaps. Rather, I plan to make maintenance work my primary focus.&lt;/p&gt;

&lt;p&gt;Maintenance can feel like riding a squared unicycle while juggling water balloons. Some of those balloons are:&lt;sup id=&quot;fnref:maintainer&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:maintainer&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Designing proposals, interviewing users, re-writing those proposals.&lt;/li&gt;
  &lt;li&gt;Coding, coding, coding.&lt;/li&gt;
  &lt;li&gt;Triaging a never-ending supply of issues.&lt;/li&gt;
  &lt;li&gt;Spelunking in ancient code paths to understand and fix weird bugs.&lt;/li&gt;
  &lt;li&gt;Following a proper security policy with responsible disclosure, collaborating privately, and preparing detailed reports.&lt;/li&gt;
  &lt;li&gt;Reviewing pull requests for quality and sticking to the vision, and hopefully teaching potential collaborators.&lt;/li&gt;
  &lt;li&gt;Writing articles and giving talks, as a form of marketing and teaching.&lt;/li&gt;
  &lt;li&gt;Pretending to be a project manager.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a lot of work, &lt;strong&gt;so who would pay for all that?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Does your company depend on my work? Become a &lt;a href=&quot;https://seanmonstar.com/sponsor&quot;&gt;sponsor&lt;/a&gt;! Consider it a form of business risk mitigation. You can use &lt;a href=&quot;https://github.com/sponsors/seanmonstar&quot;&gt;GitHub Sponsors&lt;/a&gt; or &lt;a href=&quot;https://patreon.com/seanmonstar&quot;&gt;Patreon&lt;/a&gt;. I can also work with an invoice system, for any requiring that.&lt;/p&gt;

&lt;p&gt;I am also interested in some deeper relationships with companies that want more. What exactly those relationships will look like will evolve. It would likely be things that look like office hours, support or private advice. If you want to explore that with me, reach out at &lt;a href=&quot;mailto:sean@seanmonstar.com?subject=Sponsorship&quot;&gt;sean@seanmonstar.com&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:aws&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I learned a lot from my 3 years at AWS. Many lessons, some anti-lessons. Overall, I’m very grateful for my time there. But I had been planning this change for a while. And it was quite refreshing taking off a few weeks before jumping back into it all. &lt;a href=&quot;#fnref:aws&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:features&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;A win about being independent is that no single company is deciding what features should be added. &lt;a href=&quot;#fnref:features&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:maintainer&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This would be a good subject for another article. There’s a lot more to it, and it’d probably be surprising to people how many hats are needed to maintain popular open source libraries, besides “just being a programmer”. At least, if you want to do it well. &lt;a href=&quot;#fnref:maintainer&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 27 Jul 2023 15:00:25 +0000</pubDate>
        <link>https://seanmonstar.com/blog/independent-open-source-maintainer/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/independent-open-source-maintainer/</guid>
        
        <category>open-source</category>
        
        <category>rust</category>
        
        <category>hyper</category>
        
        <category>career</category>
        
        <category>bestof</category>
        
        <category>self-employment</category>
        
        <category>independent</category>
        
        <category>foss</category>
        
        
      </item>
    
      <item>
        <title>Report on Surprise hyper CVE from 2023-04-11</title>
        <description>&lt;h2 id=&quot;meta&quot;&gt;Meta&lt;/h2&gt;

&lt;p&gt;This document is meant to help publicize the learnings from a recent emergency in hyper. Documents like these are common within various organizations. Some call them “postmortems”, others say “incident reports”. I quite like what Amazon calls them, since it aptly describes the purpose: &lt;strong&gt;Correction of Error&lt;/strong&gt;. There was an error that caused an emergency, and we want to correct that error.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;A surprise &lt;a href=&quot;https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures&quot;&gt;CVE&lt;/a&gt; publicly filed for &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; on April 11, 2023 caused an emergency situation for several collaborators, and sent out dependabot warnings with no actionable advice. By day’s end, we identified a best-guess at what the cause of the low-severity vulnerability was. By the next morning, a fix was available.&lt;/p&gt;

&lt;p&gt;That the issue should have been a CVE is uncertain.&lt;/p&gt;

&lt;p&gt;The bigger concern is the way the CVE was filed bypassing the existing security policy. That is similar to finding a lighter in a school, and pulling the fire alarm. This COE discusses both why it may have happened, and how we can try to reduce future occurrences.&lt;/p&gt;

&lt;h2 id=&quot;the-impact&quot;&gt;The impact&lt;/h2&gt;

&lt;p&gt;The RustSec&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; advisory explains the issue this way:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If an attacker is able to flood the network with pairs of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEADERS&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RST_STREAM&lt;/code&gt; frames, such that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; application is not able to accept them faster than the bytes are received, the pending accept queue can grow in memory usage. Being able to do this consistently can result in excessive memory use, and eventually trigger Out Of Memory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In reality, being able to consistently accomplish those conditions would be very difficult for an attack, and so the likelihood of this affecting anyone is minimal. Certainly low severity.&lt;/p&gt;

&lt;p&gt;But the bigger impact was not this particular issue, but rather that a CVE caused a sudden panic for the maintainers and for users as dependabot alerted people with nothing that they could do.&lt;/p&gt;

&lt;h2 id=&quot;the-story&quot;&gt;The story&lt;/h2&gt;

&lt;p&gt;The original &lt;a href=&quot;https://github.com/hyperium/hyper/issues/2877&quot;&gt;issue&lt;/a&gt; was filed on May 27, 2022. Trying to better understand, I asked some poorly worded follow-up questions. Another contributor filed a pull request trying to fix the underlying issue. Several collaborators reviewed that PR, but didn’t fully grasp what it was trying to fix. It then fell into the void.&lt;/p&gt;

&lt;p&gt;On April 11, 2023, someone decided to file a public CVE for the described issue, without following the security policy. I commented on the issue that while the motivation for doing so was likely good-intentioned, it was the wrong way to go about it. GitHub imported the report, which started triggering dependabot warnings.&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; This surprised us, and at least four people dropped everything to handle the fire alarm.&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The first step was trying to determine a reproducible example. We didn’t notice at the time it was filed, but the original issue did not include full reproducible instructions. We tried to create some unit tests to mimic the behavior described, but couldn’t trigger the issue.&lt;/p&gt;

&lt;p&gt;Eventually, we noticed that a modified test that stopped “accepting” requests from the connection, but still polled it, would cause the accept queue to grow. But hyper makes sure to have a task that is always accepting requests, unless you specifically ask it to stop. Thus, the modified test seemed like user error, but it was a just guess.&lt;/p&gt;

&lt;p&gt;It just seemed too convuluted. Then we arrived at a much better guess.&lt;/p&gt;

&lt;p&gt;We finally found a way to grow the accept queue even when continuously accepting, by creating a test to blast thousands of requests in a loop. Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt;s test suite uses in-memory IO streams, we are able to fill the read buffer to near infinity. That’s when we settled on our best guess: if someone can fill the socket’s read buffer faster than the server can pop requests, then the accept queue could grow unbounded. While there is a setting to limit concurrent requests, because these are immediately reset, the limit would never be checked.&lt;/p&gt;

&lt;p&gt;After 14 hours, we had a fix written and reviewed. We determined that the issue was low severity, as the likelihood of being able to consistently attack was extremely low. And since we were adding a new limit, there was a possiblity of causing a new bug. So, better to not push something right before going to sleep.&lt;/p&gt;

&lt;p&gt;The following morning we published the fix, as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; v0.3.17. Surprising everyone who has rushed out new code, a new bug in it was indeed found. We then published v0.3.18.&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h2 id=&quot;five-whys&quot;&gt;Five whys&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Why did someone file a CVE suddenly?&lt;/strong&gt; We don’t know for sure, but we can guess.&lt;sup id=&quot;fnref:6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; A related issue had been open for a year, not fixed, so perhaps the reporter thought this was the only way to move forward.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Why wasn’t the issue acted upon a year ago?&lt;/strong&gt; When it was initially opened, the maintainers didn’t fully understand what the problem was. Follow-up questions were asked, but even our questions weren’t that clear. Eventually, we forgot about it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Why was it forgotten?&lt;/strong&gt; We didn’t have any recurring reason to check back and try to understand what the issue was. If it had been reported privately to the security address, it would have stayed high priority until it was solved or determined incorrect.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Why wasn’t the initial issue reported privately?&lt;/strong&gt; Perhaps the original reporter didn’t know about the policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-were-doing-to-prevent-a-next-time&quot;&gt;What we’re doing to prevent a next time&lt;/h2&gt;

&lt;p&gt;We can’t completely control someone randomly filing a new CVE and causing another fire drill. But there are other things we can improve at to &lt;em&gt;reduce&lt;/em&gt; the likelihood of one.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Schedule routine triage.&lt;/strong&gt; This could be a synchronous meeting, such as in a text channel, or an audio channel. Or maybe over Twitch. But it can also just be a thing that &lt;a href=&quot;https://hyper.rs/contrib/governance/#triager&quot;&gt;triagers&lt;/a&gt; agree to do asynchronously, with a brief routine report to make sure we actually do it.
    &lt;ul&gt;
      &lt;li&gt;⚠️ &lt;strong&gt;If you or your company uses hyper&lt;/strong&gt; , this would be an especially useful way to help with maintenance. Have an engineer or two dedicate a few hours each month helping us triage.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Setup a bug report checklist.&lt;/strong&gt; There is a &lt;a href=&quot;https://hyper.rs/contrib/issues/#triaging&quot;&gt;triage guide&lt;/a&gt; for bug reports, which is a good thing. But that doesn’t mean everyone (me included!) always remembers all the steps. Checklists are famous in aviation and medicine for their effectiveness in saving lives. They can also help us make sure all issues are treated properly.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Update the issue templates to use forms instead.&lt;/strong&gt; We do have an issue template in place, to try to get people to fill in more information initially. But it’s pretty easy to skip it. It’s possible using GitHub’s new forms instead of just a text template could guide people more often.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;RustSec and the CVE database are different. RustSec was much more helpful, coordinating with us by waiting until the emergency panic was over, and then discussing the best way to describe the advisory. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I updated the advisory on GitHub’s end to only indicate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt;, not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper&lt;/code&gt;. I also indicated my disappointment in GitHub’s amplifying of the alarm and making the day much more stressful. Their reply: “We do that sometimes XD”. Cool. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Meanwhile, a reddit thread took off, watching the action, commenting, and mostly criticizing the actions of all involved. Thankfully, I didn’t read comments like “I don’t have any sympathy for the maintainers” until after the fix was completed. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“At least this made you fix it, right?” No. This attitude is toxic. Doing it this way burns out everyone around who could fix it. There is a reporting process for a reason. It helps the most amount of people. Please use it. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Not literally five questions, but an &lt;a href=&quot;https://en.wikipedia.org/wiki/Five_whys&quot;&gt;exercise to try to find the root cause&lt;/a&gt;, and to note any extra things that could be fixed along the way. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Some people tried to infer bad motives, such as for clout or “another notch on a security researchers belt”. I see no reason to assume that with no evidence. &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 27 Apr 2023 19:49:36 +0000</pubDate>
        <link>https://seanmonstar.com/blog/coe-surpise-hyper-cve/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/coe-surpise-hyper-cve/</guid>
        
        <category>hyper</category>
        
        
      </item>
    
      <item>
        <title>This Month in hyper: March 2023</title>
        <description>&lt;p&gt;The days are growing longer up here, and work to make &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; better and better continues onwards!&lt;/p&gt;

&lt;p&gt;There was some particularly exciting releases, and a bunch of conversations had in March 2023.&lt;/p&gt;

&lt;h2 id=&quot;hyper-10&quot;&gt;hyper 1.0&lt;/h2&gt;

&lt;h3 id=&quot;preparing-users-for-upgrading-to-10&quot;&gt;Preparing users for upgrading to 1.0&lt;/h3&gt;

&lt;p&gt;One of the important parts of the &lt;a href=&quot;https://seanmonstar.com/blog/hyper-polish-period/&quot;&gt;hyper 1.0 polish period&lt;/a&gt; is making sure &lt;em&gt;upgrading&lt;/em&gt; from 0.14 to 1.0 is as smooth as we can make it. &lt;a href=&quot;https://github.com/hyperium/hyper/releases/tag/v0.14.25&quot;&gt;hyper v0.14.25&lt;/a&gt; is here to help. @kxt and @oddgrd backported the client and server APIs from 1.0, and added opt-in deprecation messages to help you be ready to upgrade. The deprecation warnings are meant to help you, not to annoy you.&lt;/p&gt;

&lt;p&gt;You can enable them to see where you can start preparing your code now:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[dependencies]
# besides whatever other features you&apos;ve enabled...
hyper = { verion = &quot;0.14.25&quot;, features = [&quot;backports&quot;, &quot;deprecated&quot;] }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;rc4-discussions&quot;&gt;RC4 discussions&lt;/h3&gt;

&lt;p&gt;We’ve been discussing how to wrap up the last couple of changes for 1.0, to put out an RC4 to bake some. We have some decent answers, and can get to work.&lt;/p&gt;

&lt;p&gt;hyper’s own &lt;a href=&quot;https://github.com/hyperium/hyper/issues/3040&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt; trait will change from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut self&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;self&lt;/code&gt;&lt;/a&gt;. This better aligns with reality, as most services already need to share state behind some synchronization mechanism, and needing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut self&lt;/code&gt; in the method call doesn’t help.&lt;/p&gt;

&lt;p&gt;hyper will &lt;a href=&quot;https://github.com/hyperium/hyper/issues/3110&quot;&gt;use its own IO traits&lt;/a&gt; with forwards-compatibility in mind. We want to be able to support both poll-based and completion-based (think &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;epoll&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io-uring&lt;/code&gt;) IO models.&lt;/p&gt;

&lt;h2 id=&quot;http3&quot;&gt;HTTP/3&lt;/h2&gt;

&lt;p&gt;We’re working on HTTP/3 in a separate crate, &lt;a href=&quot;https://github.com/hyperium/h3&quot;&gt;h3&lt;/a&gt;, with the goal of fitting it into &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;reqwest-includes-experimental-http3-support&quot;&gt;reqwest includes experimental HTTP/3 support&lt;/h3&gt;

&lt;p&gt;With &lt;a href=&quot;https://github.com/seanmonstar/reqwest/releases/tag/v0.11.15&quot;&gt;reqwest v0.11.15&lt;/a&gt;, you can try out HTTP/3, on the client side, in reqwest &lt;em&gt;right now&lt;/em&gt;! It’s currently experimental, which means a couple things: it might not work perfectly. Let us know! It also might be disabled in new patches, as we fiddle with it. Lastly, you need to more explicitly opt-in to the instability.&lt;/p&gt;

&lt;p&gt;That means that besides enabling the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http3&lt;/code&gt; feature from your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;, you also need to pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RUSTFLAGS=&quot;--cfg reqwest_unstable&quot;&lt;/code&gt; to the compilation job.&lt;/p&gt;

&lt;p&gt;Huge thanks to @kckeiks for integrating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest&lt;/code&gt;!&lt;/p&gt;

&lt;h3 id=&quot;h3-quinn-upgraded-to-quinn-09&quot;&gt;h3-quinn upgraded to Quinn 0.9&lt;/h3&gt;

&lt;p&gt;We found a way to upgrade h3-quinn, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream::unfold&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BoxStream&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; crate tries to be generic over any QUIC implementation. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3-quinn&lt;/code&gt; crate implements the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3::quic&lt;/code&gt; traits for the &lt;a href=&quot;https://crates.io/crates/quinn&quot;&gt;Quinn crate&lt;/a&gt;. The traits currently use poll-based methods (async function in traits isn’t stable yet, and they also wouldn’t allow polling multiple things at the same time). Newer Quinn embraced using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async fn&lt;/code&gt; on its types, instead of returning named futures, which is very fair thing to do. But it did make it hard to figure out how to implement poll-based methods over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async fn&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;I realized we could do a async-move-dance to solve this. We make an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async move&lt;/code&gt; block, moving in the type and awaiting the future, which then returns a tuple of the original type and the return value. @Ralith made the suggestion to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream::unfold&lt;/code&gt;, which streamlines that pattern. Then @inflation quickly wrote it up, and we were able to upgrade to Quinn v0.9.&lt;/p&gt;

&lt;h2 id=&quot;contribute&quot;&gt;Contribute&lt;/h2&gt;

&lt;p&gt;Want to help us out? Even trying the new releases out and give us feedback is extremely useful. Of course, contributing reviews is a great help too. Come by and &lt;a href=&quot;https://discord.gg/kkwpueZ&quot;&gt;say hi&lt;/a&gt;!&lt;/p&gt;

</description>
        <pubDate>Fri, 07 Apr 2023 13:31:29 +0000</pubDate>
        <link>https://seanmonstar.com/blog/this-month-in-hyper-march-2023/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/this-month-in-hyper-march-2023/</guid>
        
        <category>monthly</category>
        
        <category>http3</category>
        
        <category>hyper</category>
        
        <category>rust</category>
        
        <category>rust-lang</category>
        
        
      </item>
    
      <item>
        <title>This Month in hyper: February 2023</title>
        <description>&lt;p&gt;After &lt;a href=&quot;https://seanmonstar.com/blog/hyper-ish-2022-in-review/&quot;&gt;recapping the 2022 year&lt;/a&gt;, here’s what the amazing contributors have been doing to make &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; ever better during January and February of 2023.&lt;/p&gt;

&lt;h2 id=&quot;releases&quot;&gt;Releases&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/hyperium/hyper/releases/tag/v0.14.24&quot;&gt;hyper v0.14.24&lt;/a&gt;: fixes some expect-continue behavior, and reduces the internal max allocation in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to_bytes&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/hyperium/h2/releases/tag/v0.3.16&quot;&gt;h2 v0.3.16&lt;/a&gt;: adds a missing piece for Extended CONNECT, and several bug fixes (memory reduction, panics)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/seanmonstar/reqwest/releases/tag/v0.11.14&quot;&gt;reqwest v0.11.14&lt;/a&gt;: adds &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proxy::no_proxy(url)&lt;/code&gt; that works like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_PROXY&lt;/code&gt; environment variable, and several internal optimizations reducing copies and memory allocations.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/tower-rs/tower-http/releases/tag/tower-http-0.4.0&quot;&gt;tower-http v0.4.0&lt;/a&gt;: a new decompression layer for Requests, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServeDir&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ServeFile&lt;/code&gt; now translates IO errors into Responses, and adds a more flexible &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValidateRequest&lt;/code&gt; layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;hyper-10&quot;&gt;hyper 1.0&lt;/h2&gt;

&lt;p&gt;We released &lt;a href=&quot;https://github.com/hyperium/hyper/releases/tag/v1.0.0-rc.3&quot;&gt;RC3&lt;/a&gt;, which fixed up some missing pieces in the API. Places needing an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Executor&lt;/code&gt; now ask for one, and we added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyper::rt::bounds&lt;/code&gt; to publicly expose &lt;a href=&quot;https://github.com/hyperium/hyper/issues/3097&quot;&gt;nameable but future-proof Executor trait “aliases”&lt;/a&gt;, so libraries building on top of hyper can use them as bounds. We also added a few state getters for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SendRequest&lt;/code&gt; which were needed for the next exciting part.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The higher-level pooling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Client&lt;/code&gt; from 0.14.x has been ported to &lt;a href=&quot;https://github.com/hyperium/hyper-util&quot;&gt;hyper-util&lt;/a&gt;&lt;/strong&gt;. This was the most common blocker preventing people from trying out the release candidates. You can now use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;legacy::Client&lt;/code&gt; with &lt;a href=&quot;https://github.com/hyperium/hyper/releases/tag/v1.0.0-rc.3&quot;&gt;hyper 1.0.0-rc.3&lt;/a&gt;, and have the normal connecting/pooling client experience you’re used to (see the &lt;a href=&quot;https://github.com/hyperium/hyper-util/blob/master/examples/client.rs&quot;&gt;example&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;We’re still in the &lt;a href=&quot;https://seanmonstar.com/blog/hyper-polish-period/&quot;&gt;hyper polish period&lt;/a&gt; 💅. There’s still a little bit of time left to get us your feedback! It’s the &lt;em&gt;most important&lt;/em&gt; part of this period. Or join us in one of the four polish areas (or help lead one)! You can also come &lt;a href=&quot;https://discord.gg/kkwpueZ&quot;&gt;chat&lt;/a&gt; with us about anything.&lt;/p&gt;

&lt;p&gt;We took some extra time to focus on &lt;a href=&quot;https://github.com/orgs/hyperium/projects/1/views/6&quot;&gt;RC4&lt;/a&gt;, which has the last few breaking changes to go. Likely, hyper will vendor it’s own IO traits, and change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service::call&lt;/code&gt; to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;self&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;mut self&lt;/code&gt;. See the related issues if you have feedback.&lt;/p&gt;

&lt;p&gt;The extra time will also allow us to investigate having a security review done for 1.0, to prevent any gotchas.&lt;/p&gt;

&lt;h2 id=&quot;http3&quot;&gt;HTTP/3&lt;/h2&gt;

&lt;p&gt;We’re working on HTTP/3 in a separate crate, &lt;a href=&quot;https://github.com/hyperium/h3&quot;&gt;h3&lt;/a&gt;, with the goal of fitting it into &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Within the next couple days, we’d like to &lt;a href=&quot;https://github.com/hyperium/h3/issues/125&quot;&gt;publish a v0.0.1 to crates.io&lt;/a&gt;. The API likely will change in the very near future, but knowing exactly how requires allowing &lt;a href=&quot;https://github.com/seanmonstar/reqwest/pull/1599#issuecomment-1227414443&quot;&gt;experimenters like reqwest&lt;/a&gt; to try it out.&lt;/p&gt;

</description>
        <pubDate>Thu, 02 Mar 2023 15:38:06 +0000</pubDate>
        <link>https://seanmonstar.com/blog/this-month-in-hyper-february-2023/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/this-month-in-hyper-february-2023/</guid>
        
        <category>hyper</category>
        
        <category>rust</category>
        
        <category>rust-lang</category>
        
        <category>monthly</category>
        
        <category>http3</category>
        
        
      </item>
    
      <item>
        <title>hyper-ish 2022 in review</title>
        <description>&lt;p&gt;Quite the eventful year! With 2022 over&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, I want to take some time highlight what’s happened in &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; and the immediately surrounding landscape.&lt;/p&gt;

&lt;p&gt;A quick personal note, I wrote much more this year!&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Yay!&lt;/p&gt;

&lt;h2 id=&quot;hyper&quot;&gt;hyper&lt;/h2&gt;

&lt;p&gt;Let’s start with some general things about &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the human side, there were 62 unique contributors to hyper in 2022. We added &lt;a href=&quot;https://hyper.rs/blog/2022/04/08/welcome-adam-foltzer/&quot;&gt;1 more collaborator&lt;/a&gt; and &lt;a href=&quot;https://github.com/hyperium/hyper/blob/master/docs/MAINTAINERS.md#triagers&quot;&gt;2 triagers&lt;/a&gt;, and even defined what those &lt;a href=&quot;https://github.com/hyperium/hyper/blob/master/docs/GOVERNANCE.md&quot;&gt;roles&lt;/a&gt; even mean.&lt;/p&gt;

&lt;p&gt;In an effort to share the lovely work those humans do, I started writing &lt;a href=&quot;https://seanmonstar.com/tagged/monthly&quot;&gt;monthly hyper updates&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And we celebrated &lt;a href=&quot;https://seanmonstar.com/blog/hyper-10000-stars/&quot;&gt;10 thousand stars&lt;/a&gt; this year! ⭐&lt;/p&gt;

&lt;h2 id=&quot;hyper-10&quot;&gt;hyper 1.0&lt;/h2&gt;

&lt;p&gt;As I mentioned in &lt;a href=&quot;https://seanmonstar.com/blog/hyper-ish-2021-in-review/&quot;&gt;last year’s review&lt;/a&gt;, 2022 was the year we began to prepare to release a stable 1.0 of &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We started with a &lt;a href=&quot;https://seanmonstar.com/blog/hyper-10-timeline/&quot;&gt;v1.0 timeline&lt;/a&gt; (of which we’re in the final steps). After much discussion with users, we put into writing &lt;a href=&quot;https://seanmonstar.com/blog/hypers-vision/&quot;&gt;hyper’s VISION&lt;/a&gt;, which defined &lt;em&gt;where we were going&lt;/em&gt;. Shortly aftewards came the &lt;a href=&quot;https://seanmonstar.com/blog/hyper-10-roadmap/&quot;&gt;v1.0 ROADMAP&lt;/a&gt;, outlining &lt;em&gt;how to get there&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And then, a summer flurry of coding and hairy diffs.&lt;/p&gt;

&lt;p&gt;On the other side, late last year, we published &lt;a href=&quot;https://seanmonstar.com/blog/hyper-v100-rc1/&quot;&gt;v1.0.0-rc.1&lt;/a&gt;. This represented the &lt;em&gt;likely&lt;/em&gt; working library that we’d like set down into a stable parking spot for a while. While people check it out and give us feedback, we entered the &lt;a href=&quot;https://seanmonstar.com/blog/hyper-polish-period/&quot;&gt;hyper polish period&lt;/a&gt;, making sure everything &lt;em&gt;feels&lt;/em&gt; good. That’s where we still are, for a short period more.&lt;/p&gt;

&lt;p&gt;You can follow along on the &lt;a href=&quot;https://github.com/orgs/hyperium/projects/1/views/1&quot;&gt;project board&lt;/a&gt;, and specifically the &lt;a href=&quot;https://github.com/hyperium/hyper/issues/3088&quot;&gt;1.0 meta issue&lt;/a&gt; ties together non-issue related details.&lt;/p&gt;

&lt;h2 id=&quot;hyper-in-curl&quot;&gt;hyper in curl&lt;/h2&gt;

&lt;p&gt;The work to make &lt;a href=&quot;https://seanmonstar.com/blog/how-using-hyper-in-curl-can-help-make-the-internet/&quot;&gt;hyper an HTTP backend in curl&lt;/a&gt; from last year continued throughout this year. There’s just a few remaining tests in curl’s large HTTP suite that didn’t work when hyper is enabled. Several wonderful people showed up to dig in and find out exactly &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To try to empower others to do, I wrote up a &lt;a href=&quot;https://seanmonstar.com/blog/help-stabilize-hyper-in-curl/&quot;&gt;help-us-finish guide&lt;/a&gt;, explaining step-by-step how anyone could help us finish this all-important work. Later in the year, I &lt;a href=&quot;https://twitch.tv/seanmonstar&quot;&gt;streamed&lt;/a&gt; a &lt;a href=&quot;https://youtu.be/p45KggejkJ4&quot;&gt;hyper-in-curl debug session&lt;/a&gt;, where you could watch me follow the guide, and then bash the keyboard randomly while trying to understand what the issue is. You can still watch the &lt;a href=&quot;https://youtu.be/p45KggejkJ4&quot;&gt;recording&lt;/a&gt;, or see &lt;a href=&quot;https://masto.ai/@seanmonstar/109428187573196836&quot;&gt;these details&lt;/a&gt; about what test was solved and the pull requests that came out of it.&lt;/p&gt;

&lt;p&gt;I also joined Daniel Stenberg virtually by presenting about &lt;a href=&quot;https://seanmonstar.com/blog/curl-up-2022-hyper-in-curl/&quot;&gt;hyper in curl at curl-up 2022&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;h3&quot;&gt;h3&lt;/h2&gt;

&lt;p&gt;We’ve been working on the &lt;a href=&quot;https://github.com/hyperium/h3&quot;&gt;h3 crate&lt;/a&gt;, providing HTTP/3 that is generic over any QUIC implementation, with the goal of integrating into hyper directly. The repository has had a working server and client which already interoperates with other implementations.&lt;/p&gt;

&lt;p&gt;I’ve written about it in the &lt;a href=&quot;https://seanmonstar.com/tagged/monthly&quot;&gt;monthly&lt;/a&gt; updates, but here’s some highlights I’m excited about:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We added 3 new collaborators who have been driving the work: @eagr, @g2p, and @Ruben2424.&lt;/li&gt;
  &lt;li&gt;@stammw implemented graceful shutdown for the server and the client.&lt;/li&gt;
  &lt;li&gt;@Ruben2424 added &lt;a href=&quot;https://textslashplain.com/2020/05/18/a-bit-of-grease-keeps-the-web-moving/&quot;&gt;GREASE&lt;/a&gt; support via an default-on option which sends random reserved identifiers, such as frames, settings and streams, to help prevent ossification that would make future extensions harder.&lt;/li&gt;
  &lt;li&gt;@eagr made it so we now track compliance with the HTTP/3 specifications, by using special comments that are compared with the spec text, and it even outputs &lt;a href=&quot;https://hyper.rs/h3/ci/compliance/report.html&quot;&gt;a report&lt;/a&gt; updated as part of our continuous integration.&lt;/li&gt;
  &lt;li&gt;@Ruben2424 also added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3spec&lt;/code&gt; to CI, and fixed the missing pieces it noticed.&lt;/li&gt;
  &lt;li&gt;@g2p documented the entire API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While there’s still specific work that can be done on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; crate itself, it’s time to consider next steps to get it into user hands. To that end, there’s even a &lt;a href=&quot;https://github.com/seanmonstar/reqwest/pull/1599&quot;&gt;pull request for reqwest to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt;&lt;/a&gt;! There’s just some &lt;a href=&quot;https://github.com/hyperium/h3/issues/125&quot;&gt;details to work out&lt;/a&gt; around publishing unstable versions so reqwest can depend on it. We hope this experimental support will help us iron out any usage annoyances, so we can start landing it in hyper proper.&lt;/p&gt;

&lt;h2 id=&quot;tower&quot;&gt;tower&lt;/h2&gt;

&lt;p&gt;While &lt;a href=&quot;https://crates.io/crates/tower&quot;&gt;tower&lt;/a&gt; isn’t tied to hyper, we’ve always meant for people to easily combine the two libraries to make powerful, opinionated HTTP stacks.&lt;/p&gt;

&lt;p&gt;In the later half of the year, we started having discussions about making tower &lt;em&gt;easier&lt;/em&gt;. Up until now, it has mostly felt like expert mode. But if done right, we shouldn’t be telling users “no, you don’t hold it &lt;em&gt;that&lt;/em&gt; way” when they try to implement retries slightly wrong and storm their servers. So, to that end, Lucio put together a big issue outlining how we can make &lt;a href=&quot;https://github.com/tower-rs/tower/issues/682&quot;&gt;retries better&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another discussion started about the &lt;a href=&quot;https://github.com/tower-rs/tower/issues/636&quot;&gt;path to tower 1.0&lt;/a&gt;. This brought some interesting questions around how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt; handles backpressure, whether we could make &lt;em&gt;that&lt;/em&gt; any better. Certainly, something else we would want to consider is if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt; can make use of &lt;a href=&quot;https://blog.rust-lang.org/inside-rust/2022/11/17/async-fn-in-trait-nightly.html&quot;&gt;async fn in traits&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt; repository continued to see additions. Mostly middleware that are specific to HTTP that many people would find beneficial, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RequestBodyLimit&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RequestBodyTimeout&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResponseBodyTimeout&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValidateRequest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I’ve also kicked around the idea loosely about cracking open the &lt;a href=&quot;https://crates.io/crates/reqwest&quot;&gt;reqwest&lt;/a&gt; crate, and turning its various features into tower middleware. Then, reqwest is just a single opinionated way to build up a client stack. The community would be more empowered to customize the order of layers, adding or removing or swapping, and still have the power that they come to expect from using reqwest.&lt;/p&gt;

&lt;h2 id=&quot;what-are-some-possiblities-in-2023&quot;&gt;What are some possiblities in 2023?&lt;/h2&gt;

&lt;p&gt;Besides launch hyper 1.0, of course.&lt;/p&gt;

&lt;p&gt;These are are all things that many people have asked for, and I’d like to see done. But realistically, most will require help from you!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Improved middleware&lt;/li&gt;
  &lt;li&gt;HTTP/3 in hyper&lt;/li&gt;
  &lt;li&gt;Tracing and Metrics&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h2&lt;/code&gt; performance improvements&lt;/li&gt;
  &lt;li&gt;An even-lower level &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http1&lt;/code&gt; codec crate&lt;/li&gt;
  &lt;li&gt;Tower-ify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reqwest&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll likely be focused at the top of that list, but would welcome anyone interested jumping into an issue (or discussing on &lt;a href=&quot;https://discord.gg/kkwpueZ&quot;&gt;Discord&lt;/a&gt; if you prefer). Really, the biggest success would be &lt;a href=&quot;https://github.com/hyperium/hyper/blob/master/docs/GOVERNANCE.md&quot;&gt;empowering others&lt;/a&gt; to be the leaders and owners on these things. Do you want to be one of them?&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Sorry for the delay, illness struck right at the beginning of the year. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I wrote barely anything in 2021, 2020… actually for quite a few years. I used to blog multiple times a month back in 2013, but kind of teetered off the following year. Anyways, I’m really liking it (again), so here’s to more! &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 18 Jan 2023 16:28:08 +0000</pubDate>
        <link>https://seanmonstar.com/blog/hyper-ish-2022-in-review/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/hyper-ish-2022-in-review/</guid>
        
        <category>yearly</category>
        
        <category>hyper</category>
        
        <category>http3</category>
        
        <category>curl</category>
        
        <category>rust</category>
        
        <category>rust-lang</category>
        
        <category>tower</category>
        
        
      </item>
    
      <item>
        <title>This Month in hyper: November 2022</title>
        <description>&lt;p&gt;The northern hemisphere starts to cool, the trees shed their leaves to conserve energy, cultured fans watch the quadrennial football tournament, and some magnificient contributors stay warm by continuing to make &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt; ever better!&lt;/p&gt;

&lt;h2 id=&quot;releases&quot;&gt;Releases&lt;/h2&gt;

&lt;h3 id=&quot;hyper-v01423&quot;&gt;hyper v0.14.23&lt;/h3&gt;

&lt;p&gt;@jfourie1 found and fixed a nasty bug in hyper’s HTTP/2 client dispatcher, which could result in a stalled connection under high concurrency.&lt;/p&gt;

&lt;h3 id=&quot;reqwest-v01113&quot;&gt;reqwest v0.11.13&lt;/h3&gt;

&lt;p&gt;The headline addition is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientBuilder::dns_resolver()&lt;/code&gt;, which now allows users to implement completely custom DNS resolvers for reqwest to use.&lt;/p&gt;

&lt;h2 id=&quot;hyper-10&quot;&gt;hyper 1.0&lt;/h2&gt;

&lt;p&gt;With the release of rc1 last month, I wrote about how we’re now in the &lt;a href=&quot;https://seanmonstar.com/blog/hyper-polish-period/&quot;&gt;hyper polish period&lt;/a&gt; 💅.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/hyperium/hyper/pull/3059&quot;&gt;@programatik29 volunteered&lt;/a&gt; to co-lead the &lt;a href=&quot;https://github.com/orgs/hyperium/projects/1/views/7&quot;&gt;util area&lt;/a&gt;. After many contributions to get us to rc1, &lt;a href=&quot;https://github.com/hyperium/hyper/pull/3065&quot;&gt;@oddgrd joined us&lt;/a&gt; to lead the &lt;a href=&quot;https://github.com/orgs/hyperium/projects/1/views/8&quot;&gt;docs area&lt;/a&gt;. @vi noticed that the HTTP/2 client &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SendRequest&lt;/code&gt; should implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Clone&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We still eagerly welcome you trying out the release candidate and providing us feedback. It’s the &lt;em&gt;most important&lt;/em&gt; part of this period. Or join us in one of the four polish areas (or help lead one)! You can also come &lt;a href=&quot;https://discord.gg/kkwpueZ&quot;&gt;chat&lt;/a&gt; with us about anything.&lt;/p&gt;

&lt;h2 id=&quot;hyper-in-curl&quot;&gt;hyper in curl&lt;/h2&gt;

&lt;p&gt;I fixed curl’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c-hyper.c&lt;/code&gt; to &lt;a href=&quot;https://github.com/curl/curl/pull/9947&quot;&gt;classify headers from CONNECT and 1xx responses as such&lt;/a&gt;, making two more &lt;a href=&quot;https://github.com/orgs/hyperium/projects/2/views/1&quot;&gt;unit tests pass&lt;/a&gt;. I streamed the process, in case you’d find it helpful to watch someone who mainly writes Rust flounder around debugging and fixing C. &lt;a href=&quot;https://seanmonstar.com/blog/help-stabilize-hyper-in-curl/&quot;&gt;You can try&lt;/a&gt; it too!&lt;/p&gt;

&lt;h2 id=&quot;http3&quot;&gt;HTTP/3&lt;/h2&gt;

&lt;p&gt;We’re working on HTTP/3 in a separate crate, &lt;a href=&quot;https://github.com/hyperium/h3&quot;&gt;h3&lt;/a&gt;, with the goal of fitting it into &lt;a href=&quot;https://hyper.rs&quot;&gt;hyper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;@eagr made it so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recv_trailers&lt;/code&gt; doesn’t require holding onto the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SendStream&lt;/code&gt; side. @g2p cleaned up a huge swath of clippy errors.&lt;/p&gt;

&lt;p&gt;@g2p and @Ruben2424 joined as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; collaborators, thanks to their excellent and continued work!&lt;/p&gt;

&lt;h2 id=&quot;tower&quot;&gt;Tower&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/tower-rs/tower&quot;&gt;Tower&lt;/a&gt; (and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tower-http&lt;/code&gt;) are a protocol-agnostic RPC framework with middleware, and they combine nicely with hyper.&lt;/p&gt;

&lt;p&gt;@alexrudy added a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BoxCloneServiceLayer&lt;/code&gt;, and @leoyvens fixed a couple bugs in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CallAll&lt;/code&gt;. @davidpdrsn made &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BoxService&lt;/code&gt; implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sync&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Oh, and while not Tower, there was a big new &lt;a href=&quot;https://tokio.rs/blog/2022-11-25-announcing-axum-0-6-0&quot;&gt;Axum v0.6 release&lt;/a&gt;!&lt;/p&gt;

</description>
        <pubDate>Fri, 02 Dec 2022 15:50:45 +0000</pubDate>
        <link>https://seanmonstar.com/blog/this-month-in-hyper-november-2022/</link>
        <guid isPermaLink="true">https://seanmonstar.com/blog/this-month-in-hyper-november-2022/</guid>
        
        <category>hyper</category>
        
        <category>rust</category>
        
        <category>rust-lang</category>
        
        <category>monthly</category>
        
        <category>http3</category>
        
        
      </item>
    
  </channel>
</rss>
