1use super::*;
2
3impl<T: AsyncRead + AsyncWrite + Unpin + Send> AsyncReadWrite for T {}
4impl<T: Read + Write> ReadWrite for T {}
5
6impl HttpRequest {
7 pub fn send(&mut self) -> RequestResult {
13 self.send_sync()
14 }
15
16 pub async fn send_async(&mut self) -> RequestResult {
22 self.send_async_impl().await
23 }
24
25 pub(crate) fn parse_url(&self) -> Result<HttpUrlComponents, RequestError> {
31 HttpUrlComponents::parse(self.get_url())
32 .map_err(|e: ::http_type::HttpUrlError| RequestError::Request(e.to_string()))
33 }
34
35 pub(crate) fn full_path(&self) -> String {
41 let url_obj: HttpUrlComponents = self.parse_url().unwrap_or_default();
42 let query: String = url_obj.get_query().unwrap_or_default();
43 let path: String = url_obj.get_path().unwrap_or_default();
44 if query.is_empty() {
45 path
46 } else {
47 format!("{}{}{}", path, QUERY, query)
48 }
49 }
50
51 pub(crate) fn protocol_lower(config: &RequestConfig) -> String {
61 config.get_http_version().to_string().to_ascii_lowercase()
62 }
63
64 pub(crate) fn header_bytes(&self, body_length: usize) -> Vec<u8> {
75 let mut header: HashMap<String, String> = self.get_headers().clone();
76 let host_value: String = self
77 .parse_url()
78 .ok()
79 .and_then(|u: ::http_type::HttpUrlComponents| u.get_host().clone())
80 .unwrap_or_default();
81 let content_length_value: String = body_length.to_string();
82 if !Self::header_has_key(&header, HOST) {
83 header.insert(HOST.to_ascii_lowercase(), host_value);
84 }
85 if !Self::header_has_key(&header, CONTENT_LENGTH) {
86 header.insert(CONTENT_LENGTH.to_ascii_lowercase(), content_length_value);
87 }
88 if !Self::header_has_key(&header, ACCEPT) {
89 header.insert(ACCEPT.to_ascii_lowercase(), ACCEPT_ANY.to_owned());
90 }
91 if !Self::header_has_key(&header, USER_AGENT) {
92 header.insert(USER_AGENT.to_ascii_lowercase(), APP_NAME.to_owned());
93 }
94 let estimated_size: usize = header
95 .iter()
96 .map(|(k, v): (&String, &String)| k.len() + v.len() + 4)
97 .sum();
98 let mut out: Vec<u8> = Vec::with_capacity(estimated_size);
99 for (key, value) in &header {
100 out.extend_from_slice(key.as_bytes());
101 out.extend_from_slice(HEADER_VALUE_SEPARATOR);
102 out.extend_from_slice(value.as_bytes());
103 out.extend_from_slice(HTTP_BR_BYTES);
104 }
105 out
106 }
107
108 fn header_has_key(header: &HashMap<String, String>, target_key: &str) -> bool {
119 let target: String = target_key.to_ascii_lowercase();
120 header.keys().any(|k: &String| k == &target)
121 }
122
123 pub(crate) fn body_bytes(&self) -> Vec<u8> {
130 let ct: Option<String> = self
131 .headers
132 .iter()
133 .find(|(k, _): &(&String, &String)| k.eq_ignore_ascii_case(CONTENT_TYPE))
134 .map(|(_, v): (&String, &String)| v.clone());
135 match ct {
136 Some(value) => value
137 .to_lowercase()
138 .parse::<ContentType>()
139 .unwrap_or_default()
140 .get_body_string(&String::from_utf8_lossy(self.get_body().as_slice()))
141 .into_bytes(),
142 None => Vec::new(),
143 }
144 }
145
146 pub(crate) fn send_sync(&mut self) -> RequestResult {
152 let url_obj: HttpUrlComponents = self.parse_url()?;
153 let host: String = url_obj.get_host().clone().unwrap_or_default();
154 let port: u16 = self.resolve_port(url_obj.get_port().unwrap_or_default());
155 let mut stream: BoxReadWrite = self.open_sync_stream(host, port)?;
156 let method: Method = self.get_method();
157 if method.is_get() {
158 self.send_get_request_sync(&mut stream)
159 } else if method.is_post() {
160 self.send_post_request_sync(&mut stream)
161 } else {
162 Err(RequestError::Request(METHOD_NOT_ALLOWED.to_string()))
163 }
164 }
165
166 async fn send_async_impl(&mut self) -> RequestResult {
172 let url_obj: HttpUrlComponents = self.parse_url()?;
173 let host: String = url_obj.get_host().clone().unwrap_or_default();
174 let port: u16 = self.resolve_port(url_obj.get_port().unwrap_or_default());
175 let mut stream: BoxAsyncReadWrite = self.open_async_stream(host, port).await?;
176 let method: Method = self.get_method();
177 if method.is_get() {
178 self.send_get_request_async(&mut stream).await
179 } else if method.is_post() {
180 self.send_post_request_async(&mut stream).await
181 } else {
182 Err(RequestError::Request(METHOD_NOT_ALLOWED.to_string()))
183 }
184 }
185
186 fn resolve_port(&self, port: u16) -> u16 {
196 if port != 0 {
197 return port;
198 }
199 let protocol: String = Self::protocol_lower(self.get_config());
200 Protocol::get_port(&protocol)
201 }
202
203 fn is_https(&self) -> bool {
209 Self::protocol_lower(self.get_config()) == HTTPS_LOWERCASE
210 }
211
212 fn open_sync_stream(&self, host: String, port: u16) -> Result<BoxReadWrite, RequestError> {
225 if let Some(proxy) = &self.get_config().get_proxy() {
226 return self.open_sync_proxy_stream(host, port, proxy);
227 }
228 let timeout: Duration = Duration::from_millis(self.get_config().get_timeout());
229 let tcp: TcpStream = TcpStream::connect((host.clone(), port))
230 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
231 tcp.set_read_timeout(Some(timeout))
232 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
233 tcp.set_write_timeout(Some(timeout))
234 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
235 if self.is_https() {
236 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
237 let tls_cfg: ClientConfig = ClientConfig::builder()
238 .with_root_certificates(roots)
239 .with_no_client_auth();
240 let dns: ServerName<'static> = ServerName::try_from(host.clone())
241 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
242 let session: ClientConnection = ClientConnection::new(Arc::new(tls_cfg), dns)
243 .map_err(|e: rustls::Error| RequestError::Request(e.to_string()))?;
244 Ok(Box::new(StreamOwned::new(session, tcp)))
245 } else {
246 Ok(Box::new(tcp))
247 }
248 }
249
250 fn send_get_request_sync(
260 &mut self,
261 stream: &mut BoxReadWrite,
262 ) -> Result<HttpResponse, RequestError> {
263 let path: String = self.full_path();
264 let header_bytes: Vec<u8> = self.header_bytes(0);
265 let version: String = self.get_config().get_http_version().to_string();
266 let request: Vec<u8> = build_http_request("GET", path, header_bytes, None, version);
267 stream
268 .write_all(&request)
269 .and_then(|_: ()| stream.flush())
270 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
271 self.read_response_sync(stream)
272 }
273
274 fn send_post_request_sync(
284 &mut self,
285 stream: &mut BoxReadWrite,
286 ) -> Result<HttpResponse, RequestError> {
287 let body_bytes: Vec<u8> = self.body_bytes();
288 let path: String = self.full_path();
289 let header_bytes: Vec<u8> = self.header_bytes(body_bytes.len());
290 let version: String = self.get_config().get_http_version().to_string();
291 let request: Vec<u8> = build_http_request(
292 HTTP_METHOD_POST,
293 path,
294 header_bytes,
295 Some(body_bytes),
296 version,
297 );
298 stream
299 .write_all(&request)
300 .and_then(|_: ()| stream.flush())
301 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
302 self.read_response_sync(stream)
303 }
304
305 fn read_response_sync(
315 &mut self,
316 stream: &mut BoxReadWrite,
317 ) -> Result<HttpResponse, RequestError> {
318 let buffer_size: usize = self.get_config().buffer_size;
319 let mut buffer: Vec<u8> = vec![0u8; buffer_size];
320 let mut response_bytes: Vec<u8> = Vec::with_capacity(buffer_size.max(8192));
321 let mut headers_done: bool = false;
322 let mut content_length: usize = 0usize;
323 let mut redirect_url: Option<Vec<u8>> = None;
324 let mut headers_end_pos: usize = 0usize;
325 let mut is_chunked: bool = false;
326 let version_bytes: Vec<u8> = self
327 .config
328 .get_http_version()
329 .to_string()
330 .to_ascii_lowercase()
331 .into_bytes();
332 let location_key: Vec<u8> = format!("{}:", LOCATION.to_ascii_lowercase()).into_bytes();
333 loop {
334 let n: usize = stream
335 .read(&mut buffer)
336 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
337 if n == 0 {
338 break;
339 }
340 let new_cap: usize =
341 calculate_buffer_capacity(&response_bytes, n, response_bytes.capacity());
342 if new_cap > 0 {
343 response_bytes.reserve(new_cap - response_bytes.capacity());
344 }
345 let old_len: usize = response_bytes.len();
346 response_bytes.extend_from_slice(&buffer[..n]);
347 if !headers_done {
348 let search_start: usize = old_len.saturating_sub(3);
349 if let Some(pos) = find_double_crlf(&response_bytes, search_start) {
350 headers_done = true;
351 headers_end_pos = pos + 4;
352 parse_response_headers(
353 &response_bytes[..headers_end_pos],
354 &version_bytes,
355 &location_key,
356 &mut content_length,
357 &mut redirect_url,
358 &mut is_chunked,
359 )?;
360 }
361 }
362 if headers_done {
363 if is_chunked {
364 if Self::is_chunked_response_complete(&response_bytes[headers_end_pos..]) {
365 break;
366 }
367 } else if response_bytes.len() >= headers_end_pos + content_length {
368 response_bytes.truncate(headers_end_pos + content_length);
369 break;
370 }
371 }
372 }
373 if is_chunked {
374 let body_bytes: Vec<u8> = response_bytes[headers_end_pos..].to_vec();
375 let decoded: Vec<u8> = parse_chunked_body(&body_bytes);
376 response_bytes.truncate(headers_end_pos);
377 response_bytes.extend_from_slice(&decoded);
378 }
379 let mut response: HttpResponse = HttpResponse::from_bytes(&response_bytes);
380 if !self.get_config().get_redirect() || redirect_url.is_none() {
381 if self.get_config().get_decode() {
382 response = response.decode(self.get_config().buffer_size);
383 }
384 return Ok(response);
385 }
386 let url_bytes: Vec<u8> = redirect_url
387 .take()
388 .ok_or_else(|| RequestError::Request(MISSING_REDIRECT_URL.to_string()))?;
389 let url: String = String::from_utf8(url_bytes)
390 .map_err(|e: FromUtf8Error| RequestError::Request(e.to_string()))?;
391 self.handle_redirect(url)
392 }
393
394 fn handle_redirect(&mut self, url: String) -> Result<HttpResponse, RequestError> {
404 if !self.get_config().get_redirect() {
405 return Err(RequestError::Request(REDIRECT_NOT_ENABLED.to_string()));
406 }
407 if self.get_tmp().get_visit_url().contains(&url) {
408 return Err(RequestError::Request(REDIRECT_URL_DEAD_LOOP.to_string()));
409 }
410 self.get_mut_tmp().get_mut_visit_url().insert(url.clone());
411 if self.get_config().get_max_redirect_times() == 0 {
412 return Err(RequestError::Request(
413 MAX_REDIRECT_TIMES_EXCEEDED.to_string(),
414 ));
415 }
416 let remaining: usize = self.get_config().get_max_redirect_times();
417 self.get_mut_config()
418 .set_max_redirect_times(remaining.saturating_sub(1));
419 self.set_url(url);
420 self.send_sync()
421 }
422
423 fn is_chunked_response_complete(body_bytes: &[u8]) -> bool {
433 let mut pos: usize = 0;
434 while pos < body_bytes.len() {
435 let chunk_size_end: usize = match body_bytes[pos..]
436 .windows(2)
437 .position(|w: &[u8]| w == HTTP_CARRIAGE_RETURN_LINE_FEED)
438 {
439 Some(p) => pos + p,
440 None => return false,
441 };
442 let raw: &[u8] = &body_bytes[pos..chunk_size_end];
443 let chunk_size_str: &[u8] = match raw.iter().position(|&b: &u8| b == b';') {
444 Some(p) => &raw[..p],
445 None => raw,
446 };
447 let chunk_size: usize = match from_utf8(chunk_size_str) {
448 Ok(s) => match usize::from_str_radix(s.trim(), 16) {
449 Ok(n) => n,
450 Err(_) => return false,
451 },
452 Err(_) => return false,
453 };
454 if chunk_size == 0 {
455 return true;
456 }
457 let start: usize = chunk_size_end + 2;
458 let end: usize = start + chunk_size;
459 if end + 2 > body_bytes.len() {
460 return false;
461 }
462 pos = end + 2;
463 }
464 false
465 }
466
467 async fn open_async_stream(
480 &self,
481 host: String,
482 port: u16,
483 ) -> Result<BoxAsyncReadWrite, RequestError> {
484 if let Some(proxy) = &self.get_config().get_proxy() {
485 return self.open_async_proxy_stream(host, port, proxy).await;
486 }
487 let tcp: http_type::tokio::net::TcpStream =
488 http_type::tokio::net::TcpStream::connect((host.clone(), port))
489 .await
490 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
491 if self.is_https() {
492 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
493 let tls_cfg: ClientConfig = ClientConfig::builder()
494 .with_root_certificates(roots)
495 .with_no_client_auth();
496 let connector: TlsConnector = TlsConnector::from(Arc::new(tls_cfg));
497 let dns: ServerName<'static> = ServerName::try_from(host.clone())
498 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
499 let tls: tokio_rustls::client::TlsStream<http_type::tokio::net::TcpStream> = connector
500 .connect(dns, tcp)
501 .await
502 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
503 Ok(Box::new(tls))
504 } else {
505 Ok(Box::new(tcp))
506 }
507 }
508
509 async fn send_get_request_async(
519 &mut self,
520 stream: &mut BoxAsyncReadWrite,
521 ) -> Result<HttpResponse, RequestError> {
522 let path: String = self.full_path();
523 let header_bytes: Vec<u8> = self.header_bytes(0);
524 let version: String = self.get_config().get_http_version().to_string();
525 let request: Vec<u8> = build_http_request("GET", path, header_bytes, None, version);
526 stream
527 .write_all(&request)
528 .await
529 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
530 stream
531 .flush()
532 .await
533 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
534 self.read_response_async(stream).await
535 }
536
537 async fn send_post_request_async(
547 &mut self,
548 stream: &mut BoxAsyncReadWrite,
549 ) -> Result<HttpResponse, RequestError> {
550 let body_bytes: Vec<u8> = self.body_bytes();
551 let path: String = self.full_path();
552 let header_bytes: Vec<u8> = self.header_bytes(body_bytes.len());
553 let version: String = self.get_config().get_http_version().to_string();
554 let request: Vec<u8> = build_http_request(
555 HTTP_METHOD_POST,
556 path,
557 header_bytes,
558 Some(body_bytes),
559 version,
560 );
561 stream
562 .write_all(&request)
563 .await
564 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
565 stream
566 .flush()
567 .await
568 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
569 self.read_response_async(stream).await
570 }
571
572 async fn read_response_async(
582 &mut self,
583 stream: &mut BoxAsyncReadWrite,
584 ) -> Result<HttpResponse, RequestError> {
585 let buffer_size: usize = self.get_config().buffer_size;
586 let mut buffer: Vec<u8> = vec![0u8; buffer_size];
587 let mut response_bytes: Vec<u8> = Vec::with_capacity(buffer_size.max(8192));
588 let mut headers_done: bool = false;
589 let mut content_length: usize = 0usize;
590 let mut redirect_url: Option<Vec<u8>> = None;
591 let mut headers_end_pos: usize = 0usize;
592 let mut is_chunked: bool = false;
593 let version_bytes: Vec<u8> = self
594 .config
595 .get_http_version()
596 .to_string()
597 .to_ascii_lowercase()
598 .into_bytes();
599 let location_key: Vec<u8> = format!("{}:", LOCATION.to_ascii_lowercase()).into_bytes();
600 loop {
601 let n: usize = stream
602 .read(&mut buffer)
603 .await
604 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
605 if n == 0 {
606 break;
607 }
608 let new_cap: usize =
609 calculate_buffer_capacity(&response_bytes, n, response_bytes.capacity());
610 if new_cap > 0 {
611 response_bytes.reserve(new_cap - response_bytes.capacity());
612 }
613 let old_len: usize = response_bytes.len();
614 response_bytes.extend_from_slice(&buffer[..n]);
615 if !headers_done {
616 let search_start: usize = old_len.saturating_sub(3);
617 if let Some(pos) = find_double_crlf(&response_bytes, search_start) {
618 headers_done = true;
619 headers_end_pos = pos + 4;
620 parse_response_headers(
621 &response_bytes[..headers_end_pos],
622 &version_bytes,
623 &location_key,
624 &mut content_length,
625 &mut redirect_url,
626 &mut is_chunked,
627 )?;
628 }
629 }
630 if headers_done {
631 if is_chunked {
632 if Self::is_chunked_response_complete(&response_bytes[headers_end_pos..]) {
633 break;
634 }
635 } else if response_bytes.len() >= headers_end_pos + content_length {
636 response_bytes.truncate(headers_end_pos + content_length);
637 break;
638 }
639 }
640 }
641 if is_chunked {
642 let body_bytes: Vec<u8> = response_bytes[headers_end_pos..].to_vec();
643 let decoded: Vec<u8> = parse_chunked_body(&body_bytes);
644 response_bytes.truncate(headers_end_pos);
645 response_bytes.extend_from_slice(&decoded);
646 }
647 let mut response: HttpResponse = HttpResponse::from_bytes(&response_bytes);
648 if !self.get_config().get_redirect() || redirect_url.is_none() {
649 if self.get_config().get_decode() {
650 response = response.decode(self.get_config().buffer_size);
651 }
652 return Ok(response);
653 }
654 let url_bytes: Vec<u8> = redirect_url
655 .take()
656 .ok_or_else(|| RequestError::Request(MISSING_REDIRECT_URL.to_string()))?;
657 let url: String = String::from_utf8(url_bytes)
658 .map_err(|e: FromUtf8Error| RequestError::Request(e.to_string()))?;
659 self.handle_redirect_async(url).await
660 }
661
662 async fn handle_redirect_async(&mut self, url: String) -> Result<HttpResponse, RequestError> {
672 if !self.get_config().get_redirect() {
673 return Err(RequestError::Request(REDIRECT_NOT_ENABLED.to_string()));
674 }
675 if self.get_tmp().get_visit_url().contains(&url) {
676 return Err(RequestError::Request(REDIRECT_URL_DEAD_LOOP.to_string()));
677 }
678 self.get_mut_tmp().get_mut_visit_url().insert(url.clone());
679 if self.get_config().get_max_redirect_times() == 0 {
680 return Err(RequestError::Request(
681 MAX_REDIRECT_TIMES_EXCEEDED.to_string(),
682 ));
683 }
684 let remaining: usize = self.get_config().get_max_redirect_times();
685 self.get_mut_config()
686 .set_max_redirect_times(remaining.saturating_sub(1));
687 self.set_url(url);
688 Box::pin(self.send_async()).await
689 }
690
691 fn open_sync_proxy_stream(
705 &self,
706 target_host: String,
707 target_port: u16,
708 proxy: &Proxy,
709 ) -> Result<BoxReadWrite, RequestError> {
710 match *proxy.get_proxy_type() {
711 ProxyType::Http | ProxyType::Https => {
712 self.open_sync_http_proxy(target_host, target_port, proxy)
713 }
714 ProxyType::Socks5 => self.open_sync_socks5_proxy(target_host, target_port, proxy),
715 }
716 }
717
718 fn open_sync_http_proxy(
730 &self,
731 target_host: String,
732 target_port: u16,
733 proxy: &Proxy,
734 ) -> Result<BoxReadWrite, RequestError> {
735 let timeout: Duration = Duration::from_millis(self.get_config().get_timeout());
736 let tcp: TcpStream = TcpStream::connect((proxy.get_host().clone(), *proxy.get_port()))
737 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
738 tcp.set_read_timeout(Some(timeout))
739 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
740 tcp.set_write_timeout(Some(timeout))
741 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
742 let mut proxy_stream: BoxReadWrite = if proxy.get_proxy_type() == &ProxyType::Https {
743 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
744 let tls_cfg: ClientConfig = ClientConfig::builder()
745 .with_root_certificates(roots)
746 .with_no_client_auth();
747 let dns: ServerName<'static> = ServerName::try_from(proxy.get_host().clone())
748 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
749 let session: ClientConnection = ClientConnection::new(Arc::new(tls_cfg), dns)
750 .map_err(|e: rustls::Error| RequestError::Request(e.to_string()))?;
751 Box::new(StreamOwned::new(session, tcp))
752 } else {
753 Box::new(tcp)
754 };
755 let connect_request: String = if let (Some(u), Some(p)) =
756 (proxy.get_username(), proxy.get_password())
757 {
758 let auth: String = format!("{u}:{p}");
759 let encoded: String = crate::utils::base64_encode(auth.as_bytes());
760 format!(
761 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\nProxy-Authorization: Basic {encoded}\r\n\r\n"
762 )
763 } else {
764 format!(
765 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\n\r\n"
766 )
767 };
768 proxy_stream
769 .write_all(connect_request.as_bytes())
770 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
771 proxy_stream
772 .flush()
773 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
774 let mut buf: [u8; 1024] = [0u8; 1024];
775 let n: usize = proxy_stream
776 .read(&mut buf)
777 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
778 let s: &str = from_utf8(&buf[..n]).unwrap_or("");
779 let pre_read: Vec<u8> = if let Some(pos) = s.find(HEADER_TERMINATOR) {
780 let header_part: &str = &s[..pos];
781 if !header_part.starts_with(HTTP_1_1_OK_PREFIX)
782 && !header_part.starts_with(HTTP_1_0_OK_PREFIX)
783 {
784 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
785 }
786 buf[pos + 4..n].to_vec()
787 } else {
788 if !s.starts_with(HTTP_1_1_OK_PREFIX) && !s.starts_with(HTTP_1_0_OK_PREFIX) {
789 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
790 }
791 Vec::new()
792 };
793 if self.is_https() {
794 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
795 let tls_cfg: ClientConfig = ClientConfig::builder()
796 .with_root_certificates(roots)
797 .with_no_client_auth();
798 let dns: ServerName<'static> = ServerName::try_from(target_host.clone())
799 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
800 let session: ClientConnection = ClientConnection::new(Arc::new(tls_cfg), dns)
801 .map_err(|e: rustls::Error| RequestError::Request(e.to_string()))?;
802 let tunnel: SyncProxyTunnelStream = SyncProxyTunnelStream::new(proxy_stream, pre_read);
803 return Ok(Box::new(StreamOwned::new(session, tunnel)));
804 }
805 Ok(Box::new(SyncProxyTunnelStream::new(proxy_stream, pre_read)))
806 }
807
808 fn open_sync_socks5_proxy(
820 &self,
821 target_host: String,
822 target_port: u16,
823 proxy: &Proxy,
824 ) -> Result<BoxReadWrite, RequestError> {
825 let timeout: Duration = Duration::from_millis(self.get_config().get_timeout());
826 let mut tcp: TcpStream = TcpStream::connect((proxy.get_host().clone(), *proxy.get_port()))
827 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
828 tcp.set_read_timeout(Some(timeout))
829 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
830 tcp.set_write_timeout(Some(timeout))
831 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
832 let auth_methods: Vec<u8> =
833 if proxy.get_username().is_some() && proxy.get_password().is_some() {
834 vec![0x05, 0x02, 0x00, 0x02]
835 } else {
836 vec![0x05, 0x01, 0x00]
837 };
838 tcp.write_all(&auth_methods)
839 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
840 let mut resp: [u8; 2] = [0u8; 2];
841 tcp.read_exact(&mut resp)
842 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
843 if resp[0] != 0x05 {
844 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
845 }
846 match resp[1] {
847 0x00 => {}
848 0x02 => {
849 let (Some(u), Some(p)) = (proxy.get_username(), proxy.get_password()) else {
850 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
851 };
852 let mut auth_req: Vec<u8> = vec![0x01];
853 auth_req.push(u.len() as u8);
854 auth_req.extend_from_slice(u.as_bytes());
855 auth_req.push(p.len() as u8);
856 auth_req.extend_from_slice(p.as_bytes());
857 tcp.write_all(&auth_req)
858 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
859 let mut auth_resp: [u8; 2] = [0u8; 2];
860 tcp.read_exact(&mut auth_resp)
861 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
862 if auth_resp[1] != 0x00 {
863 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
864 }
865 }
866 _ => return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string())),
867 }
868 let mut connect_req: Vec<u8> = vec![0x05, 0x01, 0x00];
869 if let Ok(ip) = target_host.parse::<Ipv4Addr>() {
870 connect_req.push(0x01);
871 connect_req.extend_from_slice(&ip.octets());
872 } else if let Ok(ip) = target_host.parse::<Ipv6Addr>() {
873 connect_req.push(0x04);
874 connect_req.extend_from_slice(&ip.octets());
875 } else {
876 connect_req.push(0x03);
877 connect_req.push(target_host.len() as u8);
878 connect_req.extend_from_slice(target_host.as_bytes());
879 }
880 connect_req.extend_from_slice(&target_port.to_be_bytes());
881 tcp.write_all(&connect_req)
882 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
883 let mut connect_resp: [u8; 4] = [0u8; 4];
884 tcp.read_exact(&mut connect_resp)
885 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
886 if connect_resp[0] != 0x05 || connect_resp[1] != 0x00 {
887 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
888 }
889 match connect_resp[3] {
890 0x01 => {
891 let mut skip: [u8; 6] = [0u8; 6];
892 tcp.read_exact(&mut skip)
893 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
894 }
895 0x03 => {
896 let mut len: [u8; 1] = [0u8; 1];
897 tcp.read_exact(&mut len)
898 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
899 let mut skip: Vec<u8> = vec![0u8; len[0] as usize + 2];
900 tcp.read_exact(&mut skip)
901 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
902 }
903 0x04 => {
904 let mut skip: [u8; 18] = [0u8; 18];
905 tcp.read_exact(&mut skip)
906 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
907 }
908 _ => return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string())),
909 }
910 if self.is_https() {
911 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
912 let tls_cfg: ClientConfig = ClientConfig::builder()
913 .with_root_certificates(roots)
914 .with_no_client_auth();
915 let dns: ServerName<'static> = ServerName::try_from(target_host)
916 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
917 let session: ClientConnection = ClientConnection::new(Arc::new(tls_cfg), dns)
918 .map_err(|e: rustls::Error| RequestError::Request(e.to_string()))?;
919 let proxy_box: BoxReadWrite = Box::new(tcp);
920 let tunnel: SyncProxyTunnelStream = SyncProxyTunnelStream::new(proxy_box, Vec::new());
921 return Ok(Box::new(StreamOwned::new(session, tunnel)));
922 }
923 Ok(Box::new(tcp))
924 }
925
926 async fn open_async_proxy_stream(
940 &self,
941 target_host: String,
942 target_port: u16,
943 proxy: &Proxy,
944 ) -> Result<BoxAsyncReadWrite, RequestError> {
945 match *proxy.get_proxy_type() {
946 ProxyType::Http | ProxyType::Https => {
947 self.open_async_http_proxy(target_host, target_port, proxy)
948 .await
949 }
950 ProxyType::Socks5 => {
951 self.open_async_socks5_proxy(target_host, target_port, proxy)
952 .await
953 }
954 }
955 }
956
957 async fn open_async_http_proxy(
969 &self,
970 target_host: String,
971 target_port: u16,
972 proxy: &Proxy,
973 ) -> Result<BoxAsyncReadWrite, RequestError> {
974 let tcp: http_type::tokio::net::TcpStream = http_type::tokio::net::TcpStream::connect((
975 proxy.get_host().clone(),
976 *proxy.get_port(),
977 ))
978 .await
979 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
980 let mut proxy_stream: BoxAsyncReadWrite = if proxy.get_proxy_type() == &ProxyType::Https {
981 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
982 let tls_cfg: ClientConfig = ClientConfig::builder()
983 .with_root_certificates(roots)
984 .with_no_client_auth();
985 let connector: TlsConnector = TlsConnector::from(Arc::new(tls_cfg));
986 let dns: ServerName<'static> = ServerName::try_from(proxy.get_host().clone())
987 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
988 let tls: tokio_rustls::client::TlsStream<http_type::tokio::net::TcpStream> = connector
989 .connect(dns, tcp)
990 .await
991 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
992 Box::new(tls)
993 } else {
994 Box::new(tcp)
995 };
996 let connect_request: String = if let (Some(u), Some(p)) =
997 (proxy.get_username(), proxy.get_password())
998 {
999 let auth: String = format!("{u}:{p}");
1000 let encoded: String = crate::utils::base64_encode(auth.as_bytes());
1001 format!(
1002 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\nProxy-Authorization: Basic {encoded}\r\n\r\n"
1003 )
1004 } else {
1005 format!(
1006 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\n\r\n"
1007 )
1008 };
1009 proxy_stream
1010 .write_all(connect_request.as_bytes())
1011 .await
1012 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1013 proxy_stream
1014 .flush()
1015 .await
1016 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1017 let mut buf: [u8; 1024] = [0u8; 1024];
1018 let n: usize = proxy_stream
1019 .read(&mut buf)
1020 .await
1021 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1022 let s: &str = from_utf8(&buf[..n]).unwrap_or("");
1023 let pre_read: Vec<u8> = if let Some(pos) = s.find(HEADER_TERMINATOR) {
1024 let header_part: &str = &s[..pos];
1025 if !header_part.starts_with(HTTP_1_1_OK_PREFIX)
1026 && !header_part.starts_with(HTTP_1_0_OK_PREFIX)
1027 {
1028 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1029 }
1030 buf[pos + 4..n].to_vec()
1031 } else {
1032 if !s.starts_with(HTTP_1_1_OK_PREFIX) && !s.starts_with(HTTP_1_0_OK_PREFIX) {
1033 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1034 }
1035 Vec::new()
1036 };
1037 if self.is_https() {
1038 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
1039 let tls_cfg: ClientConfig = ClientConfig::builder()
1040 .with_root_certificates(roots)
1041 .with_no_client_auth();
1042 let connector: TlsConnector = TlsConnector::from(Arc::new(tls_cfg));
1043 let dns: ServerName<'static> = ServerName::try_from(target_host.clone())
1044 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
1045 let tunnel: ProxyTunnelStream = ProxyTunnelStream::new(proxy_stream, pre_read);
1046 let tls: tokio_rustls::client::TlsStream<ProxyTunnelStream> = connector
1047 .connect(dns, tunnel)
1048 .await
1049 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1050 Ok(Box::new(tls))
1051 } else {
1052 Ok(Box::new(ProxyTunnelStream::new(proxy_stream, pre_read)))
1053 }
1054 }
1055
1056 async fn open_async_socks5_proxy(
1068 &self,
1069 target_host: String,
1070 target_port: u16,
1071 proxy: &Proxy,
1072 ) -> Result<BoxAsyncReadWrite, RequestError> {
1073 let mut tcp: http_type::tokio::net::TcpStream = http_type::tokio::net::TcpStream::connect(
1074 (proxy.get_host().clone(), *proxy.get_port()),
1075 )
1076 .await
1077 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1078 let auth_methods: Vec<u8> =
1079 if proxy.get_username().is_some() && proxy.get_password().is_some() {
1080 vec![0x05, 0x02, 0x00, 0x02]
1081 } else {
1082 vec![0x05, 0x01, 0x00]
1083 };
1084 tcp.write_all(&auth_methods)
1085 .await
1086 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1087 let mut resp: [u8; 2] = [0u8; 2];
1088 tcp.read_exact(&mut resp)
1089 .await
1090 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1091 if resp[0] != 0x05 {
1092 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1093 }
1094 match resp[1] {
1095 0x00 => {}
1096 0x02 => {
1097 let (Some(u), Some(p)) = (proxy.get_username(), proxy.get_password()) else {
1098 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1099 };
1100 let mut auth_req: Vec<u8> = vec![0x01u8];
1101 auth_req.push(u.len() as u8);
1102 auth_req.extend_from_slice(u.as_bytes());
1103 auth_req.push(p.len() as u8);
1104 auth_req.extend_from_slice(p.as_bytes());
1105 tcp.write_all(&auth_req)
1106 .await
1107 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1108 let mut auth_resp: [u8; 2] = [0u8; 2];
1109 tcp.read_exact(&mut auth_resp)
1110 .await
1111 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1112 if auth_resp[1] != 0x00 {
1113 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1114 }
1115 }
1116 _ => return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string())),
1117 }
1118 let mut connect_req: Vec<u8> = vec![0x05, 0x01, 0x00];
1119 if let Ok(ip) = target_host.parse::<Ipv4Addr>() {
1120 connect_req.push(0x01);
1121 connect_req.extend_from_slice(&ip.octets());
1122 } else if let Ok(ip) = target_host.parse::<Ipv6Addr>() {
1123 connect_req.push(0x04);
1124 connect_req.extend_from_slice(&ip.octets());
1125 } else {
1126 connect_req.push(0x03);
1127 connect_req.push(target_host.len() as u8);
1128 connect_req.extend_from_slice(target_host.as_bytes());
1129 }
1130 connect_req.extend_from_slice(&target_port.to_be_bytes());
1131 tcp.write_all(&connect_req)
1132 .await
1133 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1134 let mut connect_resp: [u8; 4] = [0u8; 4];
1135 tcp.read_exact(&mut connect_resp)
1136 .await
1137 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1138 if connect_resp[0] != 0x05 || connect_resp[1] != 0x00 {
1139 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1140 }
1141 match connect_resp[3] {
1142 0x01 => {
1143 let mut skip: [u8; 6] = [0u8; 6];
1144 tcp.read_exact(&mut skip)
1145 .await
1146 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1147 }
1148 0x03 => {
1149 let mut len: [u8; 1] = [0u8; 1];
1150 tcp.read_exact(&mut len)
1151 .await
1152 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1153 let mut skip: Vec<u8> = vec![0u8; len[0] as usize + 2];
1154 tcp.read_exact(&mut skip)
1155 .await
1156 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1157 }
1158 0x04 => {
1159 let mut skip: [u8; 18] = [0u8; 18];
1160 tcp.read_exact(&mut skip)
1161 .await
1162 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1163 }
1164 _ => return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string())),
1165 }
1166 if self.is_https() {
1167 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
1168 let tls_cfg: ClientConfig = ClientConfig::builder()
1169 .with_root_certificates(roots)
1170 .with_no_client_auth();
1171 let connector: TlsConnector = TlsConnector::from(Arc::new(tls_cfg));
1172 let dns: ServerName<'static> = ServerName::try_from(target_host)
1173 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
1174 let proxy_box: BoxAsyncReadWrite = Box::new(tcp);
1175 let tunnel: ProxyTunnelStream = ProxyTunnelStream::new(proxy_box, Vec::new());
1176 let tls: tokio_rustls::client::TlsStream<ProxyTunnelStream> = connector
1177 .connect(dns, tunnel)
1178 .await
1179 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1180 Ok(Box::new(tls))
1181 } else {
1182 Ok(Box::new(tcp))
1183 }
1184 }
1185}
1186
1187impl HttpRequest {
1188 pub fn get<T: Into<String>>(url: T) -> Self {
1194 Self {
1195 method: Method::Get,
1196 url: url.into(),
1197 headers: HashMap::new(),
1198 body: Body::default(),
1199 config: RequestConfig::default(),
1200 tmp: Tmp::default(),
1201 }
1202 }
1203
1204 pub fn post<T: Into<String>>(url: T) -> Self {
1210 Self {
1211 method: Method::Post,
1212 url: url.into(),
1213 headers: HashMap::new(),
1214 body: Body::default(),
1215 config: RequestConfig::default(),
1216 tmp: Tmp::default(),
1217 }
1218 }
1219
1220 pub fn set_method(&mut self, method: Method) -> &mut Self {
1230 self.method = method;
1231 self
1232 }
1233
1234 pub fn set_url<T: Into<String>>(&mut self, url: T) -> &mut Self {
1244 self.url = url.into();
1245 self
1246 }
1247
1248 pub fn set_header<K: AsRef<str>, V: AsRef<str>>(&mut self, key: K, value: V) -> &mut Self {
1260 let normalized: String = Self::normalize_header_key(key.as_ref());
1261 self.headers.insert(normalized, value.as_ref().to_owned());
1262 self
1263 }
1264
1265 pub fn remove_header<K: AsRef<str>>(&mut self, key: K) -> &mut Self {
1275 let normalized: String = Self::normalize_header_key(key.as_ref());
1276 self.get_mut_headers().remove(&normalized);
1277 self
1278 }
1279
1280 pub fn clear_headers(&mut self) -> &mut Self {
1286 self.get_mut_headers().clear();
1287 self
1288 }
1289
1290 pub fn set_body(&mut self, body: Body) -> &mut Self {
1300 self.body = body;
1301 self
1302 }
1303
1304 pub fn set_config(&mut self, config: RequestConfig) -> &mut Self {
1314 self.config = config;
1315 self
1316 }
1317
1318 fn normalize_header_key(key: &str) -> String {
1329 key.to_ascii_lowercase()
1330 }
1331}