#![warn(missing_docs)]
pub use auth::{AuthDecision, AuthHandler, AuthParam, AuthTarget, Challenge};
pub use client::{
CacheMode, Client, ClientBuilder, ConnectionPolicy, ParserStrictness, ProxyConfig, Session,
};
pub use errors::NanoGetError;
pub use request::{Header, Method, RedirectPolicy, Request};
pub use response::{HttpVersion, Response};
pub use url::{ToUrl, Url};
mod auth;
mod client;
mod date;
mod errors;
mod http;
#[cfg(feature = "https")]
mod https;
mod request;
mod response;
mod url;
const DEFAULT_REDIRECT_LIMIT: usize = 10;
pub fn get<U: ToUrl>(url: U) -> Result<String, NanoGetError> {
helper_client().get(url)
}
pub fn get_bytes<U: ToUrl>(url: U) -> Result<Vec<u8>, NanoGetError> {
let request =
Request::get(url)?.with_redirect_policy(RedirectPolicy::follow(DEFAULT_REDIRECT_LIMIT));
helper_client()
.execute(request)
.map(|response| response.body)
}
pub fn head<U: ToUrl>(url: U) -> Result<Response, NanoGetError> {
let request =
Request::head(url)?.with_redirect_policy(RedirectPolicy::follow(DEFAULT_REDIRECT_LIMIT));
helper_client().execute(request)
}
pub fn get_http<U: ToUrl>(url: U) -> Result<String, NanoGetError> {
get_http_bytes(url)
.and_then(|body| String::from_utf8(body).map_err(|error| error.utf8_error().into()))
}
pub fn get_http_bytes<U: ToUrl>(url: U) -> Result<Vec<u8>, NanoGetError> {
let request =
Request::get(url)?.with_redirect_policy(RedirectPolicy::follow(DEFAULT_REDIRECT_LIMIT));
if !request.url().is_http() {
return Err(NanoGetError::UnsupportedScheme(
request.url().scheme.clone(),
));
}
helper_client()
.execute(request)
.map(|response| response.body)
}
pub fn head_http<U: ToUrl>(url: U) -> Result<Response, NanoGetError> {
let request =
Request::head(url)?.with_redirect_policy(RedirectPolicy::follow(DEFAULT_REDIRECT_LIMIT));
if !request.url().is_http() {
return Err(NanoGetError::UnsupportedScheme(
request.url().scheme.clone(),
));
}
helper_client().execute(request)
}
#[cfg(feature = "https")]
pub fn get_https<U: ToUrl>(url: U) -> Result<String, NanoGetError> {
get_https_bytes(url)
.and_then(|body| String::from_utf8(body).map_err(|error| error.utf8_error().into()))
}
#[cfg(feature = "https")]
pub fn get_https_bytes<U: ToUrl>(url: U) -> Result<Vec<u8>, NanoGetError> {
let request =
Request::get(url)?.with_redirect_policy(RedirectPolicy::follow(DEFAULT_REDIRECT_LIMIT));
if !request.url().is_https() {
return Err(NanoGetError::UnsupportedScheme(
request.url().scheme.clone(),
));
}
helper_client()
.execute(request)
.map(|response| response.body)
}
#[cfg(feature = "https")]
pub fn head_https<U: ToUrl>(url: U) -> Result<Response, NanoGetError> {
let request =
Request::head(url)?.with_redirect_policy(RedirectPolicy::follow(DEFAULT_REDIRECT_LIMIT));
if !request.url().is_https() {
return Err(NanoGetError::UnsupportedScheme(
request.url().scheme.clone(),
));
}
helper_client().execute(request)
}
fn helper_client() -> Client {
Client::builder()
.redirect_policy(RedirectPolicy::follow(DEFAULT_REDIRECT_LIMIT))
.build()
}
#[cfg(test)]
mod tests {
use crate::client::{CacheMode, Client, ConnectionPolicy, ParserStrictness};
use crate::{get_http_bytes, Method, RedirectPolicy, Request, Url};
#[test]
fn request_constructors_work() {
let request = Request::new(Method::Get, "http://example.com").unwrap();
assert_eq!(request.method(), Method::Get);
}
#[test]
fn default_url_scheme_is_http() {
let url = Url::parse("example.com").unwrap();
assert!(url.is_http());
}
#[test]
fn helper_requests_follow_redirects_by_default() {
let request = Request::get("http://example.com")
.unwrap()
.with_redirect_policy(RedirectPolicy::follow(10));
assert_eq!(request.redirect_policy(), RedirectPolicy::follow(10));
}
#[test]
fn http_only_helpers_reject_https_urls() {
let error = get_http_bytes("https://example.com").unwrap_err();
assert!(matches!(error, crate::NanoGetError::UnsupportedScheme(_)));
}
#[test]
fn http_only_text_and_head_helpers_reject_https_urls() {
let error = crate::get_http("https://example.com").unwrap_err();
assert!(matches!(error, crate::NanoGetError::UnsupportedScheme(_)));
let error = crate::head_http("https://example.com").unwrap_err();
assert!(matches!(error, crate::NanoGetError::UnsupportedScheme(_)));
}
#[test]
fn http_only_helpers_execute_http_paths() {
let error = get_http_bytes("http://127.0.0.1:9").unwrap_err();
assert!(matches!(
error,
crate::NanoGetError::Connect(_) | crate::NanoGetError::Io(_)
));
let error = crate::head_http("http://127.0.0.1:9").unwrap_err();
assert!(matches!(
error,
crate::NanoGetError::Connect(_) | crate::NanoGetError::Io(_)
));
}
#[cfg(feature = "https")]
#[test]
fn https_only_helpers_reject_http_urls() {
let error = crate::get_https("http://example.com").unwrap_err();
assert!(matches!(error, crate::NanoGetError::UnsupportedScheme(_)));
let error = crate::get_https_bytes("http://example.com").unwrap_err();
assert!(matches!(error, crate::NanoGetError::UnsupportedScheme(_)));
let error = crate::head_https("http://example.com").unwrap_err();
assert!(matches!(error, crate::NanoGetError::UnsupportedScheme(_)));
}
#[cfg(feature = "https")]
#[test]
fn https_only_helpers_execute_https_paths() {
let error = crate::get_https_bytes("https://127.0.0.1:9").unwrap_err();
assert!(matches!(
error,
crate::NanoGetError::Connect(_)
| crate::NanoGetError::Io(_)
| crate::NanoGetError::Tls(_)
));
}
#[test]
fn client_builder_is_available() {
let _client = Client::builder()
.connection_policy(ConnectionPolicy::Reuse)
.cache_mode(CacheMode::Memory)
.parser_strictness(ParserStrictness::Lenient)
.build();
}
}