1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 //! Http network interceptor.
15 
16 use std::net::SocketAddr;
17 
18 use ylong_http::response::Response as HttpResp;
19 
20 use crate::async_impl::{HttpBody, Request, Response};
21 use crate::HttpClientError;
22 
23 pub(crate) type Interceptors = dyn Interceptor + Sync + Send + 'static;
24 
25 /// Transport layer protocol type.
26 #[derive(Clone)]
27 pub enum ConnProtocol {
28     /// Tcp protocol.
29     Tcp,
30     /// Udp Protocol.
31     Udp,
32 }
33 
34 /// Tcp connection information.
35 #[derive(Clone)]
36 pub struct ConnDetail {
37     /// Transport layer protocol type.
38     pub(crate) protocol: ConnProtocol,
39     pub(crate) alpn: Option<Vec<u8>>,
40     /// local socket address.
41     pub(crate) local: SocketAddr,
42     /// peer socket address.
43     pub(crate) peer: SocketAddr,
44     /// peer domain information.
45     pub(crate) addr: String,
46     /// Whether to use proxy.
47     pub(crate) proxy: bool,
48 }
49 
50 impl ConnDetail {
51     /// Gets the transport layer protocol for the connection.
protocol(&self) -> &ConnProtocol52     pub fn protocol(&self) -> &ConnProtocol {
53         &self.protocol
54     }
55 
56     /// Gets the local socket address of the connection.
local(&self) -> SocketAddr57     pub fn local(&self) -> SocketAddr {
58         self.local
59     }
60 
61     /// Gets the peer socket address of the connection.
peer(&self) -> SocketAddr62     pub fn peer(&self) -> SocketAddr {
63         self.peer
64     }
65 
66     /// Gets the peer domain address of the connection.
addr(&self) -> &str67     pub fn addr(&self) -> &str {
68         &self.addr
69     }
70 
71     /// Whether to use proxy.
proxy(&self) -> bool72     pub fn proxy(&self) -> bool {
73         self.proxy
74     }
75 
76     /// Whether to use tls.
alpn(&self) -> Option<&[u8]>77     pub fn alpn(&self) -> Option<&[u8]> {
78         self.alpn.as_deref()
79     }
80 }
81 
82 /// Network interceptor.
83 ///
84 /// Provides intercepting behavior at various stages of http message passing.
85 pub trait Interceptor {
86     /// Intercepts the created transport layer protocol.
87     // TODO add cache and response interceptor.
88     // Is it necessary to add a response interceptor?
89     // Does the input and output interceptor need to be added to http2 or http3
90     // encoded packets?
intercept_connection(&self, _info: ConnDetail) -> Result<(), HttpClientError>91     fn intercept_connection(&self, _info: ConnDetail) -> Result<(), HttpClientError> {
92         Ok(())
93     }
94 
95     /// Intercepts the input of transport layer io.
intercept_input(&self, _bytes: &[u8]) -> Result<(), HttpClientError>96     fn intercept_input(&self, _bytes: &[u8]) -> Result<(), HttpClientError> {
97         Ok(())
98     }
99 
100     /// Intercepts the output of transport layer io.
intercept_output(&self, _bytes: &[u8]) -> Result<(), HttpClientError>101     fn intercept_output(&self, _bytes: &[u8]) -> Result<(), HttpClientError> {
102         Ok(())
103     }
104 
105     /// Intercepts the Request that is eventually transmitted to the peer end.
intercept_request(&self, _request: &Request) -> Result<(), HttpClientError>106     fn intercept_request(&self, _request: &Request) -> Result<(), HttpClientError> {
107         Ok(())
108     }
109 
110     /// Intercepts the response that is eventually returned.
intercept_response(&self, _response: &Response) -> Result<(), HttpClientError>111     fn intercept_response(&self, _response: &Response) -> Result<(), HttpClientError> {
112         Ok(())
113     }
114 
115     /// Intercepts the error cause of the retry.
intercept_retry(&self, _error: &HttpClientError) -> Result<(), HttpClientError>116     fn intercept_retry(&self, _error: &HttpClientError) -> Result<(), HttpClientError> {
117         Ok(())
118     }
119 
120     /// Intercepts the redirect request.
intercept_redirect_request(&self, _request: &Request) -> Result<(), HttpClientError>121     fn intercept_redirect_request(&self, _request: &Request) -> Result<(), HttpClientError> {
122         Ok(())
123     }
124 
125     /// Intercepts the response returned by the redirect
intercept_redirect_response( &self, _response: &HttpResp<HttpBody>, ) -> Result<(), HttpClientError>126     fn intercept_redirect_response(
127         &self,
128         _response: &HttpResp<HttpBody>,
129     ) -> Result<(), HttpClientError> {
130         Ok(())
131     }
132 }
133 
134 /// The default Interceptor does not do any intercepting.
135 pub(crate) struct IdleInterceptor;
136 
137 impl Interceptor for IdleInterceptor {}
138