Skip to content

Commit

Permalink
feat:timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
ltpp-universe committed Dec 1, 2024
1 parent 92852c2 commit 61da20c
Show file tree
Hide file tree
Showing 11 changed files with 50 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "http-request"
version = "4.0.0"
version = "4.1.0"
edition = "2021"
authors = ["ltpp-universe <[email protected]>"]
license = "MIT"
Expand Down
3 changes: 2 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

[Official Documentation](https://docs.ltpp.vip/HTTP-REQUEST/)

> http_request is a lightweight, efficient library for building, sending, and handling HTTP/HTTPS requests in Rust applications. It provides a simple and intuitive API, allowing developers to easily interact with web services, whether they use the "HTTP" or "HTTPS" protocol. The library supports various HTTP methods, custom headers, request bodies, and automatic handling of redirects (including detecting redirect loops), enabling fast and secure communication. Whether working with secure "HTTPS" connections or standard "HTTP" requests, the library is optimized for performance, minimal resource usage, and easy integration into Rust projects.
> http_request is a lightweight, efficient library for building, sending, and handling HTTP/HTTPS requests in Rust applications. It provides a simple and intuitive API, allowing developers to easily interact with web services, whether they use the "HTTP" or "HTTPS" protocol. The library supports various HTTP methods, custom headers, request bodies, timeout, and automatic handling of redirects (including detecting redirect loops), enabling fast and secure communication. Whether working with secure "HTTPS" connections or standard "HTTP" requests, the library is optimized for performance, minimal resource usage, and easy integration into Rust projects.
## Features

Expand All @@ -20,6 +20,7 @@
- **Response Handling**: Provides a simple wrapper around HTTP responses, making it easy to access and process response data.
- **Optimized Memory Management**: Implements efficient memory management to minimize unnecessary memory allocations and improve performance.
- **Redirect Handling**: Supports redirect handling, allows setting the maximum number of redirects, and includes redirect loop detection.
- **timeout**: Supports timeout

## Installation

Expand Down
6 changes: 6 additions & 0 deletions src/constant/common.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
/// The name of the application.
pub static APP_NAME: &str = "http-request";

/// space
pub static SPACE: &str = " ";

/// Colon space
pub static COLON_SPACE: &str = ": ";
3 changes: 3 additions & 0 deletions src/constant/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub static USER_AGENT: &str = "User-Agent";
/// The HTTP header field name `Host`, used to specify the host and port number of the server.
pub static HOST: &str = "Host";

/// Unknown HTTP version
pub static UNKNOWN_HTTP_VERSION: &str = "";

/// The default HTTP version `HTTP/1.1` used in requests and responses.
pub static HTTP_VERSION_1_1: &str = "HTTP/1.1";

Expand Down
7 changes: 5 additions & 2 deletions src/request/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,17 @@ fn test_https_post_request() {
header.insert("Connection", "keep-alive");
header.insert("Accept-Encoding", "gzip, deflate");
let mut body: HashMap<&str, &str> = HashMap::new();
body.insert("code", "hello");
body.insert(
"code",
"fn main() {\r\nloop {} println!(\"hello world\");\r\n}",
);
body.insert("language", "rust");
body.insert("testin", "");
let mut _request_builder = HttpRequestBuilder::new()
.post("https://code.ltpp.vip/")
.json(body)
.headers(header)
.timeout(6000)
.timeout(1000)
.redirect()
.max_redirect_times(8)
.http1_1_only()
Expand Down
2 changes: 2 additions & 0 deletions src/request/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub enum Error {
ReadConnectionError,
TlsConnectorBuildError,
SetReadTimeoutError,
SetWriteTimeoutError,
TlsStreamConnectError,
MaxRedirectTimes,
RedirectUrlDeadLoop,
Expand Down Expand Up @@ -56,6 +57,7 @@ impl fmt::Display for Error {
Error::ReadConnectionError => write!(f, "Connection Read Error"),
Error::TlsConnectorBuildError => write!(f, "TLS Connector Build Error"),
Error::SetReadTimeoutError => write!(f, "Failed to Set Read Timeout"),
Error::SetWriteTimeoutError => write!(f, "Failed to Set Write Timeout"),
Error::TlsStreamConnectError => write!(f, "TLS Stream Connection Error"),
Error::MaxRedirectTimes => write!(f, "Max Redirect Times"),
Error::RedirectUrlDeadLoop => write!(f, "Redirect URL Dead Loop"),
Expand Down
11 changes: 9 additions & 2 deletions src/request/http_request/impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,15 +347,19 @@ impl HttpRequest {
/// - `Error::TlsStreamConnectError`: If the TLS stream could not be established.
fn get_connection_stream(&self, host: String, port: u16) -> Result<Box<dyn ReadWrite>, Error> {
let host_port: (String, u16) = (host.clone(), port);
let timeout: Duration = Duration::from_millis(self.config.timeout);
let stream: Result<Box<dyn ReadWrite>, Error> = if self.get_protocol().is_https() {
let tls_connector: TlsConnector = TlsConnector::builder()
.build()
.map_err(|_| Error::TlsConnectorBuildError)?;
let tcp_stream: TcpStream =
TcpStream::connect(host_port.clone()).map_err(|_| Error::TcpStreamConnectError)?;
tcp_stream
.set_read_timeout(Some(Duration::from_secs(self.config.timeout)))
.set_read_timeout(Some(timeout))
.map_err(|_| Error::SetReadTimeoutError)?;
tcp_stream
.set_write_timeout(Some(timeout))
.map_err(|_| Error::SetWriteTimeoutError)?;
let tls_stream: TlsStream<TcpStream> = tls_connector
.connect(&host.clone(), tcp_stream)
.map_err(|_| Error::TlsStreamConnectError)?;
Expand All @@ -364,8 +368,11 @@ impl HttpRequest {
let tcp_stream: TcpStream =
TcpStream::connect(host_port.clone()).map_err(|_| Error::TcpStreamConnectError)?;
tcp_stream
.set_read_timeout(Some(Duration::from_millis(self.config.timeout)))
.set_read_timeout(Some(timeout))
.map_err(|_| Error::SetReadTimeoutError)?;
tcp_stream
.set_write_timeout(Some(timeout))
.map_err(|_| Error::SetWriteTimeoutError)?;
Ok(Box::new(tcp_stream))
};
stream
Expand Down
3 changes: 2 additions & 1 deletion src/request/http_version/impl.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::r#type::HttpVersion;
use crate::constant::http::{HTTP_VERSION_1_1, HTTP_VERSION_2};
use crate::constant::http::{HTTP_VERSION_1_1, HTTP_VERSION_2, UNKNOWN_HTTP_VERSION};
use std::fmt;

impl Default for HttpVersion {
Expand Down Expand Up @@ -32,6 +32,7 @@ impl fmt::Display for HttpVersion {
let version_str = match self {
HttpVersion::HTTP1_1 => HTTP_VERSION_1_1,
HttpVersion::HTTP2 => HTTP_VERSION_2,
HttpVersion::Unknown(_) => UNKNOWN_HTTP_VERSION,
};
write!(f, "{}", version_str)
}
Expand Down
3 changes: 3 additions & 0 deletions src/request/http_version/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ pub enum HttpVersion {

/// HTTP version 2.0
HTTP2,

/// Unknown version
Unknown(String),
}
22 changes: 16 additions & 6 deletions src/response/impl.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use super::r#type::HttpResponse;
use crate::{
constant::http::{CONTENT_LENGTH, HTTP_BR, HTTP_VERSION_1_1},
constant::{
common::{COLON_SPACE, SPACE},
http::{CONTENT_LENGTH, HTTP_BR},
},
request::http_version::r#type::HttpVersion,
status_code::r#type::StatusCode,
};
use std::collections::HashMap;
Expand Down Expand Up @@ -64,26 +68,32 @@ impl HttpResponse {
let mut lines: Lines<'_> = response.lines();
let status_line: &str = lines.next().unwrap_or("");
let status_parts: Vec<&str> = status_line.split_whitespace().collect();
let http_version: String = status_parts.get(0).unwrap_or(&HTTP_VERSION_1_1).to_string();
let http_version: String = status_parts
.get(0)
.unwrap_or(&HttpVersion::Unknown(String::new()).to_string().as_str())
.to_string();
let status_code: u16 = status_parts
.get(1)
.unwrap_or(&StatusCode::Ok.to_string().as_str())
.parse()
.unwrap_or(StatusCode::Unknown.code());
let status_text: String = status_parts.get(2..).unwrap_or(&[]).join(" ");
let status_text: String = status_parts
.get(2..)
.unwrap_or(&[&StatusCode::Unknown.to_string()])
.join(SPACE);
let mut headers: HashMap<String, String> = HashMap::new();
while let Some(line) = lines.next() {
if line.is_empty() {
break;
}
let header_parts: Vec<&str> = line.splitn(2, ": ").collect();
let header_parts: Vec<&str> = line.splitn(2, COLON_SPACE).collect();
if header_parts.len() == 2 {
let key: String = header_parts[0].trim().to_string();
let value: String = header_parts[1].trim().to_string();
headers.insert(key, value);
}
}
let body: String = lines.collect::<Vec<&str>>().join("\n");
let body: String = lines.collect::<Vec<&str>>().join(HTTP_BR);
HttpResponse {
http_version,
status_code,
Expand All @@ -102,7 +112,7 @@ impl HttpResponse {
impl Default for HttpResponse {
fn default() -> Self {
HttpResponse {
http_version: HTTP_VERSION_1_1.to_string(),
http_version: HttpVersion::Unknown(String::new()).to_string(),
status_code: StatusCode::Unknown.code(),
status_text: StatusCode::Unknown.to_string(),
headers: HashMap::new(),
Expand Down

0 comments on commit 61da20c

Please sign in to comment.