From 83ae0975d05c4895e5c203f65fd63e151a2417be Mon Sep 17 00:00:00 2001 From: Bernhard Schuster Date: Sat, 8 Jun 2024 07:22:31 +0200 Subject: [PATCH 1/2] fix: pre_hook (sync) make request mutable --- progenitor-impl/src/method.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/progenitor-impl/src/method.rs b/progenitor-impl/src/method.rs index 2c2a731b..949955f2 100644 --- a/progenitor-impl/src/method.rs +++ b/progenitor-impl/src/method.rs @@ -1131,7 +1131,7 @@ impl Generator { let pre_hook = self.settings.pre_hook.as_ref().map(|hook| { quote! { - (#hook)(&#client.inner, &#request_ident); + (#hook)(&#client.inner, &mut #request_ident); } }); let pre_hook_async = self.settings.pre_hook_async.as_ref().map(|hook| { From b5dc9fc46ed47c03b1d4cf084ce390de1992d451 Mon Sep 17 00:00:00 2001 From: "Adam H. Leventhal" Date: Wed, 9 Sep 2026 12:56:11 -0700 Subject: [PATCH 2/2] add compile test for pre_hook signatures; update macro doc for &mut The sync pre_hook now receives &mut reqwest::Request. Validate at compile time both that a hook can mutate the request and that a hook written against &reqwest::Request still compiles via &mut -> & coercion. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01FsEsN8H4VAfy3enDy5kiGU --- progenitor-macro/src/lib.rs | 7 ++++--- progenitor/tests/build_hooks.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 progenitor/tests/build_hooks.rs diff --git a/progenitor-macro/src/lib.rs b/progenitor-macro/src/lib.rs index fb854317..bd34d100 100644 --- a/progenitor-macro/src/lib.rs +++ b/progenitor-macro/src/lib.rs @@ -129,9 +129,10 @@ impl syn::parse::Parse for SpecSource { /// The optional `pre_hook` is either a closure (that must be within /// parentheses: `(fn |[inner,] request| { .. })`) or a path to a function. The /// closure or function must take one or two parameters: the inner type (if one -/// is specified) and a `&reqwest::Request`. This allows clients to examine -/// requests before they're sent to the server, for example to log them. The -/// optional `pre_hook_async` is the `async` variant of the same. +/// is specified) and a `&mut reqwest::Request`. This allows clients to examine +/// or modify requests before they're sent to the server, for example to log +/// them or add a header. The optional `pre_hook_async` is the `async` variant +/// of the same. /// /// The optional `post_hook` is either a closure (that must be within /// parentheses: `(fn |[inner,] result| { .. })`) or a path to a function. The diff --git a/progenitor/tests/build_hooks.rs b/progenitor/tests/build_hooks.rs new file mode 100644 index 00000000..79a37702 --- /dev/null +++ b/progenitor/tests/build_hooks.rs @@ -0,0 +1,33 @@ +// Copyright 2026 Oxide Computer Company + +//! Validate the signatures with which pre and post hooks are invoked. + +fn add_header(req: &mut reqwest::Request) { + req.headers_mut().insert( + "x-pre-hook", + reqwest::header::HeaderValue::from_static("present"), + ); +} + +fn observe(_req: &reqwest::Request) {} + +fn observe_result(_result: &Result) {} + +// The sync pre_hook receives `&mut reqwest::Request` so that it can modify +// the request before it's sent. +mod pre_hook_mut { + progenitor::generate_api!( + spec = "../sample_openapi/keeper.json", + pre_hook = crate::add_header, + post_hook = crate::observe_result, + ); +} + +// A pre_hook written against `&reqwest::Request` must continue to compile: +// the generated call site passes `&mut request`, which coerces to `&_`. +mod pre_hook_ref { + progenitor::generate_api!( + spec = "../sample_openapi/keeper.json", + pre_hook = crate::observe, + ); +}