<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rogério Araújo</title>
    <description>The latest articles on DEV Community by Rogério Araújo (@rogrio_arajo_55dae16f0d).</description>
    <link>https://dev.to/rogrio_arajo_55dae16f0d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1924247%2F9075c079-ba58-4ba0-b66a-af01bf383196.jpeg</url>
      <title>DEV Community: Rogério Araújo</title>
      <link>https://dev.to/rogrio_arajo_55dae16f0d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rogrio_arajo_55dae16f0d"/>
    <language>en</language>
    <item>
      <title>API testing with EasyHttpMock</title>
      <dc:creator>Rogério Araújo</dc:creator>
      <pubDate>Mon, 06 Jul 2026 17:30:12 +0000</pubDate>
      <link>https://dev.to/rogrio_arajo_55dae16f0d/api-testing-with-easyhttpmock-4dko</link>
      <guid>https://dev.to/rogrio_arajo_55dae16f0d/api-testing-with-easyhttpmock-4dko</guid>
      <description>&lt;h2&gt;
  
  
  What is EasyHttpMock?
&lt;/h2&gt;

&lt;p&gt;EasyHttpMock is a HTTP server mocking framework, with EasyHttpMock, you can easily define how your app should react to a client request, mainly by define a set of expectations on top of request method, uri and its payload.&lt;/p&gt;

&lt;h2&gt;
  
  
  How EasyHttpMock used to work
&lt;/h2&gt;

&lt;p&gt;EasyHttpMock started with a very naive approach, by simply being a wrapper around a basic http server which do some assertions inside on its request handler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;tls_server_config&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nd"&gt;#[allow(unused_must_use)]&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="nf"&gt;.method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"GET"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="nf"&gt;.uri&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"/posts/1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;make_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b"Hello World!"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;make_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NOT_FOUND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b"Not found"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="nf"&gt;.unwrap_or_else&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to start mock server: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After sometime taking advantage of this approach, I realized the time spending on setup handlers for each test I do was taking a lot of my time when writing project integration tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  How EastHttpMock works today?
&lt;/h2&gt;

&lt;p&gt;With reusability in mind, I started refactoring code to make API easy to undertand and highly composable.&lt;/p&gt;

&lt;p&gt;It’s very intuitive API, allows developers to quickly create a mock and how a request should be validated, alongside how a response should be returned to client.&lt;/p&gt;

&lt;p&gt;Now, your http server mock can be started like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;EasyHttpMockConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VetisAdapter&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;EasyHttpMock&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/test"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="nf"&gt;.will_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nn"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;
            &lt;span class="nf"&gt;.respond&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.with_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"teste"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="nf"&gt;.register_mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  EasyHttpMock design
&lt;/h2&gt;

&lt;p&gt;Diferently from WireMock, EasyHttpMock allows you to use different http server implementations, from HTTP1 to HTTP3, in that case using Vetis as http server.&lt;/p&gt;

&lt;p&gt;By taking advantage of adapter API, EasyHttpMock can work on top of many http server implementations, for now, Vetis Smol and Vetis Tokio are available as choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  A handy set of matchers for mock creation
&lt;/h2&gt;

&lt;p&gt;EasyHttpMock comes with a basic set of matchers, which includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;path (partial, exact match)&lt;/li&gt;
&lt;li&gt;method&lt;/li&gt;
&lt;li&gt;body (exact match, partial with json path or xpath)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and many others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caramelo, a EasyHttpMock best friend
&lt;/h2&gt;

&lt;p&gt;All matchers provided by EasyHttpMock are written on top of Caramelo matcher api, by understanding matcher api, you can also add your own matchers to make even more easier to write mock servers!&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;With this article, you could go over the history behind EasyHttpMock, his motivations, how it compares to WireMock and were our mock api shines!&lt;/p&gt;

&lt;p&gt;I strongly recommend you visit &lt;a href="https://github.com/ararog/easyhttpmock" rel="noopener noreferrer"&gt;https://github.com/ararog/easyhttpmock&lt;/a&gt; to know more about EasyHttpMock and its features!&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>rust</category>
      <category>development</category>
    </item>
    <item>
      <title>🚀 Vetis: a very tiny, very fast HTTP server in Rust</title>
      <dc:creator>Rogério Araújo</dc:creator>
      <pubDate>Fri, 23 Jan 2026 21:36:32 +0000</pubDate>
      <link>https://dev.to/rogrio_arajo_55dae16f0d/vetis-a-very-tiny-very-fast-http-server-in-rust-1ldn</link>
      <guid>https://dev.to/rogrio_arajo_55dae16f0d/vetis-a-very-tiny-very-fast-http-server-in-rust-1ldn</guid>
      <description>&lt;p&gt;If you like &lt;strong&gt;small, fast, no-magic&lt;/strong&gt; tools, you’re going to enjoy &lt;strong&gt;Vetis&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vetis&lt;/strong&gt; is a minimalist HTTP server written in Rust, created by &lt;a href="https://github.com/ararog" rel="noopener noreferrer"&gt;ararog&lt;/a&gt;. It focuses on &lt;strong&gt;performance, simplicity, and modern HTTP support&lt;/strong&gt;, without trying to be a full web framework.&lt;/p&gt;

&lt;p&gt;👉 Repo: &lt;a href="https://github.com/ararog/vetis" rel="noopener noreferrer"&gt;https://github.com/ararog/vetis&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 What is Vetis?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Vetis&lt;/strong&gt; (short for &lt;em&gt;Very Tiny Server&lt;/em&gt;) is an async HTTP server designed to do one thing really well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Serve HTTP efficiently, with as little overhead as possible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of providing routing DSLs, middleware stacks, or heavy abstractions, Vetis gives you a &lt;strong&gt;clean and explicit server core&lt;/strong&gt; that you can shape to your needs.&lt;/p&gt;

&lt;p&gt;It’s a great fit for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lightweight APIs
&lt;/li&gt;
&lt;li&gt;Microservices
&lt;/li&gt;
&lt;li&gt;High-performance networking tools
&lt;/li&gt;
&lt;li&gt;Learning how modern Rust HTTP servers work
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✨ Why Vetis exists
&lt;/h2&gt;

&lt;p&gt;The Rust ecosystem has amazing web frameworks (Axum, Actix, Warp…), but sometimes you don’t want &lt;em&gt;everything&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Vetis is for when you want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧠 Full control
&lt;/li&gt;
&lt;li&gt;⚡ Minimal overhead
&lt;/li&gt;
&lt;li&gt;🦀 Idiomatic async Rust
&lt;/li&gt;
&lt;li&gt;🌐 Modern HTTP protocols
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No surprises. No hidden macros. Just Rust.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔥 Key Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚡ Performance-first design
&lt;/h3&gt;

&lt;p&gt;Vetis keeps the API surface small and avoids unnecessary abstractions. That means less overhead and more predictable performance — especially useful for latency-sensitive workloads.&lt;/p&gt;




&lt;h3&gt;
  
  
  🌐 Modern HTTP support
&lt;/h3&gt;

&lt;p&gt;Via feature flags, Vetis supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HTTP/1&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP/2&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP/3 (QUIC)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔌 Runtime flexibility
&lt;/h3&gt;

&lt;p&gt;Vetis doesn’t lock you into a single async runtime. You can run it on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tokio&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smol&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧪 Small and readable API
&lt;/h3&gt;

&lt;p&gt;Vetis favors explicit code over clever abstractions. If you enjoy reading and understanding your server code, you’ll feel at home here.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 A minimal Vetis server
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;clap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;http_body_util&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Full&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;hyper&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;vetis&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nn"&gt;server&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;config&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ServerConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Vetis&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ServerConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.interface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="py"&gt;.interface&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.port&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="py"&gt;.port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vetis&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;server&lt;/span&gt;
        &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Full&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="nf"&gt;.stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📦 Getting started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;vetis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"tokio-rt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"http2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"tokio-rust-tls"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛠 Open source &amp;amp; contributions
&lt;/h2&gt;

&lt;p&gt;Vetis is released under the &lt;strong&gt;MIT License&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/ararog/vetis" rel="noopener noreferrer"&gt;https://github.com/ararog/vetis&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 Final thoughts
&lt;/h2&gt;

&lt;p&gt;Vetis is perfect when you want &lt;strong&gt;speed, control, and simplicity&lt;/strong&gt; — nothing more, nothing less.&lt;/p&gt;

&lt;p&gt;Happy hacking 🦀&lt;/p&gt;

</description>
      <category>performance</category>
      <category>rust</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Real-time Communication with WebSockets using deboa-extras</title>
      <dc:creator>Rogério Araújo</dc:creator>
      <pubDate>Wed, 03 Dec 2025 14:10:31 +0000</pubDate>
      <link>https://dev.to/rogrio_arajo_55dae16f0d/real-time-communication-with-websockets-using-deboa-extras-172o</link>
      <guid>https://dev.to/rogrio_arajo_55dae16f0d/real-time-communication-with-websockets-using-deboa-extras-172o</guid>
      <description>&lt;p&gt;WebSockets provide a powerful way to enable real-time, bidirectional communication between clients and servers. In this article, we'll explore how to implement WebSocket clients using the &lt;code&gt;deboa-extras&lt;/code&gt; crate, a lightweight and flexible HTTP client library for Rust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to deboa-extras WebSocket Support
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;deboa-extras&lt;/code&gt; crate extends the core &lt;code&gt;deboa&lt;/code&gt; HTTP client with WebSocket capabilities, making it easy to establish WebSocket connections and exchange messages in real-time. It's built on top of the &lt;code&gt;hyper&lt;/code&gt; library and provides an ergonomic API for WebSocket communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Your Project
&lt;/h2&gt;

&lt;p&gt;First, add the necessary dependencies to your &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;deboa&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.0.9"&lt;/span&gt;
&lt;span class="py"&gt;deboa-extras&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.0.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"websockets"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;tokio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"full"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Establishing a WebSocket Connection
&lt;/h2&gt;

&lt;p&gt;To create a WebSocket connection, you'll use the &lt;code&gt;WebsocketRequestBuilder&lt;/code&gt; trait:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;request&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DeboaRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa_extras&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;
    &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DeboaWebSocket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;request&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WebsocketRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;response&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;IntoWebSocket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a WebSocket connection&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;DeboaRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;websocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wss://echo.websocket.org"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.send_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.into_websocket&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Now you can send and receive messages&lt;/span&gt;
    &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.send_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, WebSocket!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.read_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received binary data: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connection closed: {} - {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// Handle other message types if needed&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sending and Receiving Messages
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;DeboaWebSocket&lt;/code&gt; trait provides several methods for different types of messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Send a text message&lt;/span&gt;
&lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.send_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, WebSocket!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Send binary data&lt;/span&gt;
&lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.send_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x03&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Send a ping&lt;/span&gt;
&lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.send_ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"ping"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Close the connection&lt;/span&gt;
&lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.send_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Normal closure"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling Incoming Messages
&lt;/h2&gt;

&lt;p&gt;To handle incoming messages, you'll typically use a loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.read_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received text: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// Echo back the message&lt;/span&gt;
            &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.send_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You said: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received binary data: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received ping, sending pong"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.send_pong&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connection closed: {} - {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connection closed by server"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// Handle other message types&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error Handling
&lt;/h2&gt;

&lt;p&gt;The WebSocket implementation in deboa-extras provides detailed error handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.read_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handle message&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;DeboaExtrasError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;WebSocketError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SendMessage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to send message: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nn"&gt;DeboaExtrasError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;WebSocketError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ReceiveMessage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to receive message: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unexpected error: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// Handle other cases&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building a Simple Chat Application
&lt;/h2&gt;

&lt;p&gt;Let's create a simple chat client that connects to a WebSocket server and echoes messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;request&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DeboaRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa_extras&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;
    &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DeboaWebSocket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;request&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WebsocketRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;response&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;IntoWebSocket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AsyncBufReadExt&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connecting to WebSocket server..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;DeboaRequestBuilder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;websocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wss://echo.websocket.org"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.send_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.into_websocket&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connected! Type a message and press Enter to send. Type 'exit' to quit."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;BufReader&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.lines&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;select!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Read from stdin&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="nf"&gt;.next_line&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"exit"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.send_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"User requested close"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="nf"&gt;.trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.send_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="c1"&gt;// Read from WebSocket&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;websocket&lt;/span&gt;&lt;span class="nf"&gt;.read_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server closed connection: {} - {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connection closed by server"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error reading message: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// Ignore other message types&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Disconnected"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling&lt;/strong&gt;: Always handle potential errors when sending and receiving messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection Management&lt;/strong&gt;: Implement proper connection handling with reconnection logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Framing&lt;/strong&gt;: Be aware of message size limits and implement fragmentation if needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Cleanup&lt;/strong&gt;: Always close the WebSocket connection properly when done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt;: Use &lt;code&gt;tokio::select!&lt;/code&gt; to handle multiple asynchronous operations concurrently.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;deboa-extras&lt;/code&gt; crate provides a simple yet powerful way to work with WebSockets in Rust. With its intuitive API and support for different message types, you can easily build real-time applications that require bidirectional communication.&lt;/p&gt;

&lt;p&gt;Whether you're building a chat application, a real-time dashboard, or any other application that requires real-time updates, &lt;code&gt;deboa-extras&lt;/code&gt; has you covered with its WebSocket support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Explore more advanced features like message compression&lt;/li&gt;
&lt;li&gt;Implement custom serialization for complex message types&lt;/li&gt;
&lt;li&gt;Add authentication to your WebSocket connections&lt;/li&gt;
&lt;li&gt;Handle network interruptions and implement reconnection logic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Happy coding with WebSockets and deboa-extras!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>websockets</category>
    </item>
    <item>
      <title>⚡ JSON vs. Apache Fory: Choosing Your Data Serialization Powerhouse</title>
      <dc:creator>Rogério Araújo</dc:creator>
      <pubDate>Sun, 30 Nov 2025 16:58:20 +0000</pubDate>
      <link>https://dev.to/rogrio_arajo_55dae16f0d/json-vs-apache-fory-choosing-your-data-serialization-powerhouse-2hja</link>
      <guid>https://dev.to/rogrio_arajo_55dae16f0d/json-vs-apache-fory-choosing-your-data-serialization-powerhouse-2hja</guid>
      <description>&lt;p&gt;In today's interconnected world, efficiently moving data between services and systems is crucial. Two major players in the data serialization game are &lt;strong&gt;JSON (JavaScript Object Notation)&lt;/strong&gt; and the high-performance contender, &lt;strong&gt;Apache Fory&lt;/strong&gt; (formerly known as Apache Fury). While JSON dominates the web and APIs due to its simplicity and readability, Apache Fory steps in where speed, size, and advanced features are paramount.&lt;/p&gt;

&lt;p&gt;Which one is right for your project? Let's break down the key differences.&lt;/p&gt;




&lt;h3&gt;
  
  
  📝 JSON: The Readable, Universal Standard
&lt;/h3&gt;

&lt;p&gt;JSON is a &lt;strong&gt;text-based&lt;/strong&gt; data format that has become the de-facto standard for data exchange on the web.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Characteristics of JSON
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Human-Readable:&lt;/strong&gt; JSON's text format, using clear key-value pairs and common symbols (like &lt;code&gt;{}&lt;/code&gt;, &lt;code&gt;[]&lt;/code&gt;, and &lt;code&gt;""&lt;/code&gt;), makes it easy for developers to read, write, and debug data without special tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Widespread Adoption:&lt;/strong&gt; Virtually every programming language, system, and framework has built-in support for parsing and generating JSON. This makes it incredibly &lt;strong&gt;language-agnostic&lt;/strong&gt; and easy to integrate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility (Schema-less):&lt;/strong&gt; JSON doesn't strictly enforce a pre-defined schema, allowing for quick changes and flexibility in data structure, which is great for fast development or systems where the data structure evolves frequently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Trade-offs:&lt;/strong&gt; Being a text-based format means it has overhead. Serialization and deserialization can be &lt;strong&gt;slower&lt;/strong&gt; than binary formats, and the resulting file size is typically &lt;strong&gt;larger&lt;/strong&gt; (more bandwidth and storage consumed). &lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🚀 Apache Fory: The Blazing-Fast, Feature-Rich Binary Format
&lt;/h3&gt;

&lt;p&gt;Apache Fory is a &lt;strong&gt;blazingly-fast, multi-language serialization framework&lt;/strong&gt; designed for high-performance and distributed systems. It’s a modern binary format focused on optimizing serialization for speed and size.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Characteristics of Apache Fory
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Binary and Compact:&lt;/strong&gt; Fory serializes data into a compact &lt;strong&gt;binary protocol&lt;/strong&gt;, resulting in significantly smaller data sizes (often leading to a 50% or more reduction compared to JSON) and faster network transfer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ultra-Fast Performance:&lt;/strong&gt; Leveraging Just-In-Time (JIT) compilation and &lt;strong&gt;zero-copy techniques&lt;/strong&gt;, Fory offers a massive performance boost, with benchmarks often showing 10x to 20x faster serialization/deserialization speeds than JSON or even other binary formats like Protocol Buffers in specific scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced Features:&lt;/strong&gt; Fory supports complex object-oriented features that are difficult or impossible to handle cleanly in JSON, such as:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Polymorphism:&lt;/strong&gt; Serializing objects with their actual runtime types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference Preservation:&lt;/strong&gt; Correctly handling shared and &lt;strong&gt;circular references&lt;/strong&gt; within an object graph.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cross-Language without IDL:&lt;/strong&gt; Fory simplifies cross-language communication by automatically deriving schema information from your class/struct definitions, eliminating the need to manually write and compile a Domain-Specific Language (DSL) or Interface Definition Language (IDL) file like you would with some other binary formats.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Schema Evolution:&lt;/strong&gt; Fory supports both "Schema Consistent" mode for maximum performance and a "Compatible Mode" that allows for independent schema evolution (adding/removing fields) across different languages without coordinated upgrades.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Not Human-Readable:&lt;/strong&gt; The serialized data is a compressed binary stream, making it unusable for direct human reading or debugging without a deserializer.&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  📊 Direct Comparison: JSON vs. Apache Fory
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;JSON (JavaScript Object Notation)&lt;/th&gt;
&lt;th&gt;Apache Fory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Text-based (human-readable)&lt;/td&gt;
&lt;td&gt;Binary (compact, not human-readable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slower serialization/deserialization&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Ultra-fast&lt;/strong&gt; (JIT, Zero-Copy)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Larger (due to text overhead)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Significantly smaller&lt;/strong&gt; (compact binary)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Use Case&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web APIs, Configuration, Simple Data Exchange, Debugging&lt;/td&gt;
&lt;td&gt;High-Performance Microservices, Distributed Caching, High-Volume Data Pipelines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Schema&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Schema-less (flexible)&lt;/td&gt;
&lt;td&gt;Supports &lt;strong&gt;schema evolution&lt;/strong&gt; and strong type mapping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cross-Language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Universal (supported everywhere)&lt;/td&gt;
&lt;td&gt;Multi-language (Java, Python, Rust, Go, etc.) &lt;strong&gt;without requiring IDL&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Complex Objects&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited support for polymorphism or object references&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Excellent support&lt;/strong&gt; for polymorphism and circular references&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  🎯 When to Choose Which
&lt;/h3&gt;

&lt;p&gt;The choice between JSON and Apache Fory boils down to your project's priorities.&lt;/p&gt;

&lt;h4&gt;
  
  
  ✅ Choose JSON when:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Human Readability is a requirement:&lt;/strong&gt; You need developers or users to easily inspect, debug, or edit the data directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperability is paramount:&lt;/strong&gt; You are building a public-facing API (REST), or exchanging data with a very diverse set of external, general-purpose clients.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data size and speed are not the primary bottleneck:&lt;/strong&gt; The performance hit of text serialization is acceptable for your traffic volume.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ✅ Choose Apache Fory when:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance is critical:&lt;/strong&gt; You need the absolute fastest serialization/deserialization speed for low-latency communication (e.g., RPC calls between microservices).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data size matters:&lt;/strong&gt; You need to minimize network bandwidth or storage costs (e.g., caching or storing large object graphs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You deal with complex object structures:&lt;/strong&gt; You need native support for features like polymorphism or shared/circular references across languages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You have controlled endpoints:&lt;/strong&gt; Both the sender and receiver are internal, controlled systems that can implement the Fory framework.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In many modern architectures, you might even use &lt;strong&gt;both&lt;/strong&gt;: &lt;strong&gt;JSON&lt;/strong&gt; for public-facing web APIs and human-consumption data, and &lt;strong&gt;Apache Fory&lt;/strong&gt; for high-speed, high-volume internal service-to-service communication.&lt;/p&gt;

</description>
      <category>json</category>
      <category>apachefory</category>
    </item>
    <item>
      <title>A Deep Dive into `ararog/uget`: The Modern Command-Line HTTP Client</title>
      <dc:creator>Rogério Araújo</dc:creator>
      <pubDate>Fri, 28 Nov 2025 20:34:07 +0000</pubDate>
      <link>https://dev.to/rogrio_arajo_55dae16f0d/a-deep-dive-into-araroguget-the-modern-command-line-http-client-3ea7</link>
      <guid>https://dev.to/rogrio_arajo_55dae16f0d/a-deep-dive-into-araroguget-the-modern-command-line-http-client-3ea7</guid>
      <description>&lt;p&gt;For developers and command-line enthusiasts, tools like &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;wget&lt;/code&gt; are staples for making HTTP requests and downloading files. However, a new player has emerged, offering a streamlined, modern, and Rust-powered alternative: &lt;strong&gt;&lt;code&gt;uget&lt;/code&gt;&lt;/strong&gt; by developer &lt;code&gt;ararog&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This post focuses specifically on the project found at &lt;strong&gt;&lt;a href="https://github.com/ararog/uget" rel="noopener noreferrer"&gt;https://github.com/ararog/uget&lt;/a&gt;&lt;/strong&gt;, a minimalist command-line HTTP utility.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is &lt;code&gt;ararog/uget&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ararog/uget&lt;/code&gt; is defined as a &lt;strong&gt;modern and straightforward HTTP client for the command line&lt;/strong&gt;. It is a minimal CLI tool designed to simplify interactions with web services, downloads, and data transmission, built entirely using the &lt;strong&gt;Rust&lt;/strong&gt; programming language.&lt;/p&gt;

&lt;p&gt;It is crucial to note that this project is distinct from the long-standing, cross-platform &lt;strong&gt;uGet Download Manager&lt;/strong&gt; (which often has a graphical user interface and is hosted under the &lt;code&gt;ugetdm&lt;/code&gt; organization). The &lt;code&gt;ararog/uget&lt;/code&gt; project is focused purely on lightweight, developer-centric command-line functionality.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Features for the Modern Developer
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;uget&lt;/code&gt; strips away complexity while retaining essential functionality, making it an excellent choice for scripting, debugging APIs, and simple file transfers. Its feature set is purpose-built for efficiency:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Simplified HTTP Interaction
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;uget&lt;/code&gt; makes common HTTP methods clean and easy to execute. It's built to handle basic GET requests, JSON payloads, and form submissions with minimal boilerplate.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. File Download and Upload Support
&lt;/h3&gt;

&lt;p&gt;As a robust HTTP client, &lt;code&gt;uget&lt;/code&gt; excels at file operations. It allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Download files&lt;/strong&gt; and show a &lt;strong&gt;progress bar&lt;/strong&gt; during the transfer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resume a download&lt;/strong&gt; from where it previously left off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upload files&lt;/strong&gt; using multipart form fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Comprehensive Request Configuration
&lt;/h3&gt;

&lt;p&gt;It provides simple flags for setting up complex requests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easily set custom &lt;strong&gt;headers&lt;/strong&gt; (&lt;code&gt;--header "Content-Type: application/json"&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Specify request &lt;strong&gt;method&lt;/strong&gt; (&lt;code&gt;-m POST&lt;/code&gt;, &lt;code&gt;-m PUT&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Handle various request bodies, including &lt;strong&gt;JSON&lt;/strong&gt; (via stdin) and standard &lt;strong&gt;form fields&lt;/strong&gt; (&lt;code&gt;--field&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Robust Authentication and Security
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;uget&lt;/code&gt; simplifies the common task of securing API calls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bearer Auth:&lt;/strong&gt; Easily pass a token for modern API authentication (&lt;code&gt;--bearer &amp;lt;token&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic Auth:&lt;/strong&gt; Supports standard username and password credentials (&lt;code&gt;--basic &amp;lt;username&amp;gt;:&amp;lt;password&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutual TLS:&lt;/strong&gt; Allows the use of client certificates and private keys for mutual authentication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom CA:&lt;/strong&gt; Supports custom CA certificates for verification, critical when dealing with enterprise or self-signed certificates.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Basic Usage Examples
&lt;/h2&gt;

&lt;p&gt;The tool's command structure is designed for intuitive use, typically following the format: &lt;code&gt;uget &amp;lt;url&amp;gt; &amp;lt;body&amp;gt; [OPTIONS]&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command Example&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Simple GET&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uget https://api.example.com/status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Downloads the resource and prints the response body to &lt;code&gt;stdout&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JSON POST&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uget https://api.example.com/data "{'data': 'new'}"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pipes a JSON payload into &lt;code&gt;uget&lt;/code&gt;, which automatically defaults to a &lt;code&gt;POST&lt;/code&gt; request.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Form POST&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uget https://forms.example.com/submit --field "user=alice" --field "pass=secret"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Submits data as a standard URL-encoded form.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bearer Auth&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uget https://api.example.com/profile -m GET --bearer &amp;lt;YOUR_TOKEN&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Performs a secure GET request using a Bearer token.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uget https://cdn.example.com/file.zip &amp;gt; file.zip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Downloads the file and redirects the output to save it locally.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Why Choose &lt;code&gt;ararog/uget&lt;/code&gt;?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Rust Performance:&lt;/strong&gt; Being built in Rust, &lt;code&gt;uget&lt;/code&gt; offers the benefits of &lt;strong&gt;memory safety&lt;/strong&gt; and &lt;strong&gt;high performance&lt;/strong&gt;, often outperforming utilities written in interpreted languages.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Modern Syntax:&lt;/strong&gt; Its flags and usage patterns are streamlined for today's API-centric development workflows, making it a highly readable and easy-to-script tool.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Minimalist Focus:&lt;/strong&gt; It does one thing—handle HTTP—and does it well, avoiding bloat and unnecessary complexity.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are looking for a fast, simple, and reliable CLI tool to manage your HTTP requests, &lt;code&gt;ararog/uget&lt;/code&gt; is definitely a repository worth starring and integrating into your workflow.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>cli</category>
      <category>network</category>
      <category>rust</category>
    </item>
    <item>
      <title>🦀 Reqwest vs. Deboa: Which Rust HTTP Client is Right for Your Project?</title>
      <dc:creator>Rogério Araújo</dc:creator>
      <pubDate>Fri, 28 Nov 2025 19:55:22 +0000</pubDate>
      <link>https://dev.to/rogrio_arajo_55dae16f0d/comparing-deboa-and-reqwest-two-rust-http-clients-in-2025-ooa</link>
      <guid>https://dev.to/rogrio_arajo_55dae16f0d/comparing-deboa-and-reqwest-two-rust-http-clients-in-2025-ooa</guid>
      <description>&lt;p&gt;When building modern applications in &lt;strong&gt;Rust&lt;/strong&gt;, an efficient and reliable &lt;strong&gt;HTTP client&lt;/strong&gt; is essential. Two popular choices in the Rust ecosystem are &lt;strong&gt;&lt;code&gt;reqwest&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;deboa&lt;/code&gt;&lt;/strong&gt;. While &lt;code&gt;reqwest&lt;/code&gt; is the long-standing, feature-rich powerhouse, &lt;code&gt;deboa&lt;/code&gt; is emerging as a compelling, lightweight alternative.&lt;/p&gt;

&lt;p&gt;This post dives into their key differences, with a focus on &lt;strong&gt;performance&lt;/strong&gt; and suitability for different use cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Core Philosophy and Design
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Reqwest: The Feature-Rich Standard
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;reqwest&lt;/code&gt;&lt;/strong&gt; is often considered the de-facto standard for asynchronous HTTP requests in Rust. It's built on top of the powerful &lt;code&gt;hyper&lt;/code&gt; library, which provides the underlying HTTP implementation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key Design:&lt;/strong&gt; A high-level, easy-to-use API that provides both &lt;strong&gt;blocking&lt;/strong&gt; and &lt;strong&gt;asynchronous&lt;/strong&gt; modes. It's designed for completeness, offering extensive features like JSON serialization/deserialization, redirects, cookie handling, and support for both &lt;code&gt;native-tls&lt;/code&gt; and &lt;code&gt;rustls&lt;/code&gt; for TLS connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency Footprint:&lt;/strong&gt; Due to its broad feature set and the use of &lt;code&gt;hyper&lt;/code&gt; and an asynchronous runtime like &lt;code&gt;tokio&lt;/code&gt; (or &lt;code&gt;async-std&lt;/code&gt;), &lt;code&gt;reqwest&lt;/code&gt; can have a &lt;strong&gt;larger dependency tree&lt;/strong&gt; and a &lt;strong&gt;greater compiled binary size&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deboa: The Lightweight and Flexible Contender
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;deboa&lt;/code&gt;&lt;/strong&gt; is a more recent and developer-centric HTTP client. The name, which means "I'm ok" in Portuguese, suggests its focus on straightforward usability and efficiency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key Design:&lt;/strong&gt; A straightforward, non-opinionated, and highly flexible client, also built on &lt;code&gt;hyper&lt;/code&gt;. It aims to provide essential modern features—including flexible authentication, serialization (JSON, XML, MsgPack), and middleware support—while maintaining &lt;strong&gt;simplicity and a lighter touch&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency Footprint:&lt;/strong&gt; &lt;code&gt;deboa&lt;/code&gt; positions itself as a more &lt;strong&gt;lightweight&lt;/strong&gt; alternative. It's especially suited for projects where smaller binary size or a more focused feature set is a priority. It offers compatibility with various runtimes (&lt;code&gt;tokio&lt;/code&gt;, &lt;code&gt;smol&lt;/code&gt;) and pluggable features.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Performance and Binary Size Comparison
&lt;/h2&gt;

&lt;p&gt;Direct, head-to-head performance benchmarks between &lt;code&gt;reqwest&lt;/code&gt; and &lt;code&gt;deboa&lt;/code&gt; are difficult to find, as performance is often heavily influenced by configuration and workload. However, we can analyze the common trade-offs.&lt;/p&gt;

&lt;h3&gt;
  
  
  📊 Performance Factors
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;code&gt;reqwest&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;deboa&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Implication for Performance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Foundation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hyper&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hyper&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Both utilize the high-performance &lt;code&gt;hyper&lt;/code&gt; core.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TLS Backend&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;native-tls&lt;/code&gt; (default) or &lt;code&gt;rustls&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rustls&lt;/code&gt; is common&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Configuration matters greatly.&lt;/strong&gt; &lt;code&gt;reqwest&lt;/code&gt;'s default &lt;code&gt;native-tls&lt;/code&gt; can sometimes be slower for client creation than &lt;code&gt;rustls&lt;/code&gt; (especially without client reuse), but a properly configured &lt;code&gt;reqwest&lt;/code&gt; with &lt;code&gt;rustls-tls&lt;/code&gt; can be very fast.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Client Reuse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Critical&lt;/strong&gt; for performance.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Critical&lt;/strong&gt; for performance.&lt;/td&gt;
&lt;td&gt;Both clients should be instantiated once and reused to avoid the overhead of setting up TLS and connection pooling.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Runtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Heavily integrated with &lt;code&gt;tokio&lt;/code&gt; (though configurable).&lt;/td&gt;
&lt;td&gt;Supports multiple runtimes (&lt;code&gt;tokio&lt;/code&gt;, &lt;code&gt;smol&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;deboa&lt;/code&gt;'s flexibility could be beneficial in environments where a specific runtime other than &lt;code&gt;tokio&lt;/code&gt; is preferred or provides an edge.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  📉 Binary Size
&lt;/h3&gt;

&lt;p&gt;One of the most notable distinctions is in size. &lt;strong&gt;&lt;code&gt;reqwest&lt;/code&gt; is generally heavier&lt;/strong&gt; due to its extensive feature set and dependencies. For projects where &lt;strong&gt;binary size is a critical constraint&lt;/strong&gt; (e.g., small embedded systems or environments with strict deployment limits), &lt;code&gt;deboa&lt;/code&gt; or other specialized, minimalistic clients are often the preferred choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚠️ Caveat on Performance Benchmarks
&lt;/h3&gt;

&lt;p&gt;It's important to note that many reports on &lt;code&gt;reqwest&lt;/code&gt; performance issues (such as inconsistencies or slowness compared to other tools) often trace back to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Not reusing the &lt;code&gt;reqwest::Client&lt;/code&gt;:&lt;/strong&gt; Creating a new client for every request incurs high overhead, especially for TLS handshakes.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Using default features:&lt;/strong&gt; The default &lt;code&gt;native-tls&lt;/code&gt; can be slower than the &lt;code&gt;rustls-tls&lt;/code&gt; feature for client creation time in some contexts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When used correctly, both clients provide high performance, leveraging the efficiency of the &lt;code&gt;hyper&lt;/code&gt; HTTP stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Which Should You Choose?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Choose &lt;code&gt;reqwest&lt;/code&gt; if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You need a complete solution:&lt;/strong&gt; You want a well-established, battle-tested client with a high-level API for nearly every common HTTP use case (forms, redirects, advanced authentication, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You are new to Rust networking:&lt;/strong&gt; Its excellent documentation and large community make it easier to get help and find examples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Binary size is not a primary concern:&lt;/strong&gt; You're building a standard backend service or application where the small size penalty is acceptable for the feature completeness.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choose &lt;code&gt;deboa&lt;/code&gt; if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You prioritize a lightweight binary:&lt;/strong&gt; You want an efficient client with a smaller dependency footprint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need runtime flexibility:&lt;/strong&gt; You are building an application that needs to be compatible with a runtime other than the default &lt;code&gt;tokio&lt;/code&gt; ecosystem, like &lt;code&gt;smol&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You prefer a focused API:&lt;/strong&gt; You want a modern, less-opinionated client that provides core features like pluggable serialization and middleware without the bloat of more niche utilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultimately, both &lt;code&gt;reqwest&lt;/code&gt; and &lt;code&gt;deboa&lt;/code&gt; are excellent choices in the Rust ecosystem. Your decision should be based on your project's specific needs for features, binary size, and required ecosystem integration.&lt;/p&gt;

&lt;p&gt;This video gives a good overview of how to set up &lt;code&gt;reqwest&lt;/code&gt; and use it for basic monitoring tasks. &lt;a href="https://www.youtube.com/watch?v=zmW0jXNJDyM" rel="noopener noreferrer"&gt;Monitoring URLs with Tokio and Reqwest | Rust HTTP Monitor Part 1&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>backend</category>
      <category>restapi</category>
      <category>network</category>
    </item>
    <item>
      <title>Exploring deboa-macros: Ergonomic HTTP Client Macros for Rust</title>
      <dc:creator>Rogério Araújo</dc:creator>
      <pubDate>Fri, 28 Nov 2025 16:52:41 +0000</pubDate>
      <link>https://dev.to/rogrio_arajo_55dae16f0d/exploring-deboa-macros-ergonomic-http-client-macros-for-rust-5ehl</link>
      <guid>https://dev.to/rogrio_arajo_55dae16f0d/exploring-deboa-macros-ergonomic-http-client-macros-for-rust-5ehl</guid>
      <description>&lt;h2&gt;
  
  
  What is &lt;code&gt;deboa-macros&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;deboa-macros&lt;/code&gt; is a procedural-macro crate for Rust that builds on top of the core HTTP client &lt;strong&gt;deboa&lt;/strong&gt;. Its goal is to simplify common HTTP request patterns using expressive macros---turning verbose boilerplate into concise, type-safe code.&lt;/p&gt;

&lt;p&gt;Where &lt;code&gt;deboa&lt;/code&gt; provides low-level HTTP capabilities (HTTP/1 + HTTP/2, async runtimes like Tokio or Smol, etc.), &lt;code&gt;deboa-macros&lt;/code&gt; layers ergonomic syntax on top so you can focus on logic instead of&lt;br&gt;
request-building ceremony.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Macros? --- The Case for &lt;code&gt;deboa-macros&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Rust's &lt;strong&gt;procedural macros&lt;/strong&gt; allow developers to run code at compile time to generate boilerplate, enforce patterns, and create domain-specific syntax.&lt;/p&gt;

&lt;p&gt;For HTTP requests, much of the code is repetitive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  building the request&lt;/li&gt;
&lt;li&gt;  serializing bodies&lt;/li&gt;
&lt;li&gt;  deserializing responses&lt;/li&gt;
&lt;li&gt;  handling errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;deboa-macros&lt;/code&gt; addresses these pain points with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Shorthand macros&lt;/strong&gt; for common HTTP methods (&lt;code&gt;get!&lt;/code&gt;, &lt;code&gt;post!&lt;/code&gt;,
&lt;code&gt;put!&lt;/code&gt;, &lt;code&gt;patch!&lt;/code&gt;, &lt;code&gt;delete!&lt;/code&gt;, &lt;code&gt;fetch!&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Compile-time type safety&lt;/strong&gt; for request/response bodies (via Serde)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Async/await support&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Declarative API client definitions&lt;/strong&gt; using the &lt;code&gt;#[bora]&lt;/code&gt; attribute macro&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a more pleasant, readable workflow---without sacrificing control or safety.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Starting from deboa-macros 0.0.7, bora macro won’t be available on this crate anymore. It has been moved to vamo-macros crate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Features &amp;amp; API Overview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✔ Function-like Macros
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;deboa-macros&lt;/code&gt; provides macros corresponding to HTTP verbs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;get!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;post!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;put!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;patch!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;delete!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;fetch!&lt;/code&gt; (generic method caller)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each macro expands into an async HTTP call using &lt;code&gt;deboa&lt;/code&gt;, with optional body and response type handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ &lt;code&gt;#[bora]&lt;/code&gt; Attribute Macro
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;bora&lt;/code&gt; macro lets you define a high-level API client declaratively.&lt;/p&gt;

&lt;p&gt;You describe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  the endpoints&lt;/li&gt;
&lt;li&gt;  their HTTP methods&lt;/li&gt;
&lt;li&gt;  input parameters&lt;/li&gt;
&lt;li&gt;  response bodies&lt;/li&gt;
&lt;li&gt;  serialization format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The macro generates a fully-typed client struct with async methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Serialization Formats Supported
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  JSON&lt;/li&gt;
&lt;li&gt;  XML&lt;/li&gt;
&lt;li&gt;  MessagePack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All wired through Serde.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example: GET Request Using &lt;code&gt;get!&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa_extras&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;http&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;serde&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JsonBody&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(serde::Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;get!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"https://jsonplaceholder.typicode.com/posts/1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;JsonBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Post&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Post title: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="py"&gt;.title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Example: Declarative API Client with &lt;code&gt;#[bora]&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DeboaError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa_macros&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;bora&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;vamo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Vamo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Deserialize,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[bora(&lt;/span&gt;
    &lt;span class="nd"&gt;api(&lt;/span&gt;
        &lt;span class="nd"&gt;get(name=&lt;/span&gt;&lt;span class="s"&gt;"get_by_id"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"/posts/&amp;lt;id:i32&amp;gt;"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;res_body=Post,&lt;/span&gt; &lt;span class="nd"&gt;format=&lt;/span&gt;&lt;span class="s"&gt;"json"&lt;/span&gt;&lt;span class="nd"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PostService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;DeboaError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vamo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://jsonplaceholder.typicode.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;PostService&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="nf"&gt;.get_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"title: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="py"&gt;.title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When to Use &lt;code&gt;deboa-macros&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Great Fit When:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  You want concise, readable HTTP calls.&lt;/li&gt;
&lt;li&gt;  You prefer declarative API client definitions.&lt;/li&gt;
&lt;li&gt;  You care about type-safe request/response handling.&lt;/li&gt;
&lt;li&gt;  You're working with async Rust.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Consider Using Raw &lt;code&gt;deboa&lt;/code&gt; When:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  You need very fine-grained control over request lifecycle.&lt;/li&gt;
&lt;li&gt;  You need complex middleware or streaming.&lt;/li&gt;
&lt;li&gt;  You prefer explicit, hand-written code over macro-generated abstractions.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Ecosystem Fit
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;deboa-macros&lt;/code&gt; sits on top of a trio of crates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;deboa&lt;/code&gt;&lt;/strong&gt; --- core HTTP client&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;deboa-extras&lt;/code&gt;&lt;/strong&gt; --- additional serialization/compression helpers, websockets, sse and custom middleware (catchers).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;deboa-macros&lt;/code&gt;&lt;/strong&gt; --- ergonomic macros and declarative API definitions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This combination forms a flexible stack for building REST clients in Rust with minimal boilerplate.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Take
&lt;/h2&gt;

&lt;p&gt;As a developer, libraries that reduce boilerplate without hiding&lt;br&gt;
important details are always welcome. &lt;code&gt;deboa-macros&lt;/code&gt; hits that sweet spot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It speeds up API client creation&lt;/li&gt;
&lt;li&gt;  It preserves strong typing&lt;/li&gt;
&lt;li&gt;  It works seamlessly with Rust async and Serde&lt;/li&gt;
&lt;li&gt;  You can still drop down to raw &lt;code&gt;deboa&lt;/code&gt; for advanced behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building internal tools, microservices, or interacting with REST APIs, &lt;code&gt;deboa-macros&lt;/code&gt; is definitely worth trying.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;deboa-macros&lt;/code&gt; brings ergonomic macros, type safety, and readability to HTTP client code in Rust. It builds on &lt;code&gt;deboa&lt;/code&gt;'s solid async foundation to provide high-level, expressive syntax ideal for REST-heavy applications.&lt;/p&gt;

&lt;p&gt;If you enjoy clean, declarative Rust with less boilerplate---and still want full control when needed---this crate is a strong choice.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>backend</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>Vamo, a rest api friendly client</title>
      <dc:creator>Rogério Araújo</dc:creator>
      <pubDate>Wed, 26 Nov 2025 23:44:51 +0000</pubDate>
      <link>https://dev.to/rogrio_arajo_55dae16f0d/vamo-a-rest-api-friend-client-3kgl</link>
      <guid>https://dev.to/rogrio_arajo_55dae16f0d/vamo-a-rest-api-friend-client-3kgl</guid>
      <description>&lt;p&gt;Continuing our series of blog posts about deboa ecosystem, we will now cover Vamo, a rest api client built on top of deboa.&lt;/p&gt;

&lt;p&gt;Despite existing http clients written in rust, deboa comes with this friendly companion crate. Vamo is a very straightforward way to setup your client once with a base url, allowing you issue your requests after by just specifying the path of resource to be requested.&lt;/p&gt;

&lt;h1&gt;
  
  
  Installing
&lt;/h1&gt;

&lt;p&gt;In order to start using vamo in your project, please add vamo into your project with following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cargo add vamo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Initializing client
&lt;/h1&gt;

&lt;p&gt;Initialize vamo client is easy as initialize a deboa client, let's check out the example below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;vamo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Vamo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;vamo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vamo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://api.example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Sending requests
&lt;/h1&gt;

&lt;p&gt;Now that we have vamo client initialized, you can start issuing your requests, don't mind to give full url anymore, just the resource path and you are done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;vamo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Vamo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;vamo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vamo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://api.example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vamo&lt;/span&gt;
    &lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Request trait
&lt;/h1&gt;

&lt;p&gt;Request trait is a experimental feature of vamo crate, with Request trait, you can easily turn any rust struct into a kind self contained request object to be sent over vamo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nn"&gt;client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;serde&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RequestBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;vamo&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Vamo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ResourceMethod&lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa_extras&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;http&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;serde&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JsonBody&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;serde&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Serialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(skip_serializing_if&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Option::is_none"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(skip_serializing_if&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Option::is_none"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Resource&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"posts"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;body_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;RequestBody&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;JsonBody&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;vamo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vamo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://api.example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Assuming Post is a Resource&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Some title"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
     &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Some body"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
     &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vamo&lt;/span&gt;&lt;span class="nf"&gt;.create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please note that you don't need to implement Resource trait manually, in order to make this happen, please check section below.  &lt;/p&gt;

&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;p&gt;As we can see, it is faily simple make requests with vamo, and to make this task even more simplier, a Request trait has been introduced to make every happen straight from your structs. I stronly invite you to also give a try on vamo-macros, which can simply generate a implementation of Request trait for your struct by just annotating your struct with &lt;code&gt;#[derive(Resource)]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can find vamo under deboa repository at &lt;a href="https://github.com/ararog/deboa" rel="noopener noreferrer"&gt;https://github.com/ararog/deboa&lt;/a&gt;, or under creates.io at &lt;a href="https://crates.io/crates/deboa" rel="noopener noreferrer"&gt;https://crates.io/crates/deboa&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A complete documentation is also available at &lt;a href="https://docs.rs/vamo/latest/vamo/" rel="noopener noreferrer"&gt;https://docs.rs/vamo/latest/vamo/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>crates</category>
      <category>backend</category>
      <category>microservices</category>
    </item>
    <item>
      <title>deboa, a simple http client for rust</title>
      <dc:creator>Rogério Araújo</dc:creator>
      <pubDate>Mon, 17 Nov 2025 23:13:46 +0000</pubDate>
      <link>https://dev.to/rogrio_arajo_55dae16f0d/deboa-a-simple-http-client-for-rust-2758</link>
      <guid>https://dev.to/rogrio_arajo_55dae16f0d/deboa-a-simple-http-client-for-rust-2758</guid>
      <description>&lt;p&gt;&lt;a href="https://forem.comurl"&gt;&lt;/a&gt;Few months ago, I started an effort on create a very simple and easy to use http client.&lt;/p&gt;

&lt;p&gt;At first, I just tried to mimic the same approach as apisauce for NodeJS, but that didn’t sound appropriate, so I started to refactor to be more rust friendly lib.&lt;/p&gt;

&lt;p&gt;Once I moved forward with Deboa implementation, I started to brake it down by features, then by separate crates. Nowadays, Deboa is very modular and can take minimal space on final binary size.&lt;/p&gt;

&lt;p&gt;So far, whole Deboa ecosystem is made of following crates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deboa&lt;/li&gt;
&lt;li&gt;deboa-extras&lt;/li&gt;
&lt;li&gt;deboa-macros&lt;/li&gt;
&lt;li&gt;deboa-fory&lt;/li&gt;
&lt;li&gt;vamo&lt;/li&gt;
&lt;li&gt;vamo-macros&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, we will cover Deboa and some of its features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;Right now Deboa has the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tokio-rt&lt;/li&gt;
&lt;li&gt;smol-rt&lt;/li&gt;
&lt;li&gt;http1&lt;/li&gt;
&lt;li&gt;http2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the examples on this post are based on tokio-rt and http1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Deboa to your project
&lt;/h2&gt;

&lt;p&gt;You can easy add Deboa to your rust project using cargo, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo add deboa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Initializing client
&lt;/h2&gt;

&lt;p&gt;Create a new client instance can be simple as call &lt;code&gt;Deboa::new()&lt;/code&gt;, but you can also setup interceptors, protocol to use, among other things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Making requests
&lt;/h2&gt;

&lt;p&gt;You have many ways to create a request within Deboa, the most common way is by initializing DeboaResponse.&lt;/p&gt;

&lt;p&gt;There are several ways to create a instance of DeboaRequest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;by using get, post, delete, put and patch request module functions&lt;/li&gt;
&lt;li&gt;by using FetchWith trait&lt;/li&gt;
&lt;li&gt;by taking advantage of IntoRequest trait&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;
    &lt;span class="n"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;request&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;DeboaRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FetchWith&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://jsonplaceholder.typicode.com/posts"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// process request&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reading responses
&lt;/h2&gt;

&lt;p&gt;Once request is issued with &lt;code&gt;send_with&lt;/code&gt;, &lt;code&gt;fetch_with&lt;/code&gt; or &lt;code&gt;Deboa::execute&lt;/code&gt;, you will have access to DeboaResponse. Within DeboaResponse you can check status_code, cookies, headers and read response body.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;deboa&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;
    &lt;span class="n"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;request&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;DeboaRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FetchWith&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Deboa&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://jsonplaceholder.typicode.com/posts"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;
      &lt;span class="nf"&gt;.send_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
      &lt;span class="nf"&gt;.raw_body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// do something with bytes&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;As we can see, with Deboa you can easily initialize client, customize it, create request in several different ways and read responses in a very feel steps.&lt;/p&gt;

&lt;p&gt;I strongly recommend you to visit deboa repository, try examples, and leave your star if you like it!&lt;/p&gt;

&lt;p&gt;Github: &lt;a href="https://github.com/ararog/deboa" rel="noopener noreferrer"&gt;https://github.com/ararog/deboa&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
