Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
name: Build and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Cache cargo build
uses: Swatinem/rust-cache@v2

- name: Format
run: cargo fmt --all -- --check

- name: Lint
run: cargo clippy --all -- -D warnings

- name: Run tests
run: cargo test --all-features
14 changes: 6 additions & 8 deletions rttp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,23 @@ include = [
]

readme = "README.md"
edition = "2018"
edition = "2021"

[dependencies]

rttp_client = { version = "=0.1.0", optional = true, path = "../rttp_client", features = [ "tls-native", "async" ] }
rttp_client = { optional = true, path = "../rttp_client", features = [ "tls-native", "async" ] }

[dev-dependencies]


async-std = { version = "1" }

[features]
default = []

all = ["rttp_client"]
client = ["rttp_client"]
#client_tls_native = ["rttp_client"]
#client_tls_rustls = ["rttp_client"]
async = ["client", "rttp_client/async"]
tls-native = ["client", "rttp_client/tls-native"]
tls-rustls = ["client", "rttp_client/tls-rustls"]
all = ["client", "async", "tls-native", "tls-rustls"]


#[target.'cfg(feature = "all")'.dependencies]
Expand All @@ -46,4 +45,3 @@ client = ["rttp_client"]
#
#[target.'cfg(feature = "client_tls_rustls")'.dependencies]
#rttp_client = { version = "=0.1.0", path = "../rttp_client", optional = true, default-features = false, features = [ "tls-rustls" ] }

8 changes: 1 addition & 7 deletions rttp/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
pub struct Http {}


impl Http {
#[cfg(any(
feature = "all",
feature = "client",
feature = "client_tls_rustls",
feature = "client_tls_native",
))]
#[cfg(feature = "client")]
pub fn client() -> rttp_client::HttpClient {
rttp_client::HttpClient::new()
}
Expand Down
53 changes: 37 additions & 16 deletions rttp_client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,53 @@ include = [
]

readme = "README.md"
edition = "2018"
edition = "2021"

[dependencies]
url = "2"
tracing = "0.1"
socket2 = "0.5"
futures = "0.3"

url = "2"
percent-encoding = "2"

mime = "0.3"
mime = "0.3"
mime_guess = "2"

rand = "0.7"
socks = "0.3"
base64 = "0.11"
flate2 = "1.0"
httpdate = "0.3"
rand = "0.8"
socks = "0.3"
base64 = "0.22"
flate2 = "1.0"
httpdate = "1.0"


native-tls = { optional = true, version = "0.2" }
async-native-tls = { optional = true, version = "0.5" }

native-tls = { version = "0.2", optional = true }
rustls = { version = "0.16", optional = true }
webpki-roots = { version = "0.18", optional = true }
webpki = { version = "0.21", optional = true }
rustls = { optional = true, version = "0.23" }
webpki-roots = { optional = true, version = "0.26" }
async-rustls = { optional = true, version = "0.4" }

async-std = { version = "1", optional = true }

[features]
default = []
async = []
tls-native = ["native-tls", "async-native-tls"]
tls-rustls = ["rustls", "webpki-roots", "async-rustls"]

##
# warning: /data/rttp/rttp_client/Cargo.toml: Found `feature = ...` in `target.'cfg(...)'.dependencies`.
# This key is not supported for selecting dependencies and will not work as expected.
# Use the [features] section instead: https://doc.rust-lang.org/cargo/reference/features.html
##
#[target.'cfg(any(feature = "async-std", feature = "async-tokio"))'.features]
#tls-native = ["async-native-tls"]
#tls-rustls = ["async-rustls", "webpki", "webpki-roots"]

## Not good way
#[target.'cfg(any(feature = "async-std", feature = "async-tokio"))'.dependencies]
#tls-native = { optional = true, package = "async-native-tls", version = "0.4" }
#tls-rustls = { optional = true, package = "async-rustls", version = "0.2" }

tls-native = ["native-tls"]
tls-rustls = ["rustls", "webpki", "webpki-roots"]
async = ["async-std"]
[dev-dependencies]
rcgen = "0.11"
30 changes: 12 additions & 18 deletions rttp_client/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::{Config, error};
#[cfg(feature = "async")]
use crate::connection::AsyncConnection;
use crate::connection::BlockConnection;
use crate::request::{RawRequest, Request};
use crate::response::Response;
use crate::types::{Header, IntoHeader, IntoPara, Proxy, ToFormData, ToRoUrl};
use crate::{error, Config};

#[derive(Debug)]
pub struct HttpClient {
Expand All @@ -14,13 +14,12 @@ pub struct HttpClient {
impl Default for HttpClient {
fn default() -> Self {
Self {
request: Request::new()
request: Request::new(),
}
}
}

impl HttpClient {

/// Create a `HttpClient` object.
/// # Examples
/// ```rust
Expand All @@ -32,14 +31,11 @@ impl HttpClient {
}

pub(crate) fn with_request(request: Request) -> Self {
Self {
request
}
Self { request }
}
}

impl HttpClient {

/// Set count of this request auto redirect times.
pub(crate) fn count(&mut self, count: u32) -> &mut Self {
self.request.count_set(count);
Expand Down Expand Up @@ -108,8 +104,7 @@ impl HttpClient {

/// Add url path
pub fn path<S: AsRef<str>>(&mut self, path: S) -> &mut Self {
let mut paths = self.request.paths_mut();
paths.push(path.as_ref().into());
self.request.paths_mut().push(path.as_ref().into());
self
}

Expand All @@ -130,14 +125,15 @@ impl HttpClient {
unimplemented!()
}

/// Add request header
/// Add request header
pub fn header<P: IntoHeader>(&mut self, header: P) -> &mut Self {
let mut headers = self.request.headers_mut();
let headers = self.request.headers_mut();
for h in header.into_headers() {
let mut exi = headers.iter_mut()
let exit = headers
.iter_mut()
.find(|d| d.name().eq_ignore_ascii_case(h.name()));

if let Some(eh) = exi {
if let Some(eh) = exit {
if h.name().eq_ignore_ascii_case("cookie") {
let new_cookie_value = format!("{};{}", eh.value(), h.value());
eh.replace(Header::new("Cookie", new_cookie_value));
Expand Down Expand Up @@ -165,16 +161,14 @@ impl HttpClient {
/// Add request para
pub fn para<P: IntoPara>(&mut self, para: P) -> &mut Self {
let paras = para.into_paras();
let mut req_paras = self.request.paras_mut();
req_paras.extend(paras);
self.request.paras_mut().extend(paras);
self
}

/// Add request form data. include file
pub fn form<S: ToFormData>(&mut self, formdata: S) -> &mut Self {
let formdatas = formdata.to_formdatas();
let mut req_formdatas = self.request.formdatas_mut();
req_formdatas.extend(formdatas);
self.request.formdatas_mut().extend(formdatas);
self
}

Expand Down Expand Up @@ -204,7 +198,7 @@ impl HttpClient {
return Err(error::connection_closed());
}
let request = RawRequest::block_new(&mut self.request)?;
BlockConnection::new(request).block_call()
BlockConnection::new(request).call()
}

/// Async request emit
Expand Down
98 changes: 78 additions & 20 deletions rttp_client/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
//use std::{collections::HashMap, sync::Mutex};
//
//use once_cell::sync::Lazy;
//
//static DEFAULT_CONFIG: Lazy<Mutex<Config>> = Lazy::new(|| {
// let mut config = ;
// Mutex::new(config)
//});


#[derive(Clone, Debug)]
pub struct Config {
read_timeout: u64,
write_timeout: u64,
auto_redirect: bool,
max_redirect: u32,
verify_ssl_hostname: bool,
verify_ssl_cert: bool,
}

impl Default for Config {
Expand All @@ -34,27 +26,42 @@ impl Config {
}

impl Config {
pub fn read_timeout(&self) -> u64 { self.read_timeout }
pub fn write_timeout(&self) -> u64 { self.write_timeout }
pub fn auto_redirect(&self) -> bool { self.auto_redirect }
pub fn max_redirect(&self) -> u32 { self.max_redirect }
pub fn read_timeout(&self) -> u64 {
self.read_timeout
}
pub fn write_timeout(&self) -> u64 {
self.write_timeout
}
pub fn auto_redirect(&self) -> bool {
self.auto_redirect
}
pub fn max_redirect(&self) -> u32 {
self.max_redirect
}
pub fn verify_ssl_cert(&self) -> bool {
self.verify_ssl_cert
}
pub fn verify_ssl_hostname(&self) -> bool {
self.verify_ssl_hostname
}
}


#[derive(Clone, Debug)]
pub struct ConfigBuilder {
config: Config
config: Config,
}

impl ConfigBuilder {
pub fn new() -> Self {
Self {
config: Config {
read_timeout: 5000,
write_timeout: 5000,
read_timeout: 10000,
write_timeout: 10000,
auto_redirect: false,
max_redirect: 3,
}
max_redirect: 0,
verify_ssl_hostname: true,
verify_ssl_cert: true,
},
}
}

Expand All @@ -78,6 +85,14 @@ impl ConfigBuilder {
self.config.max_redirect = max_redirect;
self
}
pub fn verify_ssl_hostname(&mut self, verify_ssl_hostname: bool) -> &mut Self {
self.config.verify_ssl_hostname = verify_ssl_hostname;
self
}
pub fn verify_ssl_cert(&mut self, verify_ssl_cert: bool) -> &mut Self {
self.config.verify_ssl_cert = verify_ssl_cert;
self
}
}

impl AsRef<Config> for Config {
Expand All @@ -91,3 +106,46 @@ impl AsRef<Config> for ConfigBuilder {
&self.config
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn builder_updates_values() {
let config = Config::builder()
.read_timeout(1234)
.write_timeout(4321)
.auto_redirect(true)
.max_redirect(5)
.verify_ssl_hostname(false)
.verify_ssl_cert(false)
.build();

assert_eq!(config.read_timeout(), 1234);
assert_eq!(config.write_timeout(), 4321);
assert!(config.auto_redirect());
assert_eq!(config.max_redirect(), 5);
assert!(!config.verify_ssl_hostname());
assert!(!config.verify_ssl_cert());
}

#[test]
fn default_config_matches_builder_defaults() {
let default_config = Config::default();
let builder_config = Config::builder().build();

assert_eq!(default_config.read_timeout(), builder_config.read_timeout());
assert_eq!(default_config.write_timeout(), builder_config.write_timeout());
assert_eq!(default_config.auto_redirect(), builder_config.auto_redirect());
assert_eq!(default_config.max_redirect(), builder_config.max_redirect());
assert_eq!(
default_config.verify_ssl_hostname(),
builder_config.verify_ssl_hostname()
);
assert_eq!(
default_config.verify_ssl_cert(),
builder_config.verify_ssl_cert()
);
}
}
Loading
Loading