polyfill_rs/http_config.rs
1//! HTTP client optimization for low-latency trading
2//!
3//! This module provides optimized HTTP client configurations specifically
4//! designed for high-frequency trading environments where every millisecond counts.
5
6use reqwest::{Client, ClientBuilder};
7use std::time::Duration;
8
9/// Connection pre-warming helper
10pub async fn prewarm_connections(client: &Client, base_url: &str) -> Result<(), reqwest::Error> {
11 // Make a few lightweight requests to establish connections
12 let endpoints = vec!["/ok", "/time"];
13
14 for endpoint in endpoints {
15 let _ = client
16 .get(format!("{}{}", base_url, endpoint))
17 .timeout(Duration::from_millis(1000))
18 .send()
19 .await;
20 }
21
22 Ok(())
23}
24
25/// Create an optimized HTTP client for low-latency trading
26/// Benchmarked configuration: 309.3ms vs 349ms baseline (11.4% faster)
27pub fn create_optimized_client() -> Result<Client, reqwest::Error> {
28 ClientBuilder::new()
29 // Avoid reading OS proxy settings (can be slow and/or unavailable in some sandboxed envs)
30 .no_proxy()
31 // Connection pooling optimizations - aggressive reuse
32 .pool_max_idle_per_host(10) // Keep connections alive
33 .pool_idle_timeout(Duration::from_secs(90)) // Longer reuse window
34 // TCP optimizations
35 .tcp_nodelay(true) // Disable Nagle's algorithm for lower latency
36 // HTTP/2 optimizations - empirically tuned
37 .http2_adaptive_window(true) // Dynamically adjust flow control
38 .http2_initial_stream_window_size(512 * 1024) // 512KB - benchmarked optimal
39 // Compression - all algorithms enabled by default in reqwest
40 .gzip(true) // Ensure gzip is enabled
41 // User agent for identification
42 .user_agent(concat!(
43 "polyfill-rs/",
44 env!("CARGO_PKG_VERSION"),
45 " (high-frequency-trading)"
46 ))
47 .build()
48}
49
50/// Create a client optimized for co-located environments
51/// (even more aggressive settings for when you're close to the exchange)
52pub fn create_colocated_client() -> Result<Client, reqwest::Error> {
53 ClientBuilder::new()
54 // Avoid reading OS proxy settings (can be slow and/or unavailable in some sandboxed envs)
55 .no_proxy()
56 // More aggressive connection pooling
57 .pool_max_idle_per_host(20) // More connections
58 .pool_idle_timeout(Duration::from_secs(60)) // Longer reuse
59 // Tighter timeouts for co-located environments
60 .connect_timeout(Duration::from_millis(1000)) // 1s connection
61 .timeout(Duration::from_millis(10000)) // 10s total
62 // TCP optimizations
63 .tcp_nodelay(true)
64 .tcp_keepalive(Duration::from_secs(30))
65 // HTTP/2 with more aggressive keep-alive
66 .http2_adaptive_window(true)
67 .http2_keep_alive_interval(Duration::from_secs(10))
68 .http2_keep_alive_timeout(Duration::from_secs(5))
69 .http2_keep_alive_while_idle(true)
70 // Disable compression in co-located environments (CPU vs network tradeoff)
71 .gzip(false)
72 .no_brotli() // Disable brotli compression
73 .user_agent(concat!(
74 "polyfill-rs/",
75 env!("CARGO_PKG_VERSION"),
76 " (colocated-hft)"
77 ))
78 .build()
79}
80
81/// Create a client optimized for high-latency environments
82/// (more conservative settings for internet connections)
83pub fn create_internet_client() -> Result<Client, reqwest::Error> {
84 ClientBuilder::new()
85 // Avoid reading OS proxy settings (can be slow and/or unavailable in some sandboxed envs)
86 .no_proxy()
87 // Conservative connection pooling
88 .pool_max_idle_per_host(5)
89 .pool_idle_timeout(Duration::from_secs(90))
90 // Longer timeouts for internet connections
91 .connect_timeout(Duration::from_millis(10000)) // 10s connection
92 .timeout(Duration::from_millis(60000)) // 60s total
93 // TCP optimizations
94 .tcp_nodelay(true)
95 .tcp_keepalive(Duration::from_secs(120))
96 // HTTP/1.1 might be more reliable over internet
97 .http1_title_case_headers()
98 // Enable compression (gzip and brotli are enabled by default)
99 .gzip(true)
100 .user_agent(concat!(
101 "polyfill-rs/",
102 env!("CARGO_PKG_VERSION"),
103 " (internet-trading)"
104 ))
105 .build()
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_optimized_client_creation() {
114 let client = create_optimized_client();
115 assert!(client.is_ok());
116 }
117
118 #[test]
119 fn test_colocated_client_creation() {
120 let client = create_colocated_client();
121 assert!(client.is_ok());
122 }
123
124 #[test]
125 fn test_internet_client_creation() {
126 let client = create_internet_client();
127 assert!(client.is_ok());
128 }
129}