Skip to content

Commit

Permalink
Allow non-standard HTTP methods
Browse files Browse the repository at this point in the history
  • Loading branch information
algesten committed Feb 25, 2025
1 parent f4c2485 commit dca7620
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 3 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ _doc = ["rustls?/aws-lc-rs"]

[dependencies]
base64 = "0.22.1"
ureq-proto = "0.3.1"
ureq-proto = "0.3.2"
# ureq-proto = { path = "../ureq-proto" }
log = "0.4.25"
utf-8 = "0.7.6"
Expand Down
21 changes: 21 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ pub struct Config {
max_idle_connections: usize,
max_idle_connections_per_host: usize,
max_idle_age: Duration,
allow_non_standard_methods: bool,

// Chain built for middleware.
pub(crate) middleware: MiddlewareChain,
Expand Down Expand Up @@ -390,6 +391,15 @@ impl Config {
pub fn max_idle_age(&self) -> Duration {
self.max_idle_age
}

/// Whether to allow non-standard HTTP methods.
///
/// By default the methods are limited by the HTTP version.
///
/// Defaults to false
pub fn allow_non_standard_methods(&self) -> bool {
self.allow_non_standard_methods
}
}

/// Builder of [`Config`]
Expand Down Expand Up @@ -614,6 +624,16 @@ impl<Scope: private::ConfigScope> ConfigBuilder<Scope> {
self
}

/// Whether to allow non-standard HTTP methods.
///
/// By default the methods are limited by the HTTP version.
///
/// Defaults to false
pub fn allow_non_standard_methods(mut self, v: bool) -> Self {
self.config().allow_non_standard_methods = v;
self
}

/// Add middleware to use for each request in this agent.
///
/// Defaults to no middleware.
Expand Down Expand Up @@ -844,6 +864,7 @@ impl Default for Config {
max_idle_connections: 10,
max_idle_connections_per_host: 3,
max_idle_age: Duration::from_secs(15),
allow_non_standard_methods: false,
middleware: MiddlewareChain::default(),
}
}
Expand Down
22 changes: 22 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,28 @@ pub(crate) mod test {
assert!(matches!(err, Error::LargeResponseHeader(65, 5)));
}

#[test]
#[cfg(feature = "_test")]
fn non_standard_method() {
init_test_log();
let method = Method::from_bytes(b"FNORD").unwrap();

let req = Request::builder()
.method(method)
.uri("http://httpbin.org/fnord")
.body(())
.unwrap();

let agent = Agent::new_with_defaults();

let req = agent
.configure_request(req)
.allow_non_standard_methods(true)
.build();

agent.run(req).unwrap();
}

// This doesn't need to run, just compile.
fn _ensure_send_sync() {
fn is_send(_t: impl Send) {}
Expand Down
2 changes: 2 additions & 0 deletions src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ pub(crate) fn run(
flow.send_body_despite_method();
}

flow.allow_non_standard_methods(config.allow_non_standard_methods());

let (response, handler) = loop {
let timeout = timings.next_timeout(Timeout::Global);
let timed_out = match timeout.after {
Expand Down
20 changes: 20 additions & 0 deletions src/unversioned/transport/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,26 @@ fn setup_default_handlers(handlers: &mut Vec<TestHandler>) {
handlers,
);

maybe_add(
TestHandler::new("/fnord", |_uri, req, w| {
assert_eq!(req.method().as_str(), "FNORD");

write!(
w,
"HTTP/1.1 200 OK\r\n\
Content-Type: application/json\r\n\
Content-Length: {}\r\n\
\r\n",
HTTPBIN_GET.as_bytes().len()
)?;
if req.method() != Method::HEAD {
w.write_all(HTTPBIN_GET.as_bytes())?;
}
Ok(())
}),
handlers,
);

#[cfg(feature = "charset")]
{
let (cow, _, _) =
Expand Down

0 comments on commit dca7620

Please sign in to comment.