From ab5005c98513a477cad6035ef9814a13ff97256b Mon Sep 17 00:00:00 2001 From: zonyitoo Date: Thu, 24 Oct 2024 00:00:53 +0800 Subject: [PATCH] fix(local-http): HttpClient send HTTP requests URI contains only Path&Query - fix #1730 - hyper will serialize the hyper::Request object with all the contents in the uri, which may be rejected by some of the servers. --- crates/shadowsocks-service/Cargo.toml | 2 +- .../src/local/http/http_client.rs | 19 +++++++++++++++++-- .../src/local/http/http_service.rs | 4 ++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/crates/shadowsocks-service/Cargo.toml b/crates/shadowsocks-service/Cargo.toml index 7861e835..3b8050db 100644 --- a/crates/shadowsocks-service/Cargo.toml +++ b/crates/shadowsocks-service/Cargo.toml @@ -72,7 +72,7 @@ local-dns-relay = ["local-dns"] # Currently is only used in Android local-flow-stat = ["local"] # Enable HTTP protocol for sslocal -local-http = ["local", "hyper", "http-body-util"] +local-http = ["local", "hyper", "http", "http-body-util"] local-http-native-tls = ["local-http", "tokio-native-tls", "native-tls"] local-http-native-tls-vendored = [ "local-http-native-tls", diff --git a/crates/shadowsocks-service/src/local/http/http_client.rs b/crates/shadowsocks-service/src/local/http/http_client.rs index f304f48c..dd252434 100644 --- a/crates/shadowsocks-service/src/local/http/http_client.rs +++ b/crates/shadowsocks-service/src/local/http/http_client.rs @@ -11,6 +11,7 @@ use std::{ time::{Duration, Instant}, }; +use http::Uri; use hyper::{ body::{self, Body}, client::conn::{http1, http2}, @@ -43,6 +44,9 @@ pub enum HttpClientError { /// std::io::Error #[error("{0}")] Io(#[from] io::Error), + /// Errors from http + #[error("{0}")] + Http(#[from] http::Error), } #[derive(Clone, Debug)] @@ -195,8 +199,19 @@ where &self, host: Address, mut c: HttpConnection, - req: Request, - ) -> hyper::Result> { + mut req: Request, + ) -> Result, HttpClientError> { + // Remove Scheme, Host part from URI + if req.uri().scheme().is_some() || req.uri().authority().is_some() { + let mut builder = Uri::builder(); + if let Some(path_and_query) = req.uri().path_and_query() { + builder = builder.path_and_query(path_and_query.as_str()); + } else { + builder = builder.path_and_query("/"); + } + *(req.uri_mut()) = builder.build()?; + } + trace!("HTTP making request to host: {}, request: {:?}", host, req); let response = c.send_request(req).await?; trace!("HTTP received response from host: {}, response: {:?}", host, response); diff --git a/crates/shadowsocks-service/src/local/http/http_service.rs b/crates/shadowsocks-service/src/local/http/http_service.rs index d45b2363..8d4ab982 100644 --- a/crates/shadowsocks-service/src/local/http/http_service.rs +++ b/crates/shadowsocks-service/src/local/http/http_service.rs @@ -158,6 +158,10 @@ impl HttpService { error!("failed to make request to host: {}, error: {}", host, err); return make_internal_server_error(); } + Err(HttpClientError::Http(err)) => { + error!("failed to make request to host: {}, error: {}", host, err); + return make_bad_request(); + } }; trace!("received {} <- {} {:?}", self.peer_addr, host, res);