Loading pageā¦
Rust walkthroughs
Loading pageā¦
http::request::Builder::uri for constructing HTTP requests programmatically?The http::request::Builder::uri method sets the request target (URI) on an HTTP request being constructed through the builder pattern. This method accepts any type that can be converted to Uriāstrings, Uri instances, or Partsāand returns the builder for method chaining. The URI specifies the request target: the path, query string, host, and scheme that together tell the server what resource to act upon. Using the builder pattern separates request construction from request execution, allowing URI configuration to be composed with headers, method, and body before the request is finalized.
use http::request::Builder;
fn basic_uri() -> http::Result<http::Request<()>> {
let request = Builder::new()
.uri("https://example.com/api/users")
.body(())?;
Ok(request)
}The uri method accepts a string that gets parsed into a Uri.
use http::{request::Builder, Method};
fn builder_chaining() -> http::Result<http::Request<String>> {
let request = Builder::new()
.method(Method::POST)
.uri("https://api.example.com/users")
.header("Content-Type", "application/json")
.body(r#"{"name": "Alice"}"#.to_string())?;
Ok(request)
}The builder pattern allows composing URI with method, headers, and body.
use http::Uri;
fn uri_components() {
let uri: Uri = "https://user:pass@example.com:8080/path?query=value#fragment".parse().unwrap();
// URI components:
println!("Scheme: {:?}", uri.scheme()); // Some("https")
println!("Authority: {:?}", uri.authority()); // Some("user:pass@example.com:8080")
println!("Host: {:?}", uri.host()); // Some("example.com")
println!("Port: {:?}", uri.port_u16()); // Some(8080)
println!("Path: {:?}", uri.path()); // "/path"
println!("Query: {:?}", uri.query()); // Some("query=value")
println!("Fragment: {:?}", uri.fragment()); // Some("fragment")
}A URI contains scheme, authority, path, query, and fragment components.
use http::{request::Builder, Uri, uri::Parts};
fn uri_from_parts() -> http::Result<http::Request<()>> {
let mut parts = Parts::default();
parts.scheme = Some(http::uri::Scheme::HTTP);
parts.authority = Some("api.example.com".parse().unwrap());
parts.path_and_query = Some("/users?page=1".parse().unwrap());
let uri = Uri::from_parts(parts)?;
let request = Builder::new()
.uri(uri)
.body(())?;
Ok(request)
}Building URIs from parts allows precise control over each component.
use http::request::Builder;
fn relative_uri() -> http::Result<http::Request<()>> {
// Relative URI (path only)
let request = Builder::new()
.uri("/api/users?id=123")
.body(())?;
// The host must be set separately via Host header
// or through the authority in an absolute URI
Ok(request)
}
fn absolute_uri() -> http::Result<http::Request<()>> {
// Absolute URI includes scheme and authority
let request = Builder::new()
.uri("https://api.example.com/users?id=123")
.body(())?;
// Host is derived from the URI
Ok(request)
}Relative URIs need a host header; absolute URIs include the host.
use http::request::Builder;
fn with_query_string() -> http::Result<http::Request<()>> {
let request = Builder::new()
.uri("/search?q=rust&category=libraries&page=1")
.body(())?;
// Query string is part of the URI
let uri = request.uri();
println!("Path: {}", uri.path()); // "/search"
println!("Query: {:?}", uri.query()); // Some("q=rust&category=libraries&page=1")
Ok(request)
}Query strings are part of the path-and-query component.
use http::request::Builder;
fn dynamic_uri(user_id: u64, action: &str) -> http::Result<http::Request<()>> {
let uri = format!("https://api.example.com/users/{}/{}", user_id, action);
let request = Builder::new()
.uri(&uri)
.body(())?;
Ok(request)
}
fn build_request() -> http::Result<()> {
let request = dynamic_uri(42, "posts")?;
println!("URI: {}", request.uri()); // /users/42/posts
Ok(())
}Dynamic URIs can be constructed using format strings.
use http::request::Builder;
fn encoded_uri() -> http::Result<http::Request<()>> {
// Special characters must be percent-encoded
let search = "hello world";
let encoded = urlencoding::encode(search);
let uri = format!("/search?q={}", encoded);
let request = Builder::new()
.uri(&uri)
.body(())?;
// URI: /search?q=hello%20world
Ok(request)
}Special characters in URIs must be percent-encoded.
use http::{request::Builder, Method};
fn restful_requests() -> http::Result<()> {
// GET request
let get = Builder::new()
.method(Method::GET)
.uri("/api/users")
.body(())?;
// POST request
let post = Builder::new()
.method(Method::POST)
.uri("/api/users")
.body(r#"{"name": "Bob"}"#)?;
// PUT request
let put = Builder::new()
.method(Method::PUT)
.uri("/api/users/42")
.body(r#"{"name": "Robert"}"#)?;
// DELETE request
let delete = Builder::new()
.method(Method::DELETE)
.uri("/api/users/42")
.body(())?;
Ok(())
}URI varies by HTTP method: GET and DELETE use paths; POST and PUT include bodies.
use http::request::Builder;
fn host_from_uri() -> http::Result<http::Request<()>> {
// When using absolute URI
let request = Builder::new()
.uri("https://api.example.com:8080/users")
.body(())?;
// Host can be extracted from URI authority
if let Some(host) = request.uri().host() {
println!("Host: {}", host);
}
// For relative URIs, Host header must be set explicitly
let request2 = Builder::new()
.uri("/users")
.header("Host", "api.example.com")
.body(())?;
Ok(request)
}Absolute URIs provide host information; relative URIs need Host header.
use http::Uri;
fn parse_uri() {
let uri: Uri = "https://example.com/path?query=value".parse().unwrap();
// URI parsing extracts all components
assert_eq!(uri.scheme_str(), Some("https"));
assert_eq!(uri.host(), Some("example.com"));
assert_eq!(uri.path(), "/path");
assert_eq!(uri.query(), Some("query=value"));
}URIs are parsed and validated when set via uri().
use http::request::Builder;
fn path_and_query() -> http::Result<http::Request<()>> {
// Path and query combined
let request = Builder::new()
.uri("/users?active=true")
.body(())?;
let uri = request.uri();
println!("Path: {}", uri.path()); // /users
println!("Query: {:?}", uri.query()); // Some("active=true")
// Access query string parameters
if let Some(query) = uri.query() {
for pair in query.split('&') {
if let Some((key, value)) = pair.split_once('=') {
println!("{} = {}", key, value);
}
}
}
Ok(request)
}The path and query are accessible separately from the URI.
use http::request::Builder;
fn reconstruct_uri() -> http::Result<()> {
let request = Builder::new()
.uri("https://api.example.com:8080/v1/users?page=2&limit=50")
.body(())?;
let uri = request.uri();
// Reconstruct parts
let scheme = uri.scheme_str().unwrap_or("http");
let host = uri.host().unwrap_or("localhost");
let port = uri.port_u16().map(|p| format!(":{}", p)).unwrap_or_default();
let path = uri.path();
let query = uri.query().map(|q| format!("?{}", q)).unwrap_or_default();
let full_url = format!("{}://{}{}{}{}", scheme, host, port, path, query);
println!("Full URL: {}", full_url);
Ok(())
}URI components can be extracted and reconstructed.
use http::request::Builder;
fn invalid_uri_handling() {
// Invalid URI characters
let result = Builder::new()
.uri("/path with spaces") // Spaces are invalid
.body(());
match result {
Ok(_) => println!("Request created"),
Err(e) => println!("Error: {}", e),
}
// Must encode: /path%20with%20spaces
let valid = Builder::new()
.uri("/path%20with%20spaces")
.body(()); // This works
}Invalid URIs cause errors; special characters must be encoded.
use http::request::Builder;
fn builder_reuse() -> http::Result<()> {
// Create base builder
let base = Builder::new()
.header("User-Agent", "MyApp/1.0");
// Clone and modify for different endpoints
let users_request = base.clone()
.uri("/api/users")
.body(())?;
let posts_request = base.clone()
.uri("/api/posts")
.body(())?;
// Note: Builder doesn't implement Copy, only Clone
Ok(())
}Builders can be cloned for reuse with different URIs.
use http::{Uri, uri::Parts};
fn modify_uri() -> http::Result<http::Request<()>> {
let original: Uri = "https://example.com/api/v1/users".parse()?;
// Extract parts
let mut parts: Parts = original.into_parts();
// Modify path
parts.path_and_query = Some("/api/v2/users".parse()?);
// Rebuild URI
let new_uri = Uri::from_parts(parts)?;
let request = http::Request::builder()
.uri(new_uri)
.body(())?;
println!("New URI: {}", request.uri());
Ok(request)
}URIs can be modified by extracting and rebuilding parts.
use http::request::Builder;
// When using with hyper or other HTTP libraries
// the URI is used directly in the request
fn hyper_style_request() -> http::Result<http::Request<String>> {
let request = Builder::new()
.method("POST")
.uri("https://httpbin.org/post")
.header("Content-Type", "application/json")
.body(r#"{"test": "data"}"#.to_string())?;
// This request can be sent via hyper::Client
// The URI determines the destination
Ok(request)
}The http crate integrates with hyper and other HTTP libraries.
use http::{request::Builder, Method, Uri};
struct ApiClient {
base_url: String,
default_headers: Vec<(String, String)>,
}
impl ApiClient {
fn new(base_url: impl Into<String>) -> Self {
Self {
base_url: base_url.into(),
default_headers: Vec::new(),
}
}
fn with_header(mut self, key: &str, value: &str) -> Self {
self.default_headers.push((key.to_string(), value.to_string()));
self
}
fn build_request(
&self,
method: Method,
path: &str,
query: Option<&str>,
) -> http::Result<http::Request<()>> {
let uri = match query {
Some(q) => format!("{}{}?{}", self.base_url, path, q),
None => format!("{}{}", self.base_url, path),
};
let mut builder = Builder::new()
.method(method)
.uri(&uri);
for (key, value) in &self.default_headers {
builder = builder.header(key, value);
}
builder.body(())
}
fn get(&self, path: &str) -> http::Result<http::Request<()>> {
self.build_request(Method::GET, path, None)
}
fn get_with_query(&self, path: &str, query: &str) -> http::Result<http::Request<()>> {
self.build_request(Method::GET, path, Some(query))
}
}
fn api_client_example() -> http::Result<()> {
let client = ApiClient::new("https://api.example.com")
.with_header("Authorization", "Bearer token")
.with_header("Accept", "application/json");
let request = client.get_with_query("/users", "active=true")?;
println!("URI: {}", request.uri());
Ok(())
}API clients compose base URLs with paths and query strings.
use http::request::Builder;
fn paginated_request(base: &str, endpoint: &str, page: u32, per_page: u32) -> http::Result<http::Request<()>> {
let uri = format!("{}{}?page={}&per_page={}", base, endpoint, page, per_page);
Builder::new()
.uri(&uri)
.body(())
}
fn pagination_example() -> http::Result<()> {
let base = "https://api.example.com";
for page in 1..=3 {
let request = paginated_request(base, "/posts", page, 10)?;
println!("Page {}: {}", page, request.uri());
}
Ok(())
}Pagination uses query parameters in the URI.
use http::{request::Builder, Method};
struct ResourcePaths;
impl ResourcePaths {
fn users() -> &'static str {
"/users"
}
fn user(id: u64) -> String {
format!("/users/{}", id)
}
fn user_posts(user_id: u64) -> String {
format!("/users/{}/posts", user_id)
}
fn user_post(user_id: u64, post_id: u64) -> String {
format!("/users/{}/posts/{}", user_id, post_id)
}
}
fn rest_example() -> http::Result<()> {
let base = "https://api.example.com";
// List users
let list = Builder::new()
.method(Method::GET)
.uri(&format!("{}{}", base, ResourcePaths::users()))
.body(())?;
// Get specific user
let get = Builder::new()
.method(Method::GET)
.uri(&format!("{}{}", base, ResourcePaths::user(42)))
.body(())?;
// Get user's posts
let posts = Builder::new()
.method(Method::GET)
.uri(&format!("{}{}", base, ResourcePaths::user_posts(42)))
.body(())?;
Ok(())
}REST APIs use URI paths to represent resource hierarchies.
URI components:
| Component | Example | Purpose |
|-----------|---------|---------|
| Scheme | https | Protocol |
| Authority | user:pass@host:port | Destination |
| Host | api.example.com | Server address |
| Port | 8080 | Server port |
| Path | /users/42 | Resource path |
| Query | ?page=1&limit=10 | Parameters |
| Fragment | #section | Page anchor |
Builder chain order:
Builder::new()
.method(Method::POST) // HTTP method
.uri("/api/users") // Request target
.header("Content-Type", "application/json") // Headers
.body("{}") // Request bodyURI types:
| Type | Example | Use Case |
|------|---------|----------|
| Absolute | https://api.example.com/users | Full URL with authority |
| Relative | /users?id=42 | Path with Host header |
| Asterisk | * | OPTIONS requests |
Key insight: http::request::Builder::uri sets the request target through the builder pattern, accepting any type convertible to Uri (strings, Uri instances, or Parts). The URI specifies where the request should be sent: scheme, host, port, path, and query string. When using absolute URIs, the host is derived from the URI; when using relative URIs, the Host header must be set separately. The builder pattern allows URI configuration to compose with method, headers, and body, creating requests declaratively before execution. For API clients, the URI typically combines a base URL with endpoint paths and query parameters, enabling reusable request construction patterns that separate URL building from request handling.