seanmonstar My name is Sean McArthur, and here I blabber on about Rust, networking, open source, and a better web. https://seanmonstar.com/ Fri, 13 Dec 2024 17:38:13 +0000 Fri, 13 Dec 2024 17:38:13 +0000 Jekyll v3.10.0 hyper Roadmap 2025 <p>After a year since <a href="https://seanmonstar.com/blog/hyper-v1/">hyper 1.0</a>, we’re updating the ROADMAP. <a href="https://hyper.rs">hyper</a> is an HTTP library written in Rust, used by many in production.</p> <p>The purpose of the <a href="https://hyper.rs/contrib/roadmap/">ROADMAP</a> is to highlight what is highest priority in order to continue orienting hyper towards its VISION.</p> <p>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.</p> <h3 id="open-source-is-guiding">Open source is guiding</h3> <p>Open source is not a company, and so people can work on and contribute whatever they want.</p> <p>But we <em>can</em> 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.</p> <h3 id="focus-areas">Focus Areas</h3> <p>The roadmap breaks down <a href="https://hyper.rs/contrib/roadmap/">four focus areas</a>:</p> <ol> <li><strong>Documentation</strong>: Invest in docs, guides, and examples to ensure users can learn how to use hyper.</li> <li><strong>hyper-util</strong>: Provide new helpers for use with hyper, and stabilize and graduate some into hyper itself.</li> <li><strong>HTTP/3</strong>: Harden the <code class="language-plaintext highlighter-rouge">h3</code> crate (<a href="https://docs.rs/reqwest/latest/reqwest/#unstable-features">reqwest</a> uses this already!), and use it to power <code class="language-plaintext highlighter-rouge">conn::http3</code> in hyper.</li> <li><strong>Observability</strong>: Improve visibility into hyper’s operations through stable support for events, tracing, and metrics.</li> </ol> <h3 id="a-living-document">A living document</h3> <p>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.</p> <h3 id="contribute">Contribute</h3> <p>If you’ve wanted to <a href="https://github.com/hyperium/hyper/blob/master/CONTRIBUTING.md">get started contributing</a> 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.</p> Tue, 10 Dec 2024 11:48:00 +0000 https://seanmonstar.com/blog/hyper-roadmap-2025/ https://seanmonstar.com/blog/hyper-roadmap-2025/ rust hyper open-source http hyper in curl Needs a Champion <p><strong>tl;dr</strong> - 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.</p> <p>It needs a champion, a backing vendor or distro. Will that be you?</p> <h3 id="why-would-you-put-a-hyper-in-a-curl">Why would you put a hyper in a curl?</h3> <p>Why would you? Memory safety.</p> <p><a href="https://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/">Company</a> after <a href="https://www.chromium.org/Home/chromium-security/memory-safety">company</a>, <a href="https://security.googleblog.com/2019/05/queue-hardening-enhancements.html">product</a> after <a href="https://hacks.mozilla.org/2019/02/rewriting-a-browser-component-in-rust/">product</a>, <a href="https://langui.sh/2019/07/23/apple-memory-safety/">report</a> after <a href="https://googleprojectzero.blogspot.com/p/0day.html">report</a>. Memory <em>un</em>-safety. Causes. Serious. Issues.</p> <p><a href="https://curl.se">curl</a> is <em>everywhere</em>. Billions of installations. It’s likely all humans accessing the internet use curl.</p> <p>A self-analysis of curl finds that <a href="https://daniel.haxx.se/blog/2021/03/09/half-of-curls-vulnerabilities-are-c-mistakes/">half of curl’s vulnerabilities are C mistakes</a>. Memory safety.</p> <p>As I said when <a href="https://aws.amazon.com/blogs/opensource/how-using-hyper-in-curl-can-help-make-the-internet-safer/">when we told the world about it</a>:</p> <blockquote> <p>Considering how much curl is used, this was an opportunity to make the <em>internet</em> safer.</p> </blockquote> <p><a href="https://hyper.rs">hyper</a> 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.</p> <p>So, why do this? Oh, right. Ahem. <strong>Memory safety</strong>.</p> <h3 id="most-of-the-work-is-done">Most of the work is done</h3> <p>Let me back up a little.</p> <p>In 2020, we started <a href="https://www.memorysafety.org/blog/memory-safe-curl/">exploring the idea</a>. I designed and built a <a href="https://docs.rs/hyper/latest/hyper/ffi/">C API for hyper</a>. Daniel refactored curl to allow for HTTP backends, and <a href="https://daniel.haxx.se/blog/2021/05/28/taking-hyper-curl-further/">integrated hyper</a>.</p> <p>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.</p> <p>I gave <a href="https://seanmonstar.com/blog/curl-up-2022-hyper-in-curl/">a talk for curl up 2022</a> about the progress.<sup id="fnref:since" role="doc-noteref"><a href="#fn:since" class="footnote" rel="footnote">1</a></sup></p> <p>We’re ready to finish, technically.</p> <h3 id="over-the-finish-line">Over the finish line</h3> <p><a href="https://www.memorysafety.org/blog/memory-safe-curl/">Funding for an engineer</a> to complete the work is available.</p> <p>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 <a href="https://github.com/curl/curl/blob/7b12c36ca972d9e9a14088cdd88232385e619d44/docs/DEPRECATE.md#Hyper">planned to be removed</a> at the start of 2025.</p> <p>So, what exactly could change that? What is needed?</p> <h3 id="champion-required">Champion required</h3> <p>A champion, if you want it.<sup id="fnref:want" role="doc-noteref"><a href="#fn:want" class="footnote" rel="footnote">2</a></sup></p> <p><strong>A backing vendor or distro</strong> 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 <em>else</em> will. A launch partner actively tests it and provides feedback.</p> <p>There’s <a href="https://thenewstack.io/feds-critical-software-must-drop-c-c-by-2026-or-face-risk/">more incentive</a> to partner than ever, as we see companies <a href="https://security.googleblog.com/2024/10/safer-with-google-advancing-memory.html">successfully make code safer</a>. And this project is so close, adopting now can have a large impact compared to the remaining effort.</p> <p><a href="https://seanmonstar.com/about#contact">Reach out to me</a> if you want this to happen. Sooner rather than later. Let’s make the <em>internet</em> safer!</p> <div class="footnotes" role="doc-endnotes"> <ol> <li id="fn:since" role="doc-endnote"> <p>Recently, a few more things have been improved on hyper’s side. For instance, @nnethercote and @jsha <a href="https://github.com/hyperium/hyper/pull/3296">significantly improved</a> <a href="https://github.com/hyperium/hyper/pull/3424">the C docs</a>, and @hjr3 <a href="https://github.com/hyperium/hyper/pull/3637">added HTTP/1.1 trailers support</a> that curl needed. <a href="#fnref:since" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> <li id="fn:want" role="doc-endnote"> <p>People <em>always</em> 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. <a href="#fnref:want" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> </ol> </div> Tue, 19 Nov 2024 09:48:00 +0000 https://seanmonstar.com/blog/hyper-in-curl-needs-a-champion/ https://seanmonstar.com/blog/hyper-in-curl-needs-a-champion/ rust hyper curl memory-safety hyper HTTP/2 Continuation Flood <p>Patches are available for <a href="https://crates.io/crates/h2"><code class="language-plaintext highlighter-rouge">h2</code></a>, 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 <a href="https://seanmonstar.com/sponsor">support</a>.</p> <p>If you’re curious about more, read on.</p> <h3 id="what-is-the-attack">What is the attack?</h3> <p>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 <code class="language-plaintext highlighter-rouge">CONTINUATION</code> frames that indicate more headers for the message.</p> <p>That mechanism is the source of a new attack, trying to send an infinite number of <code class="language-plaintext highlighter-rouge">CONTINUATION</code> frames to starve or kill a server. This was a coordinated release, with various implementations involved. <a href="https://www.kb.cert.org/vuls/id/421644">VU#421664</a> has details about the others.</p> <h3 id="hypers-h2-is-somewhat-affected">hyper’s <code class="language-plaintext highlighter-rouge">h2</code> is somewhat affected</h3> <p>The HTTP/2 specification doesn’t state a default value for <code class="language-plaintext highlighter-rouge">SETTING_MAX_HEADER_LIST_SIZE</code>. You should set that to something reasonable for your use case. But even if you don’t, <code class="language-plaintext highlighter-rouge">h2</code> picks an emergency default, which is fairly high so to as to not reject requests for users who need big requests.</p> <p>Once a stream of headers and continuation frames reach the limit, either configured or the large default, memory growth will cap there. <code class="language-plaintext highlighter-rouge">h2</code> 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”.</p> <p>The problem is that <code class="language-plaintext highlighter-rouge">h2</code> 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.</p> <p>However, if deployed on Tokio (or some other runtime with a similar feature), the <a href="https://tokio.rs/blog/2020-04-preemption">task budget</a> will prevent it from locking out other tasks. Other requests <em>can</em> be served, and responded to. But it will make it slower.</p> <p>A degradation of service.<sup id="fnref:cve" role="doc-noteref"><a href="#fn:cve" class="footnote" rel="footnote">1</a></sup></p> <h3 id="what-we-did">What we did</h3> <p>Besides testing and determining the above, we also worked on a fix.<sup id="fnref:who" role="doc-noteref"><a href="#fn:who" class="footnote" rel="footnote">2</a></sup></p> <p>We realized that while a lower <code class="language-plaintext highlighter-rouge">SETTING_MAX_HEADER_LIST</code> does help, it’s not the only thing that needs to be checked. The reason for that is because a <code class="language-plaintext highlighter-rouge">CONTINUATION</code> frame could be sent with the smallest header value, and thus take longer to reach that maximum. That will still consume resources processing frames.</p> <p>We figured that a maximum needed to be set on the allowed <code class="language-plaintext highlighter-rouge">CONTINUATION</code> frames. But a naïve hard-coded number has its own problems.</p> <p>The maximum frame size isn’t usually changed, which means you’re stuck with 16kb frames. And if you <em>do</em> want to allow message headers bigger than that, then you need to allow <code class="language-plaintext highlighter-rouge">CONTINUATION</code> frames. Since both frame size and header list size are configurable, a hard-coded limit wouldn’t work.</p> <p>We settled on calculating how many <code class="language-plaintext highlighter-rouge">CONTINUATION</code> 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.</p> <p>The patch has been tried out on some production servers, and found no false positives.</p> <h3 id="what-you-can-do">What you can do</h3> <ul> <li>If you don’t use HTTP/2 on a server, then don’t worry. <ul> <li>If you do, but are not exposed to untrusted L7 traffic, also don’t worry.</li> </ul> </li> <li>If you don’t set the <code class="language-plaintext highlighter-rouge">SETTING_MAX_HEADER_LIST_SIZE</code>, you should consider doing that.</li> <li>You should run <code class="language-plaintext highlighter-rouge">cargo update -p h2</code> in your application to pull in the latest versions with fixes (v0.4.4 and v0.3.26).</li> </ul> <p>If you need help, reach out for <a href="https://seanmonstar.com/sponsor">support</a>. Or send <a href="https://seanmonstar.com/sponsor">thanks</a>, so that months long security work like this can be done in the future.</p> <div class="footnotes" role="doc-endnotes"> <ol> <li id="fn:cve" role="doc-endnote"> <p>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 <em>degradation</em> 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.) <a href="#fnref:cve" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> <li id="fn:who" role="doc-endnote"> <p><a href="https://hyper.rs/blog/2024/02/28/welcome-noah-kennedy/">Noah Kennedy</a> and I have worked on this on and off for a few months, while waiting for the VINCE deadline. Thanks Noah! <a href="#fnref:who" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> </ol> </div> Wed, 03 Apr 2024 14:11:00 +0000 https://seanmonstar.com/blog/hyper-http2-continuation-flood/ https://seanmonstar.com/blog/hyper-http2-continuation-flood/ rust hyper http2 security Podcast: Rustacean Station, hyper 1.0, and independent maintainership <p>I was recently a <a href="https://rustacean-station.org/episode/sean-mcarthur/">guest on the Rustacean Station podcast</a>. It was nice to catch up after a couple years since <a href="https://seanmonstar.com/blog/podcast-hyper-on-the-rustacean-station/">my last appearance</a> on the show. We spoke about hyper, how and why it became v1.0, becoming an independent maintainer, future work, and more.</p> <p>I thought I’d grab a few fun and interesting quotes, with their timestamps:</p> <h3 id="sponsoring-is-not-the-mafia-1148">Sponsoring is not the Mafia (11:48)</h3> <blockquote> <p>The lowest engagement is <a href="https://seanmonstar.com/sponsor">sponsorship</a> 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.</p> <p>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.</p> <p>And so what do they get? They get a business risk mitigation.</p> </blockquote> <blockquote> <p><em>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.</em></p> </blockquote> <blockquote> <p>(laughs) Yeah, it’s not like an insurance racket.</p> </blockquote> <h3 id="access-to-the-maintainer--advising-1250">Access to the maintainer / advising (12:50)</h3> <blockquote> <p>There’s <a href="https://seanmonstar.com/sponsor">more things that I can offer</a> 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?</p> <p>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.</p> <p>It’s like getting an <a href="https://seanmonstar.com/sponsor">advisor</a>, 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.</p> </blockquote> <h3 id="breaking-people-not-kneecaps-3055">Breaking people, not kneecaps (30:55)</h3> <blockquote> <p>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.</p> </blockquote> <blockquote> <p><em>Did you just say break people? We did go back to the mafia reference, right? But no relation, right?</em></p> </blockquote> <blockquote> <p>Exactly. Yeah. No breaking kneecaps.</p> </blockquote> <h3 id="client-middleware-3212">Client middleware (32:12)</h3> <blockquote> <p>The other major thing is improving middleware. There’s all this stuff in <a href="https://crates.io/crates/tower">tower</a>, and it’s great. Like there’s <a href="https://crates.io/crates/axum">Axum</a>. 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.</p> <p>The most popular thing to use for clients is <a href="https://crates.io/crates/reqwest">reqwest</a>. 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.</p> <p>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.</p> <p>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.</p> <p>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 <a href="https://seanmonstar.com/blog/reqwest-v012">much better stacked clients</a>.</p> </blockquote> <h3 id="retry-storms-and-budgets-3350">Retry storms and budgets (33:50)</h3> <blockquote> <p>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.</p> <p>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.</p> <p>It’d be so much nicer if you didn’t have to understand how bad retries can go.</p> <p>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 <a href="https://docs.rs/tower/latest/tower/retry/budget/struct.Budget.html">budget</a> 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.</p> <p>The <a href="https://linkerd.io/2019/02/22/how-we-designed-retries-in-linkerd-2-2/#using-retry-budgets">linkerd blog</a> 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.</p> </blockquote> <h3 id="and-plenty-of-other-topics">And plenty of other topics</h3> <p>Go <a href="https://rustacean-station.org/episode/sean-mcarthur/">have a listen</a>, I hope you find it informative!</p> Fri, 29 Mar 2024 10:09:00 +0000 https://seanmonstar.com/blog/podcast-rustacean-station-2/ https://seanmonstar.com/blog/podcast-rustacean-station-2/ rust hyper podcast open-source reqwest v0.12 <p>Today marks the <a href="https://github.com/seanmonstar/reqwest/releases/tag/v0.12.0">v0.12</a> release of <a href="https://crates.io/crates/reqwest"><code class="language-plaintext highlighter-rouge">reqwest</code></a>, a higher-level, batteries-included HTTP client for the Rust language.</p> <h3 id="whats-new">What’s new</h3> <p>The headline feature of reqwest v0.12 is the upgrade to <a href="https://hyper.rs">hyper</a> 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 <a href="/blog/hyper-v1">the hyper v1 announcement</a>, the parts that <em>are</em> public have stabilized. The most obvious improvement to most users of reqwest will be the stable integration with <code class="language-plaintext highlighter-rouge">http</code> v1 types. This should remove the last blocker for a lot of people to finish upgrading to hyper v1.</p> <p>With the breaking change, we made a few more improvements. Several optional features have been added which previously were required, such as <code class="language-plaintext highlighter-rouge">http2</code> and <code class="language-plaintext highlighter-rouge">charset</code>. 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 <code class="language-plaintext highlighter-rouge">dep:</code> syntax.</p> <p>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.</p> <p>See the <a href="https://github.com/seanmonstar/reqwest/releases/tag/v0.12.0">release</a> for more details.</p> <h3 id="coming-next">Coming next</h3> <p>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 <strong>remain easy to use</strong>. But it will be <em>possible</em> 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.</p> <h3 id="thank-you">Thank you!</h3> <p>reqwest usage keeps on growing, and it’s both humbling and exciting to watch! For example, <a href="https://rust-lang.github.io/rustup/">rustup</a> uses reqwest as its default download backend, helping all Rust developers to keep their compiler up to date. <a href="https://oxide.computer">Oxide</a> uses reqwest in their <a href="https://github.com/oxidecomputer/progenitor">Progenitor</a> library that powers their OpenAPI clients.</p> <p>Thank you for all your contributions, both in reporting issues, and in helping fix them. &lt;3</p> <h3 id="sponsor-and-support">Sponsor and Support</h3> <p>If your company uses reqwest, consider becoming a <a href="https://seanmonstar.com/sponsor">sponsor</a>. Additionally, for private advice, reviews, security help, and access to the maintainer, get in touch for <a href="https://seanmonstar.com/sponsor">support</a>.</p> Wed, 20 Mar 2024 08:13:00 +0000 https://seanmonstar.com/blog/reqwest-v012/ https://seanmonstar.com/blog/reqwest-v012/ rust reqwest hyper http3 2023 in review <p>A year of change, and of stability. Let me briefly reminisce and highlight what happened in 2023.</p> <h3 id="independent">Independent</h3> <p>I became an <a href="https://seanmonstar.com/blog/independent-open-source-maintainer/">independent maintainer</a> 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 <a href="https://seanmonstar.com/sponsor">email</a> if that interests you.)</p> <h3 id="hyper">hyper</h3> <p>First, some stats about <a href="https://hyper.rs">hyper</a> 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 <a href="https://hyper.rs/contrib/governance#triager">triagers</a>.</p> <h4 id="v1-">v1 🚀</h4> <p>We released <a href="https://seanmonstar.com/blog/hyper-v1/">hyper v1</a> in November. What a ride. It brought changes, moving the less stable side out into <code class="language-plaintext highlighter-rouge">hyper-util</code>. But it also signaled a core that won’t be changing any time soon. Stability.</p> <p>The ecosystem caught up quickly. There were releases for <code class="language-plaintext highlighter-rouge">tower-http</code>, <code class="language-plaintext highlighter-rouge">headers</code>, and <a href="https://tokio.rs/blog/2023-11-27-announcing-axum-0-7-0">Axum</a> ready to go just a couple weeks after. It enabled some other cool things, like the <a href="https://aws.amazon.com/about-aws/whats-new/2023/11/aws-sdk-rust/">general availability of the AWS SDK for Rust</a>.</p> <p>We closed out the year with v1.1, bringing back core pieces needed to make graceful shutdown in servers easier again.</p> <h4 id="security">Security</h4> <p>I reviewed at least 10 security reports, perhaps a couple more I didn’t keep track of. This includes the wider <a href="https://seanmonstar.com/blog/hyper-http2-rapid-reset-unaffected/">HTTP/2 rapid reset attack</a> 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.</p> <h3 id="http3">HTTP/3</h3> <p>Another priority this year was to make progress on hyper’s HTTP/3 support, currently under development in the <a href="https://github.com/hyperium/h3">h3 crate</a>. We released some initial 0.0.1 releases (and a few more subsequent ones), specifically to make it easier for people to use. <strong><a href="https://crates.io/crates/reqwest">reqwest</a> gained unstable HTTP/3 support</strong>, using <code class="language-plaintext highlighter-rouge">h3</code>, 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 <code class="language-plaintext highlighter-rouge">h3-webtransport</code> crate, building on top of <code class="language-plaintext highlighter-rouge">h3</code>.</p> <h3 id="future-focus">Future Focus</h3> <p>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.</p> <h4 id="http3-in-hyper">HTTP/3 in hyper</h4> <p>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 <code class="language-plaintext highlighter-rouge">h3</code> server for interop testing. Dig away at the <a href="https://hyper.rs/h3/ci/compliance/report.html">compliance report</a>, 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 <code class="language-plaintext highlighter-rouge">hyper_unstable_h3</code> feature to start.</p> <h4 id="level-up-client-middleware">Level up Client middleware</h4> <p>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 <a href="https://crates.io/crates/axum">Axum</a> has done for servers. I hope to do that with <a href="https://crates.io/crates/reqwest">reqwest</a>.</p> <p>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 <code class="language-plaintext highlighter-rouge">tower</code> middleware. reqwest will still have a standard “recommended” client. But it should be easier to build up your own custom stack.</p> <p>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.</p> <h4 id="on-going-maintenance">On-going maintenance</h4> <p>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 <a href="https://seanmonstar.com/sponsor">sponsors</a>, which helps identify maintenance work priorities.</p> <p><a href="https://hyper.rs/contrib/contributing/">Want to join us?</a></p> Tue, 16 Jan 2024 08:29:00 +0000 https://seanmonstar.com/blog/2023-in-review/ https://seanmonstar.com/blog/2023-in-review/ yearly rust hyper open-source http3 hyper v1 <p>I’m excited to announce <a href="https://github.com/hyperium/hyper/releases/tag/v1.0.0">v1.0</a> of <a href="https://hyper.rs">hyper</a>, 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.</p> <p>It’s been exciting and humbling to watch users build awesome things. <a href="https://blog.cloudflare.com/introducing-oxy/">Cloudflare</a> uses hyper within Oxy, its next generation proxy framework to handle traffic at considerable scale. After <a href="https://discord.com/blog/why-discord-is-switching-from-go-to-rust">Discord</a>’s 5x improvement to @mention response times a few years ago, they have moved most of their <a href="https://discord.com/blog/how-discord-stores-trillions-of-messages">critical systems</a> to depend on Rust and hyper. curl has a currently <a href="https://github.com/curl/curl/blob/master/docs/HYPER.md">experimental HTTP backend</a> built on hyper with the goal of <a href="https://aws.amazon.com/blogs/opensource/how-using-hyper-in-curl-can-help-make-the-internet-safer/">making the Internet safer</a>.</p> <p>Marc Brooker, a Distinguished Engineer at <a href="https://arxiv.org/pdf/2305.13162.pdf">AWS</a>, commented:</p> <blockquote> <p>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 <code class="language-plaintext highlighter-rouge">hyper</code> to be SO low that we are excited for it to continue powering our services.</p> </blockquote> <p>Johan Andersson, CTO at <a href="https://embark.dev">Embark</a>, said:</p> <blockquote> <p>We have been using and relying on <code class="language-plaintext highlighter-rouge">hyper</code> 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!</p> </blockquote> <p>The best way to get started is to check out the <a href="https://hyper.rs/guides/1">guide</a>.</p> <h3 id="stability-here-we-come">Stability here we come</h3> <p>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 <code class="language-plaintext highlighter-rouge">async</code>/<code class="language-plaintext highlighter-rouge">await</code> 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 <a href="https://github.com/hyperium/hyper-util">hyper-util</a>, reqwest, Axum.</p> <p>This release signals some <a href="https://hyper.rs/contrib/vision/#stability-promise">stability</a>. Major versions, like 1.0, are stable for at least 3 years.<sup id="fnref:oops" role="doc-noteref"><a href="#fn:oops" class="footnote" rel="footnote">1</a></sup> We also keep a <a href="https://hyper.rs/contrib/msrv/">MSRV</a> that is at least 6 months old.<sup id="fnref:msrv" role="doc-noteref"><a href="#fn:msrv" class="footnote" rel="footnote">2</a></sup> We’ll add <em>new</em> features, and we still have a couple places to experiment: in the <code class="language-plaintext highlighter-rouge">hyper-util</code> crate, and <code class="language-plaintext highlighter-rouge">hyper_unstable</code> compiler flags.</p> <p>Starting in <a href="https://seanmonstar.com/blog/this-month-in-hyper-march-2023/">v0.14.25</a>, we added a <code class="language-plaintext highlighter-rouge">backports</code> feature which brings the new core APIs to you immediately. Combine that with the <code class="language-plaintext highlighter-rouge">deprecated</code> feature, and you’ll be guided to making your existing code ready for the upgrade to 1.0. Be sure to check out the <a href="https://hyper.rs/guides/1/upgrading">upgrade guide</a>!</p> <h3 id="next">Next</h3> <p>The most immediate next steps are to update the other core parts of the ecosystem that depend on hyper: <a href="https://crates.io/crates/reqwest">reqwest</a>, <a href="https://crates.io/crates/axum">Axum</a>, <a href="https://crates.io/crates/tonic">Tonic</a>. But after that, there’s plenty more to do. You’re welcome to come <a href="https://hyper.rs/contrib/">join us</a>!</p> <h4 id="http3">HTTP/3</h4> <p>I would like this to be <em>my</em> next focus. We’ve been building up the <a href="https://github.com/hyperium/h3"><code class="language-plaintext highlighter-rouge">h3</code></a> crate, and <a href="https://docs.rs/reqwest/latest/reqwest/#unstable-features">reqwest has unstable support</a> 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!</p> <p>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.</p> <h4 id="stabilize-in-curl">Stabilize in curl</h4> <p>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 <a href="https://seanmonstar.com/blog/help-stabilize-hyper-in-curl/">helping to get it over the finish line</a>.</p> <h4 id="middleware">Middleware</h4> <p>There’s some excellent middleware available already in <a href="https://crates.io/crates/tower">tower</a> and <a href="https://crates.io/crates/tower-http">tower-http</a>. 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 <a href="https://crates.io/crates/reqwest">reqwest</a> such that all of its features are middleware you can customize.</p> <h4 id="tracing-and-metrics">Tracing and Metrics</h4> <p>It’s possible to currently get a decent set of logs using <code class="language-plaintext highlighter-rouge">tower_http::trace</code>. It’d be better if you could get more fine-grained traces and metrics. Probably with some stabilized integration with <code class="language-plaintext highlighter-rouge">tracing</code> directly in hyper. Maybe some sort of <code class="language-plaintext highlighter-rouge">hyper-metrics</code>, similar to <a href="https://tokio.rs/blog/2022-02-announcing-tokio-metrics"><code class="language-plaintext highlighter-rouge">tokio-metrics</code></a>.</p> <h4 id="io_uring"><code class="language-plaintext highlighter-rouge">io_uring</code></h4> <p>Part of the reason we made hyper have its own <a href="https://github.com/hyperium/hyper/issues/3110">IO traits</a> 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.</p> <h3 id="thanks">Thanks</h3> <p>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.</p> <p>Thanks to the companies who have sponsored the creation of hyper: <a href="https://aws.amazon.com/">AWS</a>, <a href="https://buoyant.io">Buoyant</a>, <a href="https://mozilla.org">Mozilla</a>, <a href="https://foundation.rust-lang.org/news/announcing-the-rust-foundation-s-2023-fellows/">Rust Foundation</a>, <a href="https://fly.io">Fly.io</a>, <a href="https://embark.dev/">Embark</a> and <a href="https://github.com/sponsors/seanmonstar#sponsors">others</a>.</p> <p>Your company could also become a <a href="https://seanmonstar.com/sponsor">sponsor or get support</a>!</p> <div class="footnotes" role="doc-endnotes"> <ol> <li id="fn:oops" role="doc-endnote"> <p>Besides some correctness mistake that <em>must</em> be fixed ASAP. <a href="#fnref:oops" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> <li id="fn:msrv" role="doc-endnote"> <p>We realize that some users just <em>cannot</em> upgrade that fast, and we care about them. <a href="#fnref:msrv" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> </ol> </div> Wed, 15 Nov 2023 16:44:00 +0000 https://seanmonstar.com/blog/hyper-v1/ https://seanmonstar.com/blog/hyper-v1/ rust hyper open-source http hyper HTTP/2 Rapid Reset Attack: Unaffected <p>Today, the world has been made aware of a potential vulnerability affecting most HTTP/2 implementations, sending a rapid amount of streams and resets.</p> <p>If you use <a href="https://hyper.rs">hyper</a>, even just it’s <code class="language-plaintext highlighter-rouge">h2</code> dependency, you are safe. <strong>hyper is not affected</strong>. Especially if you have <code class="language-plaintext highlighter-rouge">h2</code> v0.3.18 or newer. We manually verified that an example hyper server responds correctly. Big thanks to <a href="https://github.com/Noah-Kennedy">@Noah-Kennedy</a> for all the help.</p> <p>If you want to read more, checkout <a href="https://nvd.nist.gov/vuln/detail/CVE-2023-44487">CVE-2023-44487</a>, or these <a href="https://cloud.google.com/blog/products/identity-security/how-it-works-the-novel-http2-rapid-reset-ddos-attack">other</a> <a href="https://blog.cloudflare.com/technical-breakdown-http2-rapid-reset-ddos-attack/">breakdowns</a>.</p> <p>That’s it!</p> <p>You’re still here. You want to know the “why”?</p> <p>Well, for two main reasons.</p> <p>We added in specific detection of <a href="https://seanmonstar.com/post/715784167270596608/coe-surpise-hyper-cve">this problem back in April</a>. 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?</p> <p>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 <code class="language-plaintext highlighter-rouge">HEADERS</code> 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.</p> <p>So if you’ve upgraded since April, you’re safe. By the way…</p> <p>Handling security by dealing with reports, and working with coordinated disclosures like today are a significant part of maintaining hyper. <strong>If you appreciate that hyper is kept secure</strong>, consider <a href="https://seanmonstar.com/sponsor">sponsoring</a>. Being able to have more support during security disclosures is something that you can setup with me privately.</p> Tue, 10 Oct 2023 15:07:00 +0000 https://seanmonstar.com/blog/hyper-http2-rapid-reset-unaffected/ https://seanmonstar.com/blog/hyper-http2-rapid-reset-unaffected/ rust hyper http2 security Was async fn a mistake? <p>This <a href="https://github.com/rust-lang/rust/pull/115822">stabilization PR for <code class="language-plaintext highlighter-rouge">async fn</code> in traits</a> made me think: was <code class="language-plaintext highlighter-rouge">async fn</code> in Rust a mistake?</p> <p>I mean, <a href="https://twitter.com/seanmonstar/status/1702423803698286951">I dunno</a>. <a href="https://masto.ai/@seanmonstar/111065463310520732">Maybe it wasn’t</a>. But play along for a moment.</p> <p>By the way, I don’t mean that <code class="language-plaintext highlighter-rouge">async</code>/<code class="language-plaintext highlighter-rouge">await</code> in Rust itself is a mistake. That’s a Big Deal. It allows companies to deploy some serious stuff to production. And <code class="language-plaintext highlighter-rouge">async</code> and <code class="language-plaintext highlighter-rouge">await</code> syntax is a huge save. I don’t want to lose that. Writing manual futures and poll functions is megasad.</p> <p>I’m specifically talking about the <code class="language-plaintext highlighter-rouge">async fn</code> sugar. What if we didn’t have it, and instead just returned <code class="language-plaintext highlighter-rouge">impl Future</code>s, and used <code class="language-plaintext highlighter-rouge">async</code> blocks inside the functions?<sup id="fnref:reading" role="doc-noteref"><a href="#fn:reading" class="footnote" rel="footnote">1</a></sup></p> <p>The current <code class="language-plaintext highlighter-rouge">async fn</code> is really nice, if you fit the expected usage. If none of the differences with <code class="language-plaintext highlighter-rouge">impl Future</code> ever cause you problems, then great! But I do run into them. Other people seem to also.</p> <h3 id="whats-so-bad">What’s so bad?</h3> <p>Some of these differences cause problems that don’t have decent solutions. (<a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2021&amp;gist=beb7c7d6f540ca55c7d19795a023cdbe">Do you know the differences?</a>)<sup id="fnref:me" role="doc-noteref"><a href="#fn:me" class="footnote" rel="footnote">2</a></sup> If you have to deal with one of them, suddenly you need to use different syntax.</p> <p>And now, <strong>people need to understand both</strong>. And keep the subtle differences in their head when they read. Does that make things better? Or worse?</p> <p>It’s the only place that has <strong>a magic return type</strong>. It makes lifetimes weird. With <a href="https://ibraheem.ca/posts/extending-the-async-fn-syntax/">suggestions to reign them in</a>. It leads to all sort of proposals about how to customize the return type. <code class="language-plaintext highlighter-rouge">#[require_send]</code>, <code class="language-plaintext highlighter-rouge">async(Send)</code>, <code class="language-plaintext highlighter-rouge">Service::call(): Send</code>, and I’m sure there’s others.<sup id="fnref:rtn" role="doc-noteref"><a href="#fn:rtn" class="footnote" rel="footnote">3</a></sup> I also am thinking about generators and streams, since they could also end up with magic return values.</p> <p>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!<sup id="fnref:for" role="doc-noteref"><a href="#fn:for" class="footnote" rel="footnote">4</a></sup></p> <h3 id="what-if-the-alternative-was-nicer">What if the alternative was nicer?</h3> <p>But I did wonder about this. What if we had the following features ready:</p> <ul> <li><a href="https://rust-lang.github.io/rfcs/2113-dyn-trait-syntax.html#rationale-and-alternatives">Repurpose bare trait syntax</a> to mean <code class="language-plaintext highlighter-rouge">impl Trait</code>. It’s been enough editions, right?</li> <li>Ability to forgo naming an associated type name.</li> <li>Stealing the feature from Scala where functions can <em>equal</em> a single expression.</li> </ul> <p>Then asynchronous functions could look like this:</p> <div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">fn</span> <span class="nf">call</span><span class="p">(</span><span class="o">&amp;</span><span class="k">self</span><span class="p">,</span> <span class="n">req</span><span class="p">:</span> <span class="n">Request</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="n">Future</span><span class="o">&lt;</span><span class="n">Response</span><span class="o">&gt;</span> <span class="o">=</span> <span class="k">async</span> <span class="p">{</span> <span class="c1">// ...</span> <span class="p">}</span> </code></pre></div></div> <p>That’d be a nice improvement.</p> <div class="footnotes" role="doc-endnotes"> <ol> <li id="fn:reading" role="doc-endnote"> <p>Yea, I know, it’s a little more writing. But I am in the <em>optimize-for-reading</em> 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. <a href="#fnref:reading" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> <li id="fn:me" role="doc-endnote"> <p>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: <em>none</em> of the solutions look nice. <a href="#fnref:me" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> <li id="fn:rtn" role="doc-endnote"> <p>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 <code class="language-plaintext highlighter-rouge">I::Iter</code> or <code class="language-plaintext highlighter-rouge">I::into_iter()</code>. And also to consider: Rust’s <a href="https://steveklabnik.com/writing/the-language-strangeness-budget">strangeness budget</a>! <a href="#fnref:rtn" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> <li id="fn:for" role="doc-endnote"> <p>I could see an argument that it’s sort of like <code class="language-plaintext highlighter-rouge">for</code>, <code class="language-plaintext highlighter-rouge">while</code>, and <code class="language-plaintext highlighter-rouge">loop</code>. A more convenient syntax when it works, and you can use the others when you need more control. That argument breaks down when <code class="language-plaintext highlighter-rouge">async fn</code> is part of a trait definition. But anyways, I really just want the less-sugared way to be little nicer. <a href="#fnref:for" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> </ol> </div> Thu, 28 Sep 2023 16:58:00 +0000 https://seanmonstar.com/blog/was-async-fn-a-mistake/ https://seanmonstar.com/blog/was-async-fn-a-mistake/ rust opinion async I'm an independent open source maintainer <p><strong>tl;dr</strong> - I’m independent, <a href="https://seanmonstar.com/sponsor">sponsor</a> me!</p> <p>I’m doing something new. I’m an independent open source maintainer! In the beginning of June, I left my <a href="https://seanmonstar.com/blog/next-up-aws/">position at AWS</a>.<sup id="fnref:aws" role="doc-noteref"><a href="#fn:aws" class="footnote" rel="footnote">1</a></sup></p> <p>I’m still focused on Rust, async, and HTTP stuff. Projects like <a href="https://hyper.rs">hyper</a>, reqwest, h3, tower, and any other new ideas that come along. I just won’t be doing so as an employee.</p> <p>So, then how do I get paid? Let me just clear up a couple ways I’m <strong>not</strong>. I’m not making separate licenses. I’m not charging for features.<sup id="fnref:features" role="doc-noteref"><a href="#fn:features" class="footnote" rel="footnote">2</a></sup> I’m not selling prioritization on roadmaps. Rather, I plan to make maintenance work my primary focus.</p> <p>Maintenance can feel like riding a squared unicycle while juggling water balloons. Some of those balloons are:<sup id="fnref:maintainer" role="doc-noteref"><a href="#fn:maintainer" class="footnote" rel="footnote">3</a></sup></p> <ul> <li>Designing proposals, interviewing users, re-writing those proposals.</li> <li>Coding, coding, coding.</li> <li>Triaging a never-ending supply of issues.</li> <li>Spelunking in ancient code paths to understand and fix weird bugs.</li> <li>Following a proper security policy with responsible disclosure, collaborating privately, and preparing detailed reports.</li> <li>Reviewing pull requests for quality and sticking to the vision, and hopefully teaching potential collaborators.</li> <li>Writing articles and giving talks, as a form of marketing and teaching.</li> <li>Pretending to be a project manager.</li> </ul> <p>It’s a lot of work, <strong>so who would pay for all that?</strong></p> <p>Does your company depend on my work? Become a <a href="https://seanmonstar.com/sponsor">sponsor</a>! Consider it a form of business risk mitigation. You can use <a href="https://github.com/sponsors/seanmonstar">GitHub Sponsors</a> or <a href="https://patreon.com/seanmonstar">Patreon</a>. I can also work with an invoice system, for any requiring that.</p> <p>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 <a href="mailto:[email protected]?subject=Sponsorship">[email protected]</a>.</p> <div class="footnotes" role="doc-endnotes"> <ol> <li id="fn:aws" role="doc-endnote"> <p>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. <a href="#fnref:aws" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> <li id="fn:features" role="doc-endnote"> <p>A win about being independent is that no single company is deciding what features should be added. <a href="#fnref:features" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> <li id="fn:maintainer" role="doc-endnote"> <p>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. <a href="#fnref:maintainer" class="reversefootnote" role="doc-backlink">&#8617;</a></p> </li> </ol> </div> Thu, 27 Jul 2023 15:00:25 +0000 https://seanmonstar.com/blog/independent-open-source-maintainer/ https://seanmonstar.com/blog/independent-open-source-maintainer/ open-source rust hyper career bestof self-employment independent foss