slinger/lib.rs
1#![deny(missing_docs)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc(
4 html_favicon_url = "https://raw.githubusercontent.com/emo-crab/slinger/main/images/logo.svg",
5 html_logo_url = "https://raw.githubusercontent.com/emo-crab/slinger/main/images/screenshot.png"
6)]
7//! [![GitHub]](https://github.com/emo-crab/slinger) [![crates-io]](https://crates.io/crates/slinger) [![docs-rs]](crate)
8//!
9//! [GitHub]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
10//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
11//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
12//!
13//! # slinger (投石器)
14//!
15//! The `slinger` crate provides a convenient, low-level HTTP
16//! [`Client`].
17//!
18//! It handles many of the things that most people just expect an HTTP client
19//! to do for them.
20//!
21//! - Customizable [redirect policy](#redirect-policies)
22//! - HTTP [Proxies](#proxies)
23//! - Uses [TLS](#tls) by default
24//! - Cookies
25//!
26//!
27//! Additional learning resources include:
28//!
29//! - [Slinger Repository Examples](https://github.com/emo-crab/slinger/tree/master/examples)
30//!
31//! ## Making a GET request
32//!
33//! For a single request, you can use the [`get`] shortcut method.
34//!
35//!```rust
36//! async fn run() -> Result<(), Box<dyn std::error::Error>> {
37//! let body = slinger::get("https://httpbin.org/get").await?
38//! .text()?;
39//! println!("body = {body:?}");
40//! Ok(())
41//! }
42//! ```
43//!
44//! **NOTE**: If you plan to perform multiple requests, it is best to create a
45//! [`Client`] and reuse it, taking advantage of keep-alive connection
46//! pooling.
47//!
48//! ## Making POST requests (or setting request bodies)
49//!
50//! There are several ways you can set the body of a request. The basic one is
51//! by using the `body()` method of a [`RequestBuilder`]. This lets you set the
52//! exact raw bytes of what the body should be. It accepts various types,
53//! including `String` and `Vec<u8>`. If you wish to pass a custom
54//! type, you can use the `slinger::Body` constructors.
55//!
56//!```rust
57//! # use slinger::Error;
58//! #
59//! # async fn run() -> Result<(), Error> {
60//! let client = slinger::Client::new();
61//! let res = client.post("http://httpbin.org/post")
62//! .body("the exact body that is sent")
63//! .send().await?;
64//! # Ok(())
65//! # }
66//! ```
67//!
68//! ## Redirect Policies
69//!
70//! By default, a `Client` will automatically handle HTTP redirects, having a
71//! maximum redirect chain of 10 hops. To customize this behavior, a
72//! [`redirect::Policy`][redirect] can be used with a `ClientBuilder`.
73//!
74//! ## Cookies
75//!
76//! The automatic storing and sending of session cookies can be enabled with
77//! the [`cookie_store`][client::ClientBuilder::cookie_store] method on `ClientBuilder`.
78//!
79//! ## Proxies
80//!```rust
81//! async fn run() -> std::result::Result<(), Box<dyn std::error::Error>> {
82//! let proxy = slinger::Proxy::parse("http://user:pass@127.0.0.1:1080").unwrap();
83//! // let proxy = slinger::Proxy::parse("socks5://user:pass@127.0.0.1:1080").unwrap();
84//! let client = slinger::ClientBuilder::new().proxy(proxy).build().unwrap();
85//! let resp = client.get("https://httpbin.org/get").send().await?;
86//! println!("{:?}", resp);
87//! Ok(())
88//! }
89//!```
90//! ## TLS
91//!
92//! A `Client` will use transport layer security (TLS) by default to connect to
93//! HTTPS destinations.
94//!
95//! - Additional server certificates can be configured on a `ClientBuilder`
96//! with the [`tls::Certificate`][Certificate] type.
97//! - Client certificates can be added to a `ClientBuilder` with the
98//! [`tls::Identity`][tls::Identity] type.
99//! - Various parts of TLS can also be configured or even disabled on the
100//! `ClientBuilder`.
101//!
102//! ## Optional Features
103//!
104//! The following are a list of [Cargo features][cargo-features] that can be
105//! enabled or disabled:
106//!
107//! - **charset**: Improved support for decoding text.
108//! - **cookie**: Provides cookie session support.
109//! - **tls**: Provides https support.
110//! - **serde**: Provides serialization and deserialization support.
111//! - **gzip**: Provides response body gzip decompression.
112//!
113mod body;
114mod client;
115mod connector;
116#[cfg(feature = "cookie")]
117mod cookies;
118mod errors;
119mod proxy;
120/// record info
121pub mod record;
122/// Redirect Handling
123pub mod redirect;
124mod request;
125mod response;
126#[cfg(feature = "serde")]
127mod serde_schema;
128mod socket;
129#[cfg(feature = "tls")]
130pub mod tls;
131#[cfg(feature = "tls")]
132pub use tls::Certificate;
133
134pub use body::Body;
135use bytes::Bytes;
136pub use client::{Client, ClientBuilder};
137pub use connector::{Connector, ConnectorBuilder};
138pub use errors::{Error, Result};
139pub use http;
140#[cfg(feature = "serde")]
141pub use http_serde;
142// #[cfg(feature = "tls")]
143// pub use native_tls;
144// #[cfg(feature = "tls")]
145// pub use openssl;
146pub use proxy::Proxy;
147pub use request::{RawRequest, Request, RequestBuilder};
148pub use response::{Response, ResponseBuilder, ResponseConfig};
149pub use socket::Socket;
150#[cfg(feature = "tls")]
151pub use tokio_rustls;
152
153/// Shortcut method to quickly make a `GET` request.
154///
155/// See also the methods on the [`slinger::Response`](./struct.Response.html)
156/// type.
157///
158/// **NOTE**: This function creates a new internal `Client` on each call,
159/// and so should not be used if making many requests. Create a
160/// [`Client`](./struct.Client.html) instead.
161///
162/// # Examples
163///
164/// ```rust
165/// # async fn run() -> Result<(), slinger::Error> {
166/// let body = slinger::get("https://www.rust-lang.org").await?
167/// .text()?;
168/// # Ok(())
169/// # }
170/// ```
171///
172pub async fn get<U>(url: U) -> errors::Result<Response>
173where
174 http::Uri: TryFrom<U>,
175 <http::Uri as TryFrom<U>>::Error: Into<http::Error>,
176{
177 Client::builder().build()?.get(url).send().await
178}
179
180/// Shortcut method to quickly make a `RAW` request.
181///
182/// See also the methods on the [`slinger::Response`](./struct.Response.html)
183/// type.
184///
185/// **NOTE**: This function creates a new internal `Client` on each call,
186/// and so should not be used if making many requests. Create a
187/// [`Client`](./struct.Client.html) instead.
188///
189/// # Examples
190///
191/// ```rust
192/// # async fn run() -> Result<(), slinger::Error> {
193/// let body = slinger::raw("http://httpbin.org","GET /robots HTTP/1.1\r\n\r\n",true).await?
194/// .text()?;
195/// # Ok(())
196/// # }
197/// ```
198///
199pub async fn raw<U, R>(uri: U, raw: R, unsafe_raw: bool) -> errors::Result<Response>
200where
201 Bytes: From<R>,
202 http::Uri: TryFrom<U>,
203 <http::Uri as TryFrom<U>>::Error: Into<http::Error>,
204{
205 Client::builder()
206 .build()?
207 .raw(uri, raw, unsafe_raw)
208 .send()
209 .await
210}
211
212pub(crate) const CR_LF: &[u8] = &[13, 10];
213pub(crate) const SPACE: &[u8] = &[32];
214pub(crate) const COLON_SPACE: &[u8] = &[58, 32];
215
216#[cfg(test)]
217mod tests {
218 #[test]
219 fn it_works() {
220 let result = 2 + 2;
221 assert_eq!(result, 4);
222 }
223}