rust
53 lines · 8 steps
The builder pattern in Rust
A RequestBuilder accumulates HTTP request settings through chainable methods before producing a finished Request.
Explained by
highlit
1#[derive(Debug, Default)]
2pub struct RequestBuilder {
3 url: String,
4 method: String,
5 headers: Vec<(String, String)>,
6 body: Option<Vec<u8>>,
7 timeout_ms: u64,
8}
9
10impl RequestBuilder {
11 pub fn new(url: impl Into<String>) -> Self {
12 RequestBuilder {
13 url: url.into(),
14 method: "GET".to_string(),
15 timeout_ms: 30_000,
16 ..Default::default()
17 }
18 }
19
20 pub fn method(&mut self, method: impl Into<String>) -> &mut Self {
21 self.method = method.into();
22 self
23 }
24
25 pub fn header(&mut self, key: impl Into<String>, value: impl Into<String>) -> &mut Self {
26 self.headers.push((key.into(), value.into()));
27 self
28 }
29
30 pub fn bearer(&mut self, token: &str) -> &mut Self {
31 self.header("Authorization", format!("Bearer {token}"))
32 }
33
34 pub fn json(&mut self, payload: &[u8]) -> &mut Self {
35 self.body = Some(payload.to_vec());
36 self.header("Content-Type", "application/json")
37 }
38
39 pub fn timeout_ms(&mut self, ms: u64) -> &mut Self {
40 self.timeout_ms = ms;
41 self
42 }
43
44 pub fn build(&self) -> Request {
45 Request {
46 url: self.url.clone(),
47 method: self.method.clone(),
48 headers: self.headers.clone(),
49 body: self.body.clone(),
50 timeout_ms: self.timeout_ms,
51 }
52 }
53}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Returning &mut Self from each setter lets callers chain configuration calls fluently.
- 2Accepting impl Into<String> makes an API accept both &str and String without forcing conversions on the caller.
- 3A dedicated build step separates the mutable, half-finished builder from the finalized, cloned result.
Related explainers
rust
use serde::Deserialize; #[derive(Debug, Deserialize)] #[serde(untagged)]
Parsing flexible JSON shapes with serde
deserialization
enums
json
Intermediate
6 steps
rust
use std::cmp::{Ordering, Reverse}; use std::collections::BinaryHeap; use std::fs::File; use std::io::{self, BufRead, BufReader, BufWriter, Lines, Write};
K-way merge of sorted logs in Rust
binary-heap
k-way-merge
streaming-io
Intermediate
8 steps
rust
use axum::{ extract::{Path, State}, response::sse::{Event, KeepAlive, Sse}, };
Streaming import progress with SSE in Axum
server-sent-events
streams
watch-channel
Advanced
7 steps
rust
use std::f64::consts::PI; #[derive(Debug, Clone, Copy)] pub struct LatLng {
Building geographic bounding boxes in Rust
geospatial
value-types
option
Intermediate
7 steps
rust
use chrono::{Duration, NaiveDate}; #[derive(Debug)] pub struct DateRange {
Parsing and iterating date ranges in Rust
error-handling
iterators
parsing
Intermediate
7 steps
rust
use std::collections::VecDeque; use std::sync::{Arc, Condvar, Mutex}; use std::time::{Duration, Instant};
Building a counting semaphore in Rust
concurrency
synchronization
condition-variable
Advanced
9 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/the-builder-pattern-in-rust-explained-rust-e649/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.