Skip to main content

earl_core/
lib.rs

1pub mod allowlist;
2pub mod decode;
3pub mod redact;
4pub mod render;
5pub mod schema;
6pub mod transport;
7pub mod with;
8
9pub use with::{AsJson, AsPath};
10
11use std::future::Future;
12
13use serde_json::{Map, Value};
14
15pub use allowlist::ensure_url_allowed;
16pub use decode::{DecodedBody, decode_response};
17pub use redact::Redactor;
18pub use render::TemplateRenderer;
19pub use schema::{AllowRule, CommandMode, ResultDecode, ResultExtract, ResultTemplate};
20pub use transport::ResolvedTransport;
21
22/// Body data prepared for HTTP-like protocol execution.
23#[derive(Debug, Clone)]
24pub enum PreparedBody {
25    Empty,
26    Json(Value),
27    Form(Vec<(String, String)>),
28    Multipart(Vec<PreparedMultipartPart>),
29    RawBytes {
30        bytes: Vec<u8>,
31        content_type: Option<String>,
32    },
33}
34
35/// A single part in a multipart body.
36#[derive(Debug, Clone)]
37pub struct PreparedMultipartPart {
38    pub name: String,
39    pub bytes: Vec<u8>,
40    pub content_type: Option<String>,
41    pub filename: Option<String>,
42}
43
44/// Unified result type returned by all protocol executors.
45#[derive(Debug, Clone)]
46pub struct ExecutionResult {
47    pub status: u16,
48    pub url: String,
49    pub result: Value,
50    pub decoded: Value,
51}
52
53/// Raw protocol output before decode/extract post-processing.
54#[derive(Debug, Clone)]
55pub struct RawExecutionResult {
56    pub status: u16,
57    pub url: String,
58    pub body: Vec<u8>,
59    pub content_type: Option<String>,
60}
61
62/// A single chunk from a streaming response.
63#[derive(Debug, Clone)]
64pub struct StreamChunk {
65    pub data: Vec<u8>,
66    pub content_type: Option<String>,
67}
68
69/// Metadata returned when a streaming execution completes.
70#[derive(Debug, Clone)]
71pub struct StreamMeta {
72    pub status: u16,
73    pub url: String,
74}
75
76/// Shared execution context passed to all protocol executors alongside
77/// their protocol-specific prepared data.
78#[derive(Debug, Clone)]
79pub struct ExecutionContext {
80    pub key: String,
81    pub mode: CommandMode,
82    pub allow_rules: Vec<AllowRule>,
83    pub transport: ResolvedTransport,
84    pub result_template: ResultTemplate,
85    pub args: Map<String, Value>,
86    pub redactor: Redactor,
87}
88
89/// Contract implemented by all protocol executors.
90///
91/// Each protocol crate provides an executor struct that implements this trait.
92/// The associated `PreparedData` type links the executor to its matching
93/// prepared data produced by the builder.
94pub trait ProtocolExecutor {
95    /// Protocol-specific prepared data (e.g. `PreparedHttpData`, `PreparedBashScript`).
96    type PreparedData: Clone + std::fmt::Debug + Send + Sync;
97
98    /// Execute a single protocol request and return the raw result.
99    fn execute(
100        &mut self,
101        data: &Self::PreparedData,
102        context: &ExecutionContext,
103    ) -> impl Future<Output = anyhow::Result<RawExecutionResult>> + Send;
104}
105
106/// Contract for protocol executors that support streaming output.
107///
108/// Instead of buffering the full response, the executor sends individual
109/// chunks through the provided `mpsc::Sender` as they arrive.
110pub trait StreamingProtocolExecutor {
111    /// Protocol-specific prepared data.
112    type PreparedData: Clone + std::fmt::Debug + Send + Sync;
113
114    /// Execute a streaming request, sending chunks through `sender`.
115    /// Returns metadata about the completed stream.
116    fn execute_stream(
117        &mut self,
118        data: &Self::PreparedData,
119        context: &ExecutionContext,
120        sender: tokio::sync::mpsc::Sender<StreamChunk>,
121    ) -> impl Future<Output = anyhow::Result<StreamMeta>> + Send;
122}