Skip to main content

HttpExecutor

Trait HttpExecutor 

Source
pub trait HttpExecutor: Send + Sync {
    // Required method
    fn execute_request<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        method: &'life1 str,
        path: ResolvedPath<'life2>,
        body: Option<Value>,
    ) -> Pin<Box<dyn Future<Output = Result<Value, ExecutionError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             Self: 'async_trait;

    // Provided method
    fn placeholder_rules(
        &self,
        method: &str,
        path_template: &str,
        param: &str,
    ) -> PlaceholderRules<'_> { ... }
}
Expand description

Trait for making HTTP requests during execution.

This abstraction allows the executor to be used with different HTTP clients and enables easy testing with mock implementations.

§The D-09 contract change (Phase 128)

execute_request’s path parameter used to be a bare &str carrying the TEMPLATE the script wrote, and each implementor resolved its own {key} placeholders inside its own impl. That made the public trait a blind seam: a decorator wrapping HttpExecutor to inspect outbound requests saw only the template and never the values, so a placeholder carrying a query separator became a different endpoint with nothing in a position to notice.

Resolution now happens in PlanExecutor BEFORE dispatch, and the parameter is a ResolvedPath rather than a &str so the change is a compile error for a stale implementor instead of a silent semantic shift. A stale implementor that kept compiling would quietly double-resolve an already-resolved path, which for a security fix is the worst available outcome.

Required Methods§

Source

fn execute_request<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, method: &'life1 str, path: ResolvedPath<'life2>, body: Option<Value>, ) -> Pin<Box<dyn Future<Output = Result<Value, ExecutionError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Execute an HTTP request.

path is already fully resolved and checked — see ResolvedPath. Do NOT perform placeholder substitution here; body has already had the path-consumed keys removed.

Provided Methods§

Source

fn placeholder_rules( &self, method: &str, path_template: &str, param: &str, ) -> PlaceholderRules<'_>

The placeholder rules to apply to one LAYER-2 {param} value.

This is the D4(b) seam on the Code Mode surface. PlanExecutor has no access to an OpenAPI document; the only component that does is the executor implementation, so the narrowing has to be asked for here.

method is part of the signature and not decoration: an OpenAPI schema indexes operations by (path, METHOD), so GET /things/{id} and DELETE /things/{id} are two operations that may declare different constraints for the same id. A (path_template, param) signature could not disambiguate them and would have to either scan linearly or narrow from the wrong operation.

path_template is the path as it reaches layer 2 — after layer-1 ${var} interpolation and before {key} substitution. For the ordinary case of a string-literal path that is byte-identical to the OpenAPI path template, which is what makes a spec lookup work.

§The default is safe

The default returns PlaceholderRules::default(), which is FLOOR-PLUS-CAP-WITH-NO-NARROWING. An implementor that keeps the default still gets the unconditional character floor and the always-on 256-code-point cap on every value; what is absent is only the spec-declared narrowing. The floor is never what a missing override costs.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§