1use super::*;
2
3impl<T: AsyncRead + AsyncWrite + Unpin + Send> AsyncReadWrite for T {}
4impl<T: Read + Write> ReadWrite for T {}
5
6impl HttpRequest {
8 pub fn send(&mut self) -> RequestResult {
14 self.send_sync()
15 }
16
17 pub async fn send_async(&mut self) -> RequestResult {
23 self.send_async_impl().await
24 }
25
26 pub(crate) fn parse_url(&self) -> Result<HttpUrlComponents, RequestError> {
32 let (scheme, remainder): (&str, &str) = self
33 .get_url()
34 .split_once(SCHEME_SEPARATOR)
35 .ok_or(RequestError::InvalidUrlScheme(HttpStatus::BadRequest))?;
36 if !scheme.eq_ignore_ascii_case(HTTP_SCHEME)
37 && !scheme.eq_ignore_ascii_case(HTTPS_LOWERCASE)
38 {
39 return Err(RequestError::InvalidUrlScheme(HttpStatus::BadRequest));
40 }
41 let authority_end: usize = remainder
42 .find([URL_SLASH, URL_QUERY, URL_FRAGMENT])
43 .unwrap_or(remainder.len());
44 let authority: &str = &remainder[..authority_end];
45 if authority.is_empty()
46 || authority.contains(URL_BACKSLASH)
47 || authority
48 .bytes()
49 .any(|byte: u8| byte.is_ascii_control() || byte == SPACE_U8)
50 {
51 return Err(RequestError::InvalidUrlHost(HttpStatus::BadRequest));
52 }
53 let target: &str = remainder[authority_end..]
54 .split(URL_FRAGMENT)
55 .next()
56 .unwrap_or_default();
57 let (path, query): (&str, &str) = target
58 .split_once(URL_QUERY)
59 .unwrap_or((target, Default::default()));
60 if path
61 .bytes()
62 .any(|byte: u8| byte.is_ascii_control() || byte == SPACE_U8)
63 {
64 return Err(RequestError::InvalidUrlPath(HttpStatus::BadRequest));
65 }
66 if query
67 .bytes()
68 .any(|byte: u8| byte.is_ascii_control() || byte == SPACE_U8)
69 {
70 return Err(RequestError::InvalidUrlQuery(HttpStatus::BadRequest));
71 }
72 let components: HttpUrlComponents = match HttpUrlComponents::parse(self.get_url()) {
73 Ok(value) => value,
74 Err(_) => return Err(RequestError::InvalidUrlHost(HttpStatus::BadRequest)),
75 };
76 let host: String = components.get_host().unwrap_or_default();
77 if host.is_empty()
78 || host
79 .bytes()
80 .any(|byte: u8| byte.is_ascii_control() || byte == SPACE_U8)
81 {
82 return Err(RequestError::InvalidUrlHost(HttpStatus::BadRequest));
83 }
84 Ok(components)
85 }
86
87 pub(crate) fn full_path(&self) -> Result<String, RequestError> {
93 let url_obj: HttpUrlComponents = self.parse_url()?;
94 let query: String = url_obj.get_query().unwrap_or_default();
95 let path: String = url_obj.get_path().unwrap_or_default();
96 if query.is_empty() {
97 Ok(path)
98 } else {
99 Ok(format!("{}{}{}", path, QUERY, query))
100 }
101 }
102
103 pub(crate) fn protocol_lower(config: &RequestConfig) -> String {
113 config.get_http_version().to_string().to_ascii_lowercase()
114 }
115
116 pub(crate) fn header_bytes(&self, body_length: usize) -> Result<Vec<u8>, RequestError> {
127 let mut header: HashMap<String, String> = self.get_headers().clone();
128 let host_value: String = self.parse_url()?.get_host().unwrap_or_default();
129 let content_length_value: String = body_length.to_string();
130 if !Self::header_has_key(&header, HOST) {
131 header.insert(HOST.to_ascii_lowercase(), host_value);
132 }
133 if !Self::header_has_key(&header, CONTENT_LENGTH) {
134 header.insert(CONTENT_LENGTH.to_ascii_lowercase(), content_length_value);
135 }
136 if !Self::header_has_key(&header, ACCEPT) {
137 header.insert(ACCEPT.to_ascii_lowercase(), ACCEPT_ANY.to_owned());
138 }
139 if !Self::header_has_key(&header, USER_AGENT) {
140 header.insert(USER_AGENT.to_ascii_lowercase(), APP_NAME.to_owned());
141 }
142 validate_request_headers(&header)?;
143 let estimated_size: usize = header
144 .iter()
145 .map(|(k, v): (&String, &String)| k.len() + v.len() + 4)
146 .sum();
147 let mut out: Vec<u8> = Vec::with_capacity(estimated_size);
148 for (key, value) in &header {
149 out.extend_from_slice(key.as_bytes());
150 out.extend_from_slice(HEADER_VALUE_SEPARATOR);
151 out.extend_from_slice(value.as_bytes());
152 out.extend_from_slice(HTTP_BR_BYTES);
153 }
154 Ok(out)
155 }
156
157 fn header_has_key(header: &HashMap<String, String>, target_key: &str) -> bool {
168 header
169 .keys()
170 .any(|key: &String| key.eq_ignore_ascii_case(target_key))
171 }
172
173 pub(crate) fn body_bytes(&self) -> Vec<u8> {
180 let ct: Option<String> = self
181 .headers
182 .iter()
183 .find(|(k, _): &(&String, &String)| k.eq_ignore_ascii_case(CONTENT_TYPE))
184 .map(|(_, v): (&String, &String)| v.clone());
185 match ct {
186 Some(value) => value
187 .to_lowercase()
188 .parse::<ContentType>()
189 .unwrap_or_default()
190 .get_body_string(&String::from_utf8_lossy(self.get_body().as_slice()))
191 .into_bytes(),
192 None => Vec::new(),
193 }
194 }
195
196 pub(crate) fn send_sync(&mut self) -> RequestResult {
202 let url_obj: HttpUrlComponents = self.parse_url()?;
203 validate_request_headers(self.get_headers())?;
204 let host: String = url_obj.get_host().clone().unwrap_or_default();
205 let port: u16 = self.resolve_port(url_obj.get_port().unwrap_or_default());
206 let mut stream: BoxReadWrite = self.open_sync_stream(host, port)?;
207 let method: Method = self.get_method();
208 if method.is_get() {
209 self.send_get_request_sync(&mut stream)
210 } else if method.is_post() {
211 self.send_post_request_sync(&mut stream)
212 } else {
213 Err(RequestError::Request(METHOD_NOT_ALLOWED.to_string()))
214 }
215 }
216
217 async fn send_async_impl(&mut self) -> RequestResult {
223 let url_obj: HttpUrlComponents = self.parse_url()?;
224 validate_request_headers(self.get_headers())?;
225 let host: String = url_obj.get_host().clone().unwrap_or_default();
226 let port: u16 = self.resolve_port(url_obj.get_port().unwrap_or_default());
227 let mut stream: BoxAsyncReadWrite = self.open_async_stream(host, port).await?;
228 let method: Method = self.get_method();
229 if method.is_get() {
230 self.send_get_request_async(&mut stream).await
231 } else if method.is_post() {
232 self.send_post_request_async(&mut stream).await
233 } else {
234 Err(RequestError::Request(METHOD_NOT_ALLOWED.to_string()))
235 }
236 }
237
238 fn resolve_port(&self, port: u16) -> u16 {
248 if port != 0 {
249 return port;
250 }
251 let protocol: String = Self::protocol_lower(self.get_config());
252 Protocol::get_port(&protocol)
253 }
254
255 fn is_https(&self) -> bool {
261 Self::protocol_lower(self.get_config()) == HTTPS_LOWERCASE
262 }
263
264 fn open_sync_stream(&self, host: String, port: u16) -> Result<BoxReadWrite, RequestError> {
277 if let Some(proxy) = &self.get_config().get_proxy() {
278 return self.open_sync_proxy_stream(host, port, proxy);
279 }
280 let timeout: Duration = Duration::from_millis(self.get_config().get_timeout());
281 let tcp: TcpStream = TcpStream::connect((host.clone(), port))
282 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
283 tcp.set_read_timeout(Some(timeout))
284 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
285 tcp.set_write_timeout(Some(timeout))
286 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
287 if self.is_https() {
288 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
289 let tls_cfg: ClientConfig = ClientConfig::builder()
290 .with_root_certificates(roots)
291 .with_no_client_auth();
292 let dns: ServerName<'static> = ServerName::try_from(host.clone())
293 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
294 let session: ClientConnection = ClientConnection::new(Arc::new(tls_cfg), dns)
295 .map_err(|e: rustls::Error| RequestError::Request(e.to_string()))?;
296 Ok(Box::new(StreamOwned::new(session, tcp)))
297 } else {
298 Ok(Box::new(tcp))
299 }
300 }
301
302 fn send_get_request_sync(
312 &mut self,
313 stream: &mut BoxReadWrite,
314 ) -> Result<HttpResponse, RequestError> {
315 let path: String = self.full_path()?;
316 let header_bytes: Vec<u8> = self.header_bytes(0)?;
317 let version: String = self.get_config().get_http_version().to_string();
318 let request: Vec<u8> = build_http_request("GET", path, header_bytes, None, version);
319 stream
320 .write_all(&request)
321 .and_then(|_: ()| stream.flush())
322 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
323 self.read_response_sync(stream)
324 }
325
326 fn send_post_request_sync(
336 &mut self,
337 stream: &mut BoxReadWrite,
338 ) -> Result<HttpResponse, RequestError> {
339 let body_bytes: Vec<u8> = self.body_bytes();
340 let path: String = self.full_path()?;
341 let header_bytes: Vec<u8> = self.header_bytes(body_bytes.len())?;
342 let version: String = self.get_config().get_http_version().to_string();
343 let request: Vec<u8> = build_http_request(
344 HTTP_METHOD_POST,
345 path,
346 header_bytes,
347 Some(body_bytes),
348 version,
349 );
350 stream
351 .write_all(&request)
352 .and_then(|_: ()| stream.flush())
353 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
354 self.read_response_sync(stream)
355 }
356
357 fn read_response_sync(
367 &mut self,
368 stream: &mut BoxReadWrite,
369 ) -> Result<HttpResponse, RequestError> {
370 let buffer_size: usize = self.get_config().buffer_size;
371 let mut buffer: Vec<u8> = vec![0u8; buffer_size];
372 let mut response_bytes: Vec<u8> = Vec::with_capacity(buffer_size.max(8192));
373 let mut headers_done: bool = false;
374 let mut content_length: usize = 0usize;
375 let mut redirect_url: Option<Vec<u8>> = None;
376 let mut headers_end_pos: usize = 0usize;
377 let mut is_chunked: bool = false;
378 let version_bytes: Vec<u8> = self
379 .config
380 .get_http_version()
381 .to_string()
382 .to_ascii_lowercase()
383 .into_bytes();
384 let location_key: Vec<u8> = format!("{}:", LOCATION.to_ascii_lowercase()).into_bytes();
385 loop {
386 let n: usize = stream
387 .read(&mut buffer)
388 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
389 if n == 0 {
390 break;
391 }
392 let new_cap: usize =
393 calculate_buffer_capacity(&response_bytes, n, response_bytes.capacity());
394 if new_cap > 0 {
395 response_bytes.reserve(new_cap - response_bytes.capacity());
396 }
397 let old_len: usize = response_bytes.len();
398 response_bytes.extend_from_slice(&buffer[..n]);
399 if !headers_done {
400 let search_start: usize = old_len.saturating_sub(3);
401 if let Some(pos) = find_double_crlf(&response_bytes, search_start) {
402 headers_done = true;
403 headers_end_pos = pos + 4;
404 parse_response_headers(
405 &response_bytes[..headers_end_pos],
406 &version_bytes,
407 &location_key,
408 &mut content_length,
409 &mut redirect_url,
410 &mut is_chunked,
411 )?;
412 }
413 }
414 if headers_done {
415 if is_chunked {
416 if Self::is_chunked_response_complete(&response_bytes[headers_end_pos..])? {
417 break;
418 }
419 } else if response_bytes.len() >= headers_end_pos + content_length {
420 response_bytes.truncate(headers_end_pos + content_length);
421 break;
422 }
423 }
424 }
425 if !headers_done {
426 return Err(RequestError::HttpRequestPartsInsufficient(
427 HttpStatus::BadRequest,
428 ));
429 }
430 if !is_chunked && response_bytes.len() < headers_end_pos + content_length {
431 return Err(RequestError::InvalidContentLength(HttpStatus::BadRequest));
432 }
433 if is_chunked {
434 let body_bytes: Vec<u8> = response_bytes[headers_end_pos..].to_vec();
435 let decoded: Vec<u8> = parse_chunked_body(&body_bytes)?;
436 response_bytes.truncate(headers_end_pos);
437 response_bytes.extend_from_slice(&decoded);
438 }
439 let mut response: HttpResponse = HttpResponse::from_bytes(&response_bytes);
440 if !self.get_config().get_redirect() || redirect_url.is_none() {
441 if self.get_config().get_decode() {
442 response = response.decode(self.get_config().buffer_size);
443 }
444 return Ok(response);
445 }
446 let url_bytes: Vec<u8> = redirect_url
447 .take()
448 .ok_or_else(|| RequestError::Request(MISSING_REDIRECT_URL.to_string()))?;
449 let url: String = String::from_utf8(url_bytes)
450 .map_err(|e: FromUtf8Error| RequestError::Request(e.to_string()))?;
451 self.handle_redirect(url)
452 }
453
454 fn handle_redirect(&mut self, url: String) -> Result<HttpResponse, RequestError> {
464 if !self.get_config().get_redirect() {
465 return Err(RequestError::Request(REDIRECT_NOT_ENABLED.to_string()));
466 }
467 if self.get_tmp().get_visit_url().contains(&url) {
468 return Err(RequestError::Request(REDIRECT_URL_DEAD_LOOP.to_string()));
469 }
470 self.get_mut_tmp().get_mut_visit_url().insert(url.clone());
471 if self.get_config().get_max_redirect_times() == 0 {
472 return Err(RequestError::Request(
473 MAX_REDIRECT_TIMES_EXCEEDED.to_string(),
474 ));
475 }
476 let remaining: usize = self.get_config().get_max_redirect_times();
477 self.get_mut_config()
478 .set_max_redirect_times(remaining.saturating_sub(1));
479 self.set_url(url);
480 self.send_sync()
481 }
482
483 fn is_chunked_response_complete(body_bytes: &[u8]) -> Result<bool, RequestError> {
493 chunked_body_end(body_bytes).map(|end: Option<usize>| end.is_some())
494 }
495
496 async fn open_async_stream(
509 &self,
510 host: String,
511 port: u16,
512 ) -> Result<BoxAsyncReadWrite, RequestError> {
513 if let Some(proxy) = &self.get_config().get_proxy() {
514 return self.open_async_proxy_stream(host, port, proxy).await;
515 }
516 let tcp: http_type::tokio::net::TcpStream =
517 http_type::tokio::net::TcpStream::connect((host.clone(), port))
518 .await
519 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
520 if self.is_https() {
521 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
522 let tls_cfg: ClientConfig = ClientConfig::builder()
523 .with_root_certificates(roots)
524 .with_no_client_auth();
525 let connector: TlsConnector = TlsConnector::from(Arc::new(tls_cfg));
526 let dns: ServerName<'static> = ServerName::try_from(host.clone())
527 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
528 let tls: tokio_rustls::client::TlsStream<http_type::tokio::net::TcpStream> = connector
529 .connect(dns, tcp)
530 .await
531 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
532 Ok(Box::new(tls))
533 } else {
534 Ok(Box::new(tcp))
535 }
536 }
537
538 async fn send_get_request_async(
548 &mut self,
549 stream: &mut BoxAsyncReadWrite,
550 ) -> Result<HttpResponse, RequestError> {
551 let path: String = self.full_path()?;
552 let header_bytes: Vec<u8> = self.header_bytes(0)?;
553 let version: String = self.get_config().get_http_version().to_string();
554 let request: Vec<u8> = build_http_request("GET", path, header_bytes, None, version);
555 stream
556 .write_all(&request)
557 .await
558 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
559 stream
560 .flush()
561 .await
562 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
563 self.read_response_async(stream).await
564 }
565
566 async fn send_post_request_async(
576 &mut self,
577 stream: &mut BoxAsyncReadWrite,
578 ) -> Result<HttpResponse, RequestError> {
579 let body_bytes: Vec<u8> = self.body_bytes();
580 let path: String = self.full_path()?;
581 let header_bytes: Vec<u8> = self.header_bytes(body_bytes.len())?;
582 let version: String = self.get_config().get_http_version().to_string();
583 let request: Vec<u8> = build_http_request(
584 HTTP_METHOD_POST,
585 path,
586 header_bytes,
587 Some(body_bytes),
588 version,
589 );
590 stream
591 .write_all(&request)
592 .await
593 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
594 stream
595 .flush()
596 .await
597 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
598 self.read_response_async(stream).await
599 }
600
601 async fn read_response_async(
611 &mut self,
612 stream: &mut BoxAsyncReadWrite,
613 ) -> Result<HttpResponse, RequestError> {
614 let buffer_size: usize = self.get_config().buffer_size;
615 let mut buffer: Vec<u8> = vec![0u8; buffer_size];
616 let mut response_bytes: Vec<u8> = Vec::with_capacity(buffer_size.max(8192));
617 let mut headers_done: bool = false;
618 let mut content_length: usize = 0usize;
619 let mut redirect_url: Option<Vec<u8>> = None;
620 let mut headers_end_pos: usize = 0usize;
621 let mut is_chunked: bool = false;
622 let version_bytes: Vec<u8> = self
623 .config
624 .get_http_version()
625 .to_string()
626 .to_ascii_lowercase()
627 .into_bytes();
628 let location_key: Vec<u8> = format!("{}:", LOCATION.to_ascii_lowercase()).into_bytes();
629 loop {
630 let n: usize = stream
631 .read(&mut buffer)
632 .await
633 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
634 if n == 0 {
635 break;
636 }
637 let new_cap: usize =
638 calculate_buffer_capacity(&response_bytes, n, response_bytes.capacity());
639 if new_cap > 0 {
640 response_bytes.reserve(new_cap - response_bytes.capacity());
641 }
642 let old_len: usize = response_bytes.len();
643 response_bytes.extend_from_slice(&buffer[..n]);
644 if !headers_done {
645 let search_start: usize = old_len.saturating_sub(3);
646 if let Some(pos) = find_double_crlf(&response_bytes, search_start) {
647 headers_done = true;
648 headers_end_pos = pos + 4;
649 parse_response_headers(
650 &response_bytes[..headers_end_pos],
651 &version_bytes,
652 &location_key,
653 &mut content_length,
654 &mut redirect_url,
655 &mut is_chunked,
656 )?;
657 }
658 }
659 if headers_done {
660 if is_chunked {
661 if Self::is_chunked_response_complete(&response_bytes[headers_end_pos..])? {
662 break;
663 }
664 } else if response_bytes.len() >= headers_end_pos + content_length {
665 response_bytes.truncate(headers_end_pos + content_length);
666 break;
667 }
668 }
669 }
670 if !headers_done {
671 return Err(RequestError::HttpRequestPartsInsufficient(
672 HttpStatus::BadRequest,
673 ));
674 }
675 if !is_chunked && response_bytes.len() < headers_end_pos + content_length {
676 return Err(RequestError::InvalidContentLength(HttpStatus::BadRequest));
677 }
678 if is_chunked {
679 let body_bytes: Vec<u8> = response_bytes[headers_end_pos..].to_vec();
680 let decoded: Vec<u8> = parse_chunked_body(&body_bytes)?;
681 response_bytes.truncate(headers_end_pos);
682 response_bytes.extend_from_slice(&decoded);
683 }
684 let mut response: HttpResponse = HttpResponse::from_bytes(&response_bytes);
685 if !self.get_config().get_redirect() || redirect_url.is_none() {
686 if self.get_config().get_decode() {
687 response = response.decode(self.get_config().buffer_size);
688 }
689 return Ok(response);
690 }
691 let url_bytes: Vec<u8> = redirect_url
692 .take()
693 .ok_or_else(|| RequestError::Request(MISSING_REDIRECT_URL.to_string()))?;
694 let url: String = String::from_utf8(url_bytes)
695 .map_err(|e: FromUtf8Error| RequestError::Request(e.to_string()))?;
696 self.handle_redirect_async(url).await
697 }
698
699 async fn handle_redirect_async(&mut self, url: String) -> Result<HttpResponse, RequestError> {
709 if !self.get_config().get_redirect() {
710 return Err(RequestError::Request(REDIRECT_NOT_ENABLED.to_string()));
711 }
712 if self.get_tmp().get_visit_url().contains(&url) {
713 return Err(RequestError::Request(REDIRECT_URL_DEAD_LOOP.to_string()));
714 }
715 self.get_mut_tmp().get_mut_visit_url().insert(url.clone());
716 if self.get_config().get_max_redirect_times() == 0 {
717 return Err(RequestError::Request(
718 MAX_REDIRECT_TIMES_EXCEEDED.to_string(),
719 ));
720 }
721 let remaining: usize = self.get_config().get_max_redirect_times();
722 self.get_mut_config()
723 .set_max_redirect_times(remaining.saturating_sub(1));
724 self.set_url(url);
725 Box::pin(self.send_async()).await
726 }
727
728 fn open_sync_proxy_stream(
742 &self,
743 target_host: String,
744 target_port: u16,
745 proxy: &Proxy,
746 ) -> Result<BoxReadWrite, RequestError> {
747 match *proxy.get_proxy_type() {
748 ProxyType::Http | ProxyType::Https => {
749 self.open_sync_http_proxy(target_host, target_port, proxy)
750 }
751 ProxyType::Socks5 => self.open_sync_socks5_proxy(target_host, target_port, proxy),
752 }
753 }
754
755 fn open_sync_http_proxy(
767 &self,
768 target_host: String,
769 target_port: u16,
770 proxy: &Proxy,
771 ) -> Result<BoxReadWrite, RequestError> {
772 let timeout: Duration = Duration::from_millis(self.get_config().get_timeout());
773 let tcp: TcpStream = TcpStream::connect((proxy.get_host().clone(), proxy.get_port()))
774 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
775 tcp.set_read_timeout(Some(timeout))
776 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
777 tcp.set_write_timeout(Some(timeout))
778 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
779 let mut proxy_stream: BoxReadWrite = if proxy.get_proxy_type() == &ProxyType::Https {
780 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
781 let tls_cfg: ClientConfig = ClientConfig::builder()
782 .with_root_certificates(roots)
783 .with_no_client_auth();
784 let dns: ServerName<'static> = ServerName::try_from(proxy.get_host().clone())
785 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
786 let session: ClientConnection = ClientConnection::new(Arc::new(tls_cfg), dns)
787 .map_err(|e: rustls::Error| RequestError::Request(e.to_string()))?;
788 Box::new(StreamOwned::new(session, tcp))
789 } else {
790 Box::new(tcp)
791 };
792 let connect_request: String = if let (Some(u), Some(p)) =
793 (proxy.get_username(), proxy.get_password())
794 {
795 let auth: String = format!("{u}:{p}");
796 let encoded: String = crate::utils::base64_encode(auth.as_bytes());
797 format!(
798 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\nProxy-Authorization: Basic {encoded}\r\n\r\n"
799 )
800 } else {
801 format!(
802 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\n\r\n"
803 )
804 };
805 proxy_stream
806 .write_all(connect_request.as_bytes())
807 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
808 proxy_stream
809 .flush()
810 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
811 let mut buf: [u8; 1024] = [0u8; 1024];
812 let n: usize = proxy_stream
813 .read(&mut buf)
814 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
815 let s: &str = from_utf8(&buf[..n]).unwrap_or("");
816 let pre_read: Vec<u8> = if let Some(pos) = s.find(HEADER_TERMINATOR) {
817 let header_part: &str = &s[..pos];
818 if !header_part.starts_with(HTTP_1_1_OK_PREFIX)
819 && !header_part.starts_with(HTTP_1_0_OK_PREFIX)
820 {
821 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
822 }
823 buf[pos + 4..n].to_vec()
824 } else {
825 if !s.starts_with(HTTP_1_1_OK_PREFIX) && !s.starts_with(HTTP_1_0_OK_PREFIX) {
826 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
827 }
828 Vec::new()
829 };
830 if self.is_https() {
831 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
832 let tls_cfg: ClientConfig = ClientConfig::builder()
833 .with_root_certificates(roots)
834 .with_no_client_auth();
835 let dns: ServerName<'static> = ServerName::try_from(target_host.clone())
836 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
837 let session: ClientConnection = ClientConnection::new(Arc::new(tls_cfg), dns)
838 .map_err(|e: rustls::Error| RequestError::Request(e.to_string()))?;
839 let tunnel: SyncProxyTunnelStream = SyncProxyTunnelStream::new(proxy_stream, pre_read);
840 return Ok(Box::new(StreamOwned::new(session, tunnel)));
841 }
842 Ok(Box::new(SyncProxyTunnelStream::new(proxy_stream, pre_read)))
843 }
844
845 fn open_sync_socks5_proxy(
857 &self,
858 target_host: String,
859 target_port: u16,
860 proxy: &Proxy,
861 ) -> Result<BoxReadWrite, RequestError> {
862 let timeout: Duration = Duration::from_millis(self.get_config().get_timeout());
863 let mut tcp: TcpStream = TcpStream::connect((proxy.get_host().clone(), proxy.get_port()))
864 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
865 tcp.set_read_timeout(Some(timeout))
866 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
867 tcp.set_write_timeout(Some(timeout))
868 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
869 let auth_methods: Vec<u8> =
870 if proxy.get_username().is_some() && proxy.get_password().is_some() {
871 vec![0x05, 0x02, 0x00, 0x02]
872 } else {
873 vec![0x05, 0x01, 0x00]
874 };
875 tcp.write_all(&auth_methods)
876 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
877 let mut resp: [u8; 2] = [0u8; 2];
878 tcp.read_exact(&mut resp)
879 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
880 if resp[0] != 0x05 {
881 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
882 }
883 match resp[1] {
884 0x00 => {}
885 0x02 => {
886 let (Some(u), Some(p)) = (proxy.get_username(), proxy.get_password()) else {
887 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
888 };
889 let mut auth_req: Vec<u8> = vec![0x01];
890 auth_req.push(u.len() as u8);
891 auth_req.extend_from_slice(u.as_bytes());
892 auth_req.push(p.len() as u8);
893 auth_req.extend_from_slice(p.as_bytes());
894 tcp.write_all(&auth_req)
895 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
896 let mut auth_resp: [u8; 2] = [0u8; 2];
897 tcp.read_exact(&mut auth_resp)
898 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
899 if auth_resp[1] != 0x00 {
900 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
901 }
902 }
903 _ => return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string())),
904 }
905 let mut connect_req: Vec<u8> = vec![0x05, 0x01, 0x00];
906 if let Ok(ip) = target_host.parse::<Ipv4Addr>() {
907 connect_req.push(0x01);
908 connect_req.extend_from_slice(&ip.octets());
909 } else if let Ok(ip) = target_host.parse::<Ipv6Addr>() {
910 connect_req.push(0x04);
911 connect_req.extend_from_slice(&ip.octets());
912 } else {
913 connect_req.push(0x03);
914 connect_req.push(target_host.len() as u8);
915 connect_req.extend_from_slice(target_host.as_bytes());
916 }
917 connect_req.extend_from_slice(&target_port.to_be_bytes());
918 tcp.write_all(&connect_req)
919 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
920 let mut connect_resp: [u8; 4] = [0u8; 4];
921 tcp.read_exact(&mut connect_resp)
922 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
923 if connect_resp[0] != 0x05 || connect_resp[1] != 0x00 {
924 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
925 }
926 match connect_resp[3] {
927 0x01 => {
928 let mut skip: [u8; 6] = [0u8; 6];
929 tcp.read_exact(&mut skip)
930 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
931 }
932 0x03 => {
933 let mut len: [u8; 1] = [0u8; 1];
934 tcp.read_exact(&mut len)
935 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
936 let mut skip: Vec<u8> = vec![0u8; len[0] as usize + 2];
937 tcp.read_exact(&mut skip)
938 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
939 }
940 0x04 => {
941 let mut skip: [u8; 18] = [0u8; 18];
942 tcp.read_exact(&mut skip)
943 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
944 }
945 _ => return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string())),
946 }
947 if self.is_https() {
948 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
949 let tls_cfg: ClientConfig = ClientConfig::builder()
950 .with_root_certificates(roots)
951 .with_no_client_auth();
952 let dns: ServerName<'static> = ServerName::try_from(target_host)
953 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
954 let session: ClientConnection = ClientConnection::new(Arc::new(tls_cfg), dns)
955 .map_err(|e: rustls::Error| RequestError::Request(e.to_string()))?;
956 let proxy_box: BoxReadWrite = Box::new(tcp);
957 let tunnel: SyncProxyTunnelStream = SyncProxyTunnelStream::new(proxy_box, Vec::new());
958 return Ok(Box::new(StreamOwned::new(session, tunnel)));
959 }
960 Ok(Box::new(tcp))
961 }
962
963 async fn open_async_proxy_stream(
977 &self,
978 target_host: String,
979 target_port: u16,
980 proxy: &Proxy,
981 ) -> Result<BoxAsyncReadWrite, RequestError> {
982 match *proxy.get_proxy_type() {
983 ProxyType::Http | ProxyType::Https => {
984 self.open_async_http_proxy(target_host, target_port, proxy)
985 .await
986 }
987 ProxyType::Socks5 => {
988 self.open_async_socks5_proxy(target_host, target_port, proxy)
989 .await
990 }
991 }
992 }
993
994 async fn open_async_http_proxy(
1006 &self,
1007 target_host: String,
1008 target_port: u16,
1009 proxy: &Proxy,
1010 ) -> Result<BoxAsyncReadWrite, RequestError> {
1011 let tcp: http_type::tokio::net::TcpStream =
1012 http_type::tokio::net::TcpStream::connect((proxy.get_host().clone(), proxy.get_port()))
1013 .await
1014 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1015 let mut proxy_stream: BoxAsyncReadWrite = if proxy.get_proxy_type() == &ProxyType::Https {
1016 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
1017 let tls_cfg: ClientConfig = ClientConfig::builder()
1018 .with_root_certificates(roots)
1019 .with_no_client_auth();
1020 let connector: TlsConnector = TlsConnector::from(Arc::new(tls_cfg));
1021 let dns: ServerName<'static> = ServerName::try_from(proxy.get_host().clone())
1022 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
1023 let tls: tokio_rustls::client::TlsStream<http_type::tokio::net::TcpStream> = connector
1024 .connect(dns, tcp)
1025 .await
1026 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1027 Box::new(tls)
1028 } else {
1029 Box::new(tcp)
1030 };
1031 let connect_request: String = if let (Some(u), Some(p)) =
1032 (proxy.get_username(), proxy.get_password())
1033 {
1034 let auth: String = format!("{u}:{p}");
1035 let encoded: String = crate::utils::base64_encode(auth.as_bytes());
1036 format!(
1037 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\nProxy-Authorization: Basic {encoded}\r\n\r\n"
1038 )
1039 } else {
1040 format!(
1041 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\n\r\n"
1042 )
1043 };
1044 proxy_stream
1045 .write_all(connect_request.as_bytes())
1046 .await
1047 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1048 proxy_stream
1049 .flush()
1050 .await
1051 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1052 let mut buf: [u8; 1024] = [0u8; 1024];
1053 let n: usize = proxy_stream
1054 .read(&mut buf)
1055 .await
1056 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1057 let s: &str = from_utf8(&buf[..n]).unwrap_or("");
1058 let pre_read: Vec<u8> = if let Some(pos) = s.find(HEADER_TERMINATOR) {
1059 let header_part: &str = &s[..pos];
1060 if !header_part.starts_with(HTTP_1_1_OK_PREFIX)
1061 && !header_part.starts_with(HTTP_1_0_OK_PREFIX)
1062 {
1063 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1064 }
1065 buf[pos + 4..n].to_vec()
1066 } else {
1067 if !s.starts_with(HTTP_1_1_OK_PREFIX) && !s.starts_with(HTTP_1_0_OK_PREFIX) {
1068 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1069 }
1070 Vec::new()
1071 };
1072 if self.is_https() {
1073 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
1074 let tls_cfg: ClientConfig = ClientConfig::builder()
1075 .with_root_certificates(roots)
1076 .with_no_client_auth();
1077 let connector: TlsConnector = TlsConnector::from(Arc::new(tls_cfg));
1078 let dns: ServerName<'static> = ServerName::try_from(target_host.clone())
1079 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
1080 let tunnel: ProxyTunnelStream = ProxyTunnelStream::new(proxy_stream, pre_read);
1081 let tls: tokio_rustls::client::TlsStream<ProxyTunnelStream> = connector
1082 .connect(dns, tunnel)
1083 .await
1084 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1085 Ok(Box::new(tls))
1086 } else {
1087 Ok(Box::new(ProxyTunnelStream::new(proxy_stream, pre_read)))
1088 }
1089 }
1090
1091 async fn open_async_socks5_proxy(
1103 &self,
1104 target_host: String,
1105 target_port: u16,
1106 proxy: &Proxy,
1107 ) -> Result<BoxAsyncReadWrite, RequestError> {
1108 let mut tcp: http_type::tokio::net::TcpStream =
1109 http_type::tokio::net::TcpStream::connect((proxy.get_host().clone(), proxy.get_port()))
1110 .await
1111 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1112 let auth_methods: Vec<u8> =
1113 if proxy.get_username().is_some() && proxy.get_password().is_some() {
1114 vec![0x05, 0x02, 0x00, 0x02]
1115 } else {
1116 vec![0x05, 0x01, 0x00]
1117 };
1118 tcp.write_all(&auth_methods)
1119 .await
1120 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1121 let mut resp: [u8; 2] = [0u8; 2];
1122 tcp.read_exact(&mut resp)
1123 .await
1124 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1125 if resp[0] != 0x05 {
1126 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1127 }
1128 match resp[1] {
1129 0x00 => {}
1130 0x02 => {
1131 let (Some(u), Some(p)) = (proxy.get_username(), proxy.get_password()) else {
1132 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1133 };
1134 let mut auth_req: Vec<u8> = vec![0x01u8];
1135 auth_req.push(u.len() as u8);
1136 auth_req.extend_from_slice(u.as_bytes());
1137 auth_req.push(p.len() as u8);
1138 auth_req.extend_from_slice(p.as_bytes());
1139 tcp.write_all(&auth_req)
1140 .await
1141 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1142 let mut auth_resp: [u8; 2] = [0u8; 2];
1143 tcp.read_exact(&mut auth_resp)
1144 .await
1145 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1146 if auth_resp[1] != 0x00 {
1147 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1148 }
1149 }
1150 _ => return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string())),
1151 }
1152 let mut connect_req: Vec<u8> = vec![0x05, 0x01, 0x00];
1153 if let Ok(ip) = target_host.parse::<Ipv4Addr>() {
1154 connect_req.push(0x01);
1155 connect_req.extend_from_slice(&ip.octets());
1156 } else if let Ok(ip) = target_host.parse::<Ipv6Addr>() {
1157 connect_req.push(0x04);
1158 connect_req.extend_from_slice(&ip.octets());
1159 } else {
1160 connect_req.push(0x03);
1161 connect_req.push(target_host.len() as u8);
1162 connect_req.extend_from_slice(target_host.as_bytes());
1163 }
1164 connect_req.extend_from_slice(&target_port.to_be_bytes());
1165 tcp.write_all(&connect_req)
1166 .await
1167 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1168 let mut connect_resp: [u8; 4] = [0u8; 4];
1169 tcp.read_exact(&mut connect_resp)
1170 .await
1171 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1172 if connect_resp[0] != 0x05 || connect_resp[1] != 0x00 {
1173 return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string()));
1174 }
1175 match connect_resp[3] {
1176 0x01 => {
1177 let mut skip: [u8; 6] = [0u8; 6];
1178 tcp.read_exact(&mut skip)
1179 .await
1180 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1181 }
1182 0x03 => {
1183 let mut len: [u8; 1] = [0u8; 1];
1184 tcp.read_exact(&mut len)
1185 .await
1186 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1187 let mut skip: Vec<u8> = vec![0u8; len[0] as usize + 2];
1188 tcp.read_exact(&mut skip)
1189 .await
1190 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1191 }
1192 0x04 => {
1193 let mut skip: [u8; 18] = [0u8; 18];
1194 tcp.read_exact(&mut skip)
1195 .await
1196 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1197 }
1198 _ => return Err(RequestError::Request(INTERNAL_SERVER_ERROR.to_string())),
1199 }
1200 if self.is_https() {
1201 let roots: RootCertStore = self.get_tmp().get_root_cert().clone();
1202 let tls_cfg: ClientConfig = ClientConfig::builder()
1203 .with_root_certificates(roots)
1204 .with_no_client_auth();
1205 let connector: TlsConnector = TlsConnector::from(Arc::new(tls_cfg));
1206 let dns: ServerName<'static> = ServerName::try_from(target_host)
1207 .map_err(|e: InvalidDnsNameError| RequestError::Request(e.to_string()))?;
1208 let proxy_box: BoxAsyncReadWrite = Box::new(tcp);
1209 let tunnel: ProxyTunnelStream = ProxyTunnelStream::new(proxy_box, Vec::new());
1210 let tls: tokio_rustls::client::TlsStream<ProxyTunnelStream> = connector
1211 .connect(dns, tunnel)
1212 .await
1213 .map_err(|e: io::Error| RequestError::Request(e.to_string()))?;
1214 Ok(Box::new(tls))
1215 } else {
1216 Ok(Box::new(tcp))
1217 }
1218 }
1219}
1220
1221impl HttpRequest {
1223 pub fn get<T: Into<String>>(url: T) -> Self {
1229 Self {
1230 method: Method::Get,
1231 url: url.into(),
1232 headers: HashMap::new(),
1233 body: Body::default(),
1234 config: RequestConfig::default(),
1235 tmp: Tmp::default(),
1236 }
1237 }
1238
1239 pub fn post<T: Into<String>>(url: T) -> Self {
1245 Self {
1246 method: Method::Post,
1247 url: url.into(),
1248 headers: HashMap::new(),
1249 body: Body::default(),
1250 config: RequestConfig::default(),
1251 tmp: Tmp::default(),
1252 }
1253 }
1254
1255 pub fn set_method(&mut self, method: Method) -> &mut Self {
1265 self.method = method;
1266 self
1267 }
1268
1269 pub fn set_url<T: Into<String>>(&mut self, url: T) -> &mut Self {
1279 self.url = url.into();
1280 self
1281 }
1282
1283 pub fn set_header<K: AsRef<str>, V: AsRef<str>>(&mut self, key: K, value: V) -> &mut Self {
1295 let normalized: String = Self::normalize_header_key(key.as_ref());
1296 self.headers.insert(normalized, value.as_ref().to_owned());
1297 self
1298 }
1299
1300 pub fn remove_header<K: AsRef<str>>(&mut self, key: K) -> &mut Self {
1310 let normalized: String = Self::normalize_header_key(key.as_ref());
1311 self.get_mut_headers().remove(&normalized);
1312 self
1313 }
1314
1315 pub fn clear_headers(&mut self) -> &mut Self {
1321 self.get_mut_headers().clear();
1322 self
1323 }
1324
1325 pub fn set_body(&mut self, body: Body) -> &mut Self {
1335 self.body = body;
1336 self
1337 }
1338
1339 pub fn set_config(&mut self, config: RequestConfig) -> &mut Self {
1349 self.config = config;
1350 self
1351 }
1352
1353 fn normalize_header_key(key: &str) -> String {
1364 key.to_ascii_lowercase()
1365 }
1366}