Skip to content

Commit

Permalink
force_send_body() escape hatch
Browse files Browse the repository at this point in the history
  • Loading branch information
algesten committed Oct 13, 2024
1 parent 50aa2d1 commit dba8d6f
Show file tree
Hide file tree
Showing 5 changed files with 44 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 @@ -37,7 +37,7 @@ _test = []

[dependencies]
base64 = "0.22.1"
hoot = "0.2.4"
hoot = "0.2.5"
# hoot = { path = "../hoot/hoot" }
http = "1.1.0"
log = "0.4.22"
Expand Down
5 changes: 5 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ pub struct Config {
pub(crate) max_idle_connections_per_host: usize,
pub(crate) max_idle_age: Duration,
pub(crate) middleware: MiddlewareChain,

// Techically not config, but here to pass as argument from
// RequestBuilder::force_send_body() to run()
pub(crate) force_send_body: bool,
}

impl Config {
Expand Down Expand Up @@ -508,6 +512,7 @@ impl Default for Config {
max_idle_connections_per_host: 3,
max_idle_age: Duration::from_secs(15),
middleware: MiddlewareChain::default(),
force_send_body: false,
}
}
}
Expand Down
32 changes: 32 additions & 0 deletions src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,38 @@ impl RequestBuilder<WithoutBody> {
let request = self.builder.body(())?;
do_call(self.agent, request, self.query_extra, SendBody::none())
}

/// Force sending a body.
///
/// This is an escape hatch to interact with broken services.
///
/// According to the spec, methods such as GET, DELETE and TRACE should
/// not have a body. Despite that there are broken API services and
/// servers that use it.
///
/// Example using DELETE while sending a body.
///
/// ```
/// let res = ureq::delete("http://httpbin.org/delete")
/// // this "unlocks" send() below
/// .force_send_body()
/// .send("DELETE with body is not correct")?;
/// # Ok::<_, ureq::Error>(())
/// ```
pub fn force_send_body(mut self) -> RequestBuilder<WithBody> {
// This is how we communicate to run() that we want to disable
// the method-body-compliance check.
let config = self.request_level_config();
config.force_send_body = true;

RequestBuilder {
agent: self.agent,
builder: self.builder,
query_extra: self.query_extra,
dummy_config: None,
_ph: PhantomData,
}
}
}

impl RequestBuilder<WithBody> {
Expand Down
4 changes: 4 additions & 0 deletions src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ pub(crate) fn run(

let mut flow = Flow::new(request)?;

if config.force_send_body {
flow.send_body_despite_method();
}

let (response, handler) = loop {
let timeout = timings.next_timeout(Timeout::Global);
let timed_out = match timeout.after {
Expand Down

0 comments on commit dba8d6f

Please sign in to comment.