Skip to main content

http_unix_client/
lib.rs

1#![deny(missing_docs)]
2#![deny(missing_debug_implementations)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![cfg_attr(not(test), warn(unused_crate_dependencies))]
5#![cfg_attr(test, deny(warnings))]
6
7//! # http-unix-client
8//!
9//! An HTTP client for interacting with HTTP servers over Unix sockets.
10//! The crate mimics the architecture of the [reqwest](https://docs.rs/reqwest/latest/reqwest/) crate.
11//! The [`Client`] is asynchronous (requiring Tokio).
12//!
13//! ## Supported Platforms
14//!
15//! This crate is only supported on Unix-like systems (Linux, macOS, BSD, etc.) because it relies on Unix domain sockets.
16//!
17//! ## Examples
18//!
19//! ### Making a GET request
20//!
21//! For a single request, you can use the [`get`] shortcut method.
22//!
23//! ```rust
24//! # use http_unix_client::{Client, Error, get};
25//! #
26//! # async fn run() -> Result<(), Error> {
27//! let body = get("/tmp/my.socket", "/health")
28//!     .await?
29//!     .text()
30//!     .await?;
31//!
32//! println!("body = {body:?}");
33//! #   Ok(())
34//! # }
35//! ```
36//!
37//! **NOTE**: If you plan to perform multiple requests, it is best to create a
38//! [`Client`] and reuse it, taking advantage of keep-alive connection
39//! pooling.
40//!
41//! ## Making POST requests (or setting request bodies)
42//!
43//! There are several ways you can set the body of a request. The basic one is
44//! by using the `body()` method of a [`RequestBuilder`]. This lets you set the
45//! exact raw bytes of what the body should be. It accepts various types,
46//! including `String` and `Vec<u8>`. If you wish to pass a custom
47//! type, you can use the `reqwest::Body` constructors.
48//!
49//! ```rust
50//! # use http_unix_client::{Client, Error};
51//!
52//! # async fn run() -> Result<(), Error> {
53//! let client = Client::new();
54//! let res = client.post("/tmp/my.socket", "/health")
55//!     .body("the exact body that is sent")
56//!     .send()
57//!     .await?;
58//! #   Ok(())
59//! # }
60//! ```
61//!
62//! ### Forms
63//!
64//! It's very common to want to send form data in a request body. This can be
65//! done with any type that can be serialized into form data.
66//!
67//! This can be an array of tuples, or a `HashMap`, or a custom type that
68//! implements [`Serialize`][serde].
69//!
70//! ```no_run
71//! # use http_unix_client::{Client, Error};
72//! #
73//! # async fn run() -> Result<(), Error> {
74//! // This will POST a body of `foo=bar&baz=quux`
75//! let params = [("foo", "bar"), ("baz", "quux")];
76//! let client = Client::new();
77//! let res = client.post("/tmp/my.socket", "/health")
78//!     .form(&params)
79//!     .send()
80//!     .await?;
81//!     Ok(())
82//! }
83//! ```
84//!
85//! ### JSON
86//!
87//! There is also a `json` method helper on the [`RequestBuilder`] that works in
88//! a similar fashion the `form` method. It can take any value that can be
89//! serialized into JSON. The feature `json` is required.
90//!
91//! ```rust
92//! # use http_unix_client::{Client, Error};
93//! # use std::collections::HashMap;
94//! #
95//! # #[cfg(feature = "json")]
96//! # async fn run() -> Result<(), Error> {
97//! // This will POST a body of `{"lang":"rust","body":"json"}`
98//! let mut map = HashMap::new();
99//! map.insert("lang", "rust");
100//! map.insert("body", "json");
101//! let client = Client::new();
102//! let res = client.post("/tmp/my.socket", "/health")
103//!     .json(&map)
104//!     .send()
105//!     .await?;
106//! #   Ok(())
107//! # }
108//! ```
109
110mod body;
111mod client;
112mod error;
113mod request;
114mod response;
115mod unix_url;
116
117pub use body::Body;
118pub use client::Client;
119#[cfg(feature = "cookies")]
120pub use cookie::Cookie;
121pub use error::{Error, Result};
122pub use http::{Extensions, Method, StatusCode, Uri, Version, header};
123pub use request::{Request, RequestBuilder};
124pub use response::Response;
125pub use unix_url::UnixUrl;
126pub use url::Url;
127
128/// Shortcut method to quickly make a `GET` request.
129///
130/// See also the methods on the [`Response`]
131/// type.
132///
133/// **NOTE**: This function creates a new internal `Client` on each call,
134/// and so should not be used if making many requests. Create a
135/// [`Client`] instead.
136///
137/// # Examples
138///
139/// ```rust
140/// # use http_unix_client::Error;
141///
142/// # async fn run() -> Result<(), Error> {
143/// let body = http_unix_client::get("/tmp/my.socket", "/").await?
144///     .text().await?;
145/// # Ok(())
146/// # }
147/// ```
148///
149/// # Errors
150///
151/// This function fails if:
152///
153/// - supplied `path` cannot be parsed to an url
154/// - there was an error while sending request
155pub async fn get<P>(socket: P, path: &str) -> crate::Result<Response>
156where
157    P: AsRef<std::path::Path>,
158{
159    Client::new().get(socket, path).send().await
160}