Skip to content

Commit

Permalink
add support to defined h2 method using configs
Browse files Browse the repository at this point in the history
  • Loading branch information
shiroedev2024 committed Apr 27, 2024
1 parent 085810d commit 72859d2
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 11 deletions.
1 change: 1 addition & 0 deletions leaf/src/app/outbound/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ impl OutboundManager {
.map_err(|e| anyhow!("invalid [{}] outbound settings: {}", &tag, e))?;
let stream = Box::new(h2::outbound::StreamHandler {
path: settings.path.clone(),
method: settings.method.clone(),
headers: settings.headers.clone(),
});
HandlerBuilder::default()
Expand Down
11 changes: 11 additions & 0 deletions leaf/src/config/conf/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub struct Proxy {
pub h2: Option<bool>,
pub h2_path: Option<String>,
pub h2_host: Option<String>,
pub h2_method: Option<String>,

// trojan
pub sni: Option<String>,
Expand Down Expand Up @@ -112,6 +113,7 @@ impl Default for Proxy {
h2: Some(false),
h2_host: None,
h2_path: None,
h2_method: Some("PUT".to_string()),
sni: None,
username: None,
amux: Some(false),
Expand Down Expand Up @@ -419,6 +421,9 @@ pub fn from_lines(lines: Vec<io::Result<String>>) -> Result<Config> {
"h2-host" => {
proxy.h2_host = Some(v.to_string());
}
"h2-method" => {
proxy.h2_method = Some(v.to_string());
}
"sni" => {
proxy.sni = Some(v.to_string());
}
Expand Down Expand Up @@ -1067,6 +1072,9 @@ pub fn to_internal(conf: &mut Config) -> Result<internal::Config> {
headers.insert("Host".to_string(), ext_h2_host.clone());
h2_settings.headers = headers;
}
if let Some(ext_h2_method) = &ext_proxy.h2_method {
h2_settings.method = ext_h2_method.clone();
}
let h2_settings = h2_settings.write_to_bytes().unwrap();
h2_outbound.settings = h2_settings;
h2_outbound.tag = format!("{}_h2_xxx", ext_proxy.tag.clone());
Expand Down Expand Up @@ -1288,6 +1296,9 @@ pub fn to_internal(conf: &mut Config) -> Result<internal::Config> {
headers.insert("Host".to_string(), ext_h2_host.clone());
h2_settings.headers = headers;
}
if let Some(ext_h2_method) = &ext_proxy.h2_method {
h2_settings.method = ext_h2_method.clone();
}
let h2_settings = h2_settings.write_to_bytes().unwrap();
h2_outbound.settings = h2_settings;
h2_outbound.tag = format!("{}_h2_xxx", ext_proxy.tag.clone());
Expand Down
3 changes: 2 additions & 1 deletion leaf/src/config/internal/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ message WebSocketOutboundSettings {

message H2OutboundSettings {
string path = 1;
map<string, string> headers = 2;
string method = 2;
map<string, string> headers = 3;
}

message TryAllOutboundSettings {
Expand Down
14 changes: 13 additions & 1 deletion leaf/src/config/internal/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2395,6 +2395,8 @@ pub struct H2OutboundSettings {
// message fields
// @@protoc_insertion_point(field:H2OutboundSettings.path)
pub path: ::std::string::String,
// @@protoc_insertion_point(field:H2OutboundSettings.method)
pub method: ::std::string::String,
// @@protoc_insertion_point(field:H2OutboundSettings.headers)
pub headers: ::std::collections::HashMap<::std::string::String, ::std::string::String>,
// special fields
Expand Down Expand Up @@ -2428,6 +2430,9 @@ impl ::protobuf::Message for H2OutboundSettings {
self.path = is.read_string()?;
},
18 => {
self.method = is.read_string()?;
},
26 => {
let len = is.read_raw_varint32()?;
let old_limit = is.push_limit(len as u64)?;
let mut key = ::std::default::Default::default();
Expand Down Expand Up @@ -2457,6 +2462,9 @@ impl ::protobuf::Message for H2OutboundSettings {
if !self.path.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.path);
}
if !self.method.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.method);
}
for (k, v) in &self.headers {
let mut entry_size = 0;
entry_size += ::protobuf::rt::string_size(1, &k);
Expand All @@ -2472,11 +2480,14 @@ impl ::protobuf::Message for H2OutboundSettings {
if !self.path.is_empty() {
os.write_string(1, &self.path)?;
}
if !self.method.is_empty() {
os.write_string(2, &self.method)?;
}
for (k, v) in &self.headers {
let mut entry_size = 0;
entry_size += ::protobuf::rt::string_size(1, &k);
entry_size += ::protobuf::rt::string_size(2, &v);
os.write_raw_varint32(18)?; // Tag.
os.write_raw_varint32(26)?; // Tag.
os.write_raw_varint32(entry_size as u32)?;
os.write_string(1, &k)?;
os.write_string(2, &v)?;
Expand All @@ -2499,6 +2510,7 @@ impl ::protobuf::Message for H2OutboundSettings {

fn clear(&mut self) {
self.path.clear();
self.method.clear();
self.headers.clear();
self.special_fields.clear();
}
Expand Down
6 changes: 6 additions & 0 deletions leaf/src/config/json/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ pub struct WebSocketOutboundSettings {
#[derive(Serialize, Deserialize, Debug)]
pub struct H2OutboundSettings {
pub path: Option<String>,
pub method: Option<String>,
pub headers: Option<HashMap<String, String>>,
}

Expand Down Expand Up @@ -739,6 +740,11 @@ pub fn to_internal(json: &mut Config) -> Result<internal::Config> {
if let Some(ext_headers) = ext_settings.headers {
settings.headers = ext_headers;
}
if let Some(ext_method) = ext_settings.method {
settings.method = ext_method;
} else {
settings.method = "PUT".to_string();
}
let settings = settings.write_to_bytes().unwrap();
outbound.settings = settings;
outbounds.push(outbound);
Expand Down
16 changes: 7 additions & 9 deletions leaf/src/proxy/h2/outbound/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ impl AsyncWrite for H2Adapter {

pub struct Handler {
pub path: String,
pub method: String,
pub headers: HashMap<String, String>,
}

Expand Down Expand Up @@ -128,24 +129,21 @@ impl OutboundStreamHandler for Handler {
let mut url = Url::parse(&format!("https://{}", host)).unwrap();
url = url.join(self.path.as_str()).unwrap();
let mut req = http::Request::builder()
.method(http::Method::PUT)
.method(self.method.to_uppercase().as_str())
.uri(&url.to_string())
.body(())
.unwrap();
.version(http::Version::HTTP_2);

for (key, value) in self.headers.iter() {
req.headers_mut().insert(HeaderName::from_str(key.as_str()).unwrap(), HeaderValue::from_str(value.as_str()).unwrap());
}

for (key, val) in req.headers() {
trace!("h2 header {:?}={:?}", key, val);
if key != "Host" {
req = req.header(key.as_str(), value.as_str());
}
}

let mut client = client
.ready()
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("h2 error: {}", e)))
.await?;
let (resp, send_stream) = client.send_request(req, false).map_err(|e| {
let (resp, send_stream) = client.send_request(req.body(()).unwrap(), false).map_err(|e| {
io::Error::new(io::ErrorKind::Other, format!("h2 error: {}", e))
})?;

Expand Down

0 comments on commit 72859d2

Please sign in to comment.