Files
aria2-rust-pro/crates/aria2-rust-pro-protocol/src/http/model.rs
T

510 lines
16 KiB
Rust

use std::{collections::HashMap, path::PathBuf};
pub use crate::auth::{
AuthChallengeModel as AuthChallenge, AuthCredentialModel as AuthCredential, AuthScheme,
};
/// Classifies how one header participates in an HTTP exchange.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum HeaderKind {
/// Header belongs to the request.
Request,
/// Header belongs to the response.
Response,
/// Header is valid for both directions.
General,
}
/// One normalized HTTP header field.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpHeader {
/// Lower-level header name.
pub name: String,
/// Raw header value.
pub value: String,
/// Header classification within the exchange.
pub kind: HeaderKind,
}
/// HTTP methods supported by the protocol layer.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum HttpMethod {
/// `GET`
Get,
/// `HEAD`
Head,
/// `POST`
Post,
/// `PUT`
Put,
/// `DELETE`
Delete,
}
/// HTTP versions surfaced by the transport layer.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum HttpVersion {
/// HTTP/1.0
Http10,
/// HTTP/1.1
Http11,
/// HTTP/2
Http2,
/// HTTP/3
Http3,
}
/// One request byte or piece range.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RangeSpec {
/// Inclusive start offset.
pub start: u64,
/// Optional inclusive end offset.
pub end_inclusive: Option<u64>,
/// Unit used by the range.
pub unit: RangeUnit,
}
impl RangeSpec {
#[must_use]
/// Returns whether the range omits an explicit end bound.
pub const fn is_open_ended(&self) -> bool {
self.end_inclusive.is_none()
}
#[must_use]
/// Returns the requested length when the end bound is known.
pub fn length_hint(&self) -> Option<u64> {
self.end_inclusive
.map(|end| end.saturating_sub(self.start).saturating_add(1))
}
}
/// Units supported by HTTP-style range models.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RangeUnit {
/// Byte-oriented ranges.
Bytes,
/// Piece-oriented ranges used by higher-level scheduling.
Pieces,
}
/// Parsed `Content-Range` response metadata.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ContentRangeSpec {
/// Unit reported by the server.
pub unit: RangeUnit,
/// Inclusive start offset returned by the server.
pub start: u64,
/// Inclusive end offset returned by the server.
pub end_inclusive: u64,
/// Total object size when known.
pub total_size: Option<u64>,
/// Whether the response represents an unsatisfied range.
pub unsatisfied: bool,
}
impl ContentRangeSpec {
#[must_use]
/// Returns the completed length implied by the range payload.
pub const fn completed_length(&self) -> u64 {
if self.unsatisfied {
0
} else {
self.end_inclusive.saturating_add(1)
}
}
#[must_use]
/// Returns whether the range is explicitly unsatisfied.
pub const fn is_unsatisfied(&self) -> bool {
self.unsatisfied
}
}
/// Resume metadata carried into one HTTP transfer attempt.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ResumeState {
/// Requested starting offset for the retry or resumed request.
pub requested_offset: u64,
/// Offset actually accepted by the remote server.
pub accepted_offset: Option<u64>,
/// Whether the attempt truly resumed instead of restarting from zero.
pub resumed: bool,
}
/// Retry policy knobs applied to HTTP work.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RetryPolicy {
/// Maximum number of attempts.
pub max_attempts: u32,
/// Initial backoff delay in milliseconds.
pub initial_backoff_ms: u64,
/// Maximum backoff delay in milliseconds.
pub max_backoff_ms: u64,
/// Whether `3xx` responses are retryable.
pub retry_on_3xx: bool,
/// Whether `4xx` responses are retryable.
pub retry_on_4xx: bool,
/// Whether `5xx` responses are retryable.
pub retry_on_5xx: bool,
/// Whether transport-level network errors are retryable.
pub retry_on_network_error: bool,
/// Whether timeout failures are retryable.
pub retry_on_timeout: bool,
}
/// Fully-resolved retry behavior for one request.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RetryStrategy {
/// Base retry policy.
pub policy: RetryPolicy,
/// Optional jitter value in milliseconds.
pub jitter: Option<u64>,
/// Optional upper bound on total retry elapsed time in milliseconds.
pub max_elapsed_ms: Option<u64>,
}
/// Normalized reasons for retrying one transfer attempt.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RetryReason {
/// A transport-level network failure occurred.
NetworkError,
/// The request timed out.
Timeout,
/// The server responded with a retryable `3xx`.
Http3xx,
/// The server responded with a retryable `4xx`.
Http4xx,
/// The server responded with a retryable `5xx`.
Http5xx,
/// Partial-content semantics did not match the requested resume state.
PartialContentMismatch,
/// Another retryable condition occurred.
Other,
}
/// One recorded retry attempt.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RetryAttempt {
/// Attempt number starting at one.
pub attempt: u32,
/// Retry reason for the attempt.
pub reason: RetryReason,
/// Optional HTTP status observed during the attempt.
pub status: Option<u16>,
/// Optional backoff delay in milliseconds before the next attempt.
pub backoff_ms: Option<u64>,
}
/// Final or intermediate completion state for one HTTP response.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum HttpCompletionState {
/// Response is not yet complete.
Incomplete,
/// Response is usable but only partial.
Partial,
/// Response is complete without checksum verification.
Complete,
/// Response is complete and checksum-verified.
Verified,
}
/// Derived completion summary for one HTTP response.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct HttpCompletionModel {
/// Overall completion state.
pub state: HttpCompletionState,
/// Total payload length when known.
pub total_length: Option<u64>,
/// Number of completed bytes.
pub completed_length: u64,
/// Whether the response used partial-content semantics.
pub partial_content: bool,
/// Whether the status code indicates terminal success.
pub terminal_success: bool,
/// Whether checksum metadata was present.
pub checksum_seen: bool,
/// Whether the checksum could be verified successfully.
pub checksum_verified: bool,
}
/// Segment-level progress view for one transfer snapshot.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct HttpSegmentProgressModel {
/// Range originally requested from the server.
pub requested_range: Option<RangeSpec>,
/// Requested starting offset.
pub requested_offset: u64,
/// Offset accepted by the server when present.
pub accepted_offset: Option<u64>,
/// Completed offset derived from the current response.
pub completed_offset: Option<u64>,
/// Whether the transfer is actively resuming instead of restarting.
pub resumed: bool,
}
/// Retry-attempt detail enriched with segment and resume context.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct HttpRetryAttemptDetailModel {
/// Base retry-attempt data.
pub base: RetryAttempt,
/// Range requested for the attempt.
pub requested_range: Option<RangeSpec>,
/// Requested starting offset for the attempt.
pub requested_offset: u64,
/// Offset accepted by the server when present.
pub accepted_offset: Option<u64>,
/// Resume metadata captured for the attempt.
pub resume_state: Option<ResumeState>,
}
/// Snapshot of one in-flight or completed HTTP transfer.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpTransferProgressModel {
/// Stable task identifier.
pub task_id: String,
/// Request model associated with the transfer.
pub request: HttpRequestModel,
/// Segment-level progress details.
pub segment: HttpSegmentProgressModel,
/// Retry-attempt history with contextual detail.
pub retry_attempts: Vec<HttpRetryAttemptDetailModel>,
/// Maximum number of concurrent connections permitted for the task.
pub max_connections: u16,
/// Optional checksum hook attached to the transfer.
pub checksum_hook: Option<ChecksumHookModel>,
/// Derived completion summary when a response exists.
pub completion: Option<HttpCompletionModel>,
}
/// Proxy configuration projected into HTTP requests.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ProxyConfig {
/// Proxy scheme such as `http` or `socks5`.
pub scheme: String,
/// Proxy host name or IP.
pub host: String,
/// Proxy port.
pub port: u16,
/// Optional proxy username.
pub username: Option<String>,
/// Optional proxy password.
pub password: Option<String>,
/// Hosts that should bypass the proxy.
pub bypass_hosts: Vec<String>,
/// Whether proxying is disabled for the request.
pub no_proxy: bool,
}
/// One normalized HTTP cookie.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Cookie {
/// Cookie name.
pub name: String,
/// Cookie value.
pub value: String,
/// Optional domain constraint.
pub domain: Option<String>,
/// Optional path constraint.
pub path: Option<String>,
/// Whether the cookie requires a secure transport.
pub secure: bool,
/// Whether the cookie is `HttpOnly`.
pub http_only: bool,
/// Optional same-site policy marker.
pub same_site: Option<String>,
/// Expiration time as a Unix timestamp when present.
pub expires_unix_epoch: Option<u64>,
}
/// TLS behavior attached to one HTTP session.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TlsConfig {
/// Whether peer certificates must be verified.
pub verify_peer: bool,
/// Whether host name verification is enabled.
pub verify_host: bool,
/// Minimum TLS version when constrained.
pub min_version: Option<String>,
/// Maximum TLS version when constrained.
pub max_version: Option<String>,
/// Optional CA bundle path.
pub ca_file: Option<String>,
/// Optional client certificate path.
pub cert_file: Option<String>,
/// Optional client key path.
pub key_file: Option<String>,
}
/// Ordered collection of request headers.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpRequestHeaders {
/// Stored request headers.
pub headers: Vec<HttpHeader>,
}
/// Ordered collection of response headers.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpResponseHeaders {
/// Stored response headers.
pub headers: Vec<HttpHeader>,
}
/// Request-body representation for HTTP transfers.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum HttpBody {
/// No request body.
Empty,
/// UTF-8 text request body.
Text(String),
/// Arbitrary binary request body.
Binary(Vec<u8>),
/// Streaming body with an optional declared length.
Stream {
/// Declared body length when the caller knows it.
expected_len: Option<u64>,
},
}
/// Expected and observed checksum metadata for one payload.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ChecksumSpec {
/// Hash algorithm name.
pub algorithm: String,
/// Expected digest hex string.
pub expected_hex: String,
/// Observed digest hex string when known.
pub actual_hex: Option<String>,
}
/// Optional checksum hook attached to a transfer.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ChecksumHookModel {
/// Checksum specification to evaluate.
pub spec: ChecksumSpec,
/// Whether the hook is enabled.
pub enabled: bool,
}
/// Optional direct-write target for one live HTTP response body.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpResponseSinkTarget {
/// Final output path that should receive the response body directly.
pub target_path: PathBuf,
}
/// Fully normalized HTTP request model.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpRequestModel {
/// HTTP method.
pub method: HttpMethod,
/// Fully-qualified request URL.
pub url: String,
/// Requested HTTP version.
pub version: HttpVersion,
/// Explicit request headers.
pub headers: HttpRequestHeaders,
/// Query parameters to attach to the URL.
pub query: HashMap<String, String>,
/// Optional range metadata.
pub range: Option<RangeSpec>,
/// Request body.
pub body: HttpBody,
/// Retry strategy for the request.
pub retry: RetryStrategy,
/// Optional origin credential.
pub auth: Option<AuthCredential>,
/// Optional proxy configuration.
pub proxy: Option<ProxyConfig>,
/// Optional direct-write sink for live response persistence.
pub response_sink: Option<HttpResponseSinkTarget>,
}
/// Session-scoped defaults that shape HTTP execution.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpSessionModel {
/// Stable session identifier.
pub session_id: String,
/// Optional user-agent string.
pub user_agent: Option<String>,
/// Default headers applied to requests.
pub default_headers: Vec<HttpHeader>,
/// Cookies carried by the session.
pub cookies: Vec<Cookie>,
/// Optional default credential.
pub auth: Option<AuthCredential>,
/// Optional default proxy configuration.
pub proxy: Option<ProxyConfig>,
/// Optional TLS behavior for the session.
pub tls: Option<TlsConfig>,
/// Default retry strategy for the session.
pub retry: RetryStrategy,
}
/// Response-body representation used by the protocol layer.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ResponseBody {
/// No response payload.
Empty,
/// Inline retained payload bytes.
Inline(Vec<u8>),
/// Streamed payload metadata with optional retained artifacts.
Streamed {
/// Declared content length when known.
expected_len: Option<u64>,
/// Observed byte count written through the sink.
observed_len: Option<u64>,
/// Observed digest when computed by the sink.
observed_digest: Option<String>,
/// Optional temporary file path holding the streamed body.
temp_path: Option<PathBuf>,
},
}
/// Executable HTTP transfer task passed into downloaders.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpTransferTaskModel {
/// Stable task identifier.
pub task_id: String,
/// Request model for the task.
pub request: HttpRequestModel,
/// Response headers already associated with the task.
pub response_headers: HttpResponseHeaders,
/// Current response body state.
pub body: ResponseBody,
/// Resume metadata when resuming is in play.
pub resume_state: Option<ResumeState>,
/// Retry-attempt history.
pub retry_attempts: Vec<RetryAttempt>,
/// Optional checksum hook.
pub checksum_hook: Option<ChecksumHookModel>,
/// Maximum allowed concurrent connections.
pub max_connections: u16,
/// Retry strategy for the task.
pub retry: RetryStrategy,
}
/// Normalized HTTP response model produced by connectors and fixtures.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpResponseModel {
/// Numeric HTTP status code.
pub status: u16,
/// Human-readable reason phrase.
pub reason: String,
/// Negotiated HTTP version.
pub version: HttpVersion,
/// Response headers.
pub headers: HttpResponseHeaders,
/// Response body representation.
pub body: ResponseBody,
/// Parsed `Content-Range` metadata when present.
pub content_range: Option<ContentRangeSpec>,
/// Whether the response used partial-content semantics.
pub partial_content: bool,
/// Optional checksum metadata.
pub checksum: Option<ChecksumSpec>,
/// Original URL before redirects when one occurred.
pub redirected_from: Option<String>,
}