Skip to content

Commit

Permalink
feat: add flag for disabling rate-limiting
Browse files Browse the repository at this point in the history
  • Loading branch information
matusf committed Oct 16, 2023
1 parent 60f13e0 commit 28312f7
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 36 deletions.
43 changes: 12 additions & 31 deletions src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,38 +43,33 @@ pub struct FuzzStats {
did_failed: Vec<bool>,
}

#[derive(Debug)]
pub type RequestSender = Box<dyn Fn(&str, &str, &Payload) -> Result<ureq::Response>>;

pub struct Fuzzer {
schema: OpenAPI,
url: Url,
ignored_status_codes: Vec<u16>,
extra_headers: HashMap<String, String>,
max_test_case_count: u32,
results_dir: PathBuf,
stats_dir: Option<PathBuf>,
agent: Agent,
request_sender: RequestSender,
}

impl Fuzzer {
pub fn new(
schema: OpenAPI,
url: Url,
ignored_status_codes: Vec<u16>,
extra_headers: HashMap<String, String>,
max_test_case_count: u32,
results_dir: PathBuf,
stats_dir: Option<PathBuf>,
agent: Agent,
request_sender: RequestSender,
) -> Fuzzer {
Fuzzer {
schema,
url,
ignored_status_codes,
extra_headers,
max_test_case_count,
results_dir,
stats_dir,
agent,
request_sender,
}
}

Expand Down Expand Up @@ -129,8 +124,7 @@ impl Fuzzer {
&any_with::<Payload>(Rc::new(ArbitraryParameters::new(operation))),
|payload| {
let now = Instant::now();
let response = self
.send_request_with_backoff(path_with_params, method, &payload)
let response = (self.request_sender)(path_with_params, method, &payload)
.map_err(|e| {
TestCaseError::Fail(format!("unable to send request: {e}").into())
})?;
Expand Down Expand Up @@ -167,16 +161,19 @@ impl Fuzzer {
}
}

fn send_request_with_backoff(
&self,
pub fn send_request_with_backoff(
url: &Url,
path_with_params: &str,
method: &str,
payload: &Payload,
extra_headers: &HashMap<String, String>,
agent: &Agent,
) -> Result<ureq::Response> {
let max_backoff = 10;

for backoff in 0..max_backoff {
let response = self.send_request_(path_with_params, method, payload)?;
let response =
Fuzzer::send_request(url, path_with_params, method, payload, extra_headers, agent)?;
if !BACKOFF_STATUS_CODES.contains(&response.status()) {
return Ok(response);
}
Expand All @@ -191,22 +188,6 @@ impl Fuzzer {
Err(anyhow!("max backoff threshold reached"))
}

fn send_request_(
&self,
path_with_params: &str,
method: &str,
payload: &Payload,
) -> Result<ureq::Response> {
Fuzzer::send_request(
&self.url,
path_with_params,
method,
payload,
&self.extra_headers,
&self.agent,
)
}

pub fn send_request(
url: &Url,
path_with_params: &str,
Expand Down
48 changes: 43 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod fuzzer;
mod stats;
mod verifier;

use std::collections::HashMap;
use std::path::PathBuf;
use std::process::ExitCode;
use std::str::FromStr;
Expand Down Expand Up @@ -68,6 +69,10 @@ struct RunArgs {

#[argh(switch, description = "disable verification of TLS certificates")]
skip_tls_verify: bool,

/// do not use rate limiting
#[argh(switch)]
no_rate_limiting: bool,
}

#[derive(FromArgs, Debug, PartialEq)]
Expand Down Expand Up @@ -146,18 +151,20 @@ fn main() -> Result<ExitCode> {
serde_yaml::from_str(&specfile).context("Failed to parse schema")?;
let openapi_schema = openapi_schema.deref_all();

let agent = create_agent(!args.skip_tls_verify);

let request_sender = create_sender(
create_agent(!args.skip_tls_verify),
args.url.into(),
args.header.into_iter().map(Into::into).collect(),
args.no_rate_limiting,
);
let now = Instant::now();
let exit_code = Fuzzer::new(
openapi_schema,
args.url.into(),
args.ignore_status_code,
args.header.into_iter().map(Into::into).collect(),
args.max_test_case_count,
args.results_dir,
args.stats_dir,
agent,
request_sender,
)
.run()?;
println!("Elapsed time: {}s", now.elapsed().as_secs());
Expand Down Expand Up @@ -197,3 +204,34 @@ fn create_agent(verify_cert: bool) -> ureq::Agent {
.build()
}
}

fn create_sender(
agent: ureq::Agent,
url: Url,
extra_headers: HashMap<String, String>,
no_rate_limiting: bool,
) -> fuzzer::RequestSender {
if no_rate_limiting {
Box::new(move |path_with_params, method, payload| {
Fuzzer::send_request(
&url,
path_with_params,
method,
payload,
&extra_headers,
&agent,
)
})
} else {
Box::new(move |path_with_params, method, payload| {
Fuzzer::send_request_with_backoff(
&url,
path_with_params,
method,
payload,
&extra_headers,
&agent,
)
})
}
}

0 comments on commit 28312f7

Please sign in to comment.