PostgresHandler

Struct PostgresHandler 

Source
pub struct PostgresHandler<TReq = Value, TRes = Value>
where TReq: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static, TRes: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static,
{ /* private fields */ }
Expand description

PostgreSQL handler for outlet middleware.

Implements the RequestHandler trait to log HTTP requests and responses to PostgreSQL. Request and response bodies are serialized to JSONB fields.

Generic over TReq and TRes which represent the request and response body types that should implement Deserialize for parsing and Serialize for database storage as JSONB. Use serde_json::Value for flexible JSON storage, or custom structs for typed storage.

Implementations§

Source§

impl<TReq, TRes> PostgresHandler<TReq, TRes>
where TReq: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static, TRes: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static,

Source

pub async fn new(database_url: &str) -> Result<Self, PostgresHandlerError>

Create a new PostgreSQL handler with a connection pool.

This will connect to the database but will NOT run migrations. Use migrator() to get a migrator and run migrations separately.

§Arguments
  • database_url - PostgreSQL connection string
§Examples
use outlet_postgres::PostgresHandler;
use serde::{Deserialize, Serialize};
use serde_json::Value;

#[derive(Deserialize, Serialize)]
struct MyBodyType {
    id: u64,
    name: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Run migrations first
    let pool = sqlx::PgPool::connect("postgresql://user:pass@localhost/db").await?;
    PostgresHandler::<MyBodyType, MyBodyType>::migrator().run(&pool).await?;
     
    // Create handler
    let handler = PostgresHandler::<MyBodyType>::new("postgresql://user:pass@localhost/db").await?;
    Ok(())
}
Source

pub async fn from_pool(pool: PgPool) -> Result<Self, PostgresHandlerError>

Create a PostgreSQL handler from an existing connection pool.

Use this if you already have a connection pool and want to reuse it. This will NOT run migrations - use migrator() to run migrations separately.

§Arguments
  • pool - Existing PostgreSQL connection pool
§Examples
use outlet_postgres::PostgresHandler;
use sqlx::PgPool;
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct MyBodyType {
    id: u64,
    name: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let pool = PgPool::connect("postgresql://user:pass@localhost/db").await?;
     
    // Run migrations first
    PostgresHandler::<MyBodyType, MyBodyType>::migrator().run(&pool).await?;
     
    // Create handler
    let handler = PostgresHandler::<MyBodyType>::from_pool(pool).await?;
    Ok(())
}
Source

pub fn migrator() -> Migrator

Get the migrator for running outlet-postgres database migrations.

This returns a SQLx migrator that can be used to set up the required http_requests and http_responses tables. The consuming application is responsible for running these migrations at the appropriate time and in the appropriate database schema.

§Examples
use outlet_postgres::PostgresHandler;
use sqlx::{PgPool, Executor};
use serde_json::Value;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let pool = PgPool::connect("postgresql://user:pass@localhost/db").await?;
     
    // Run outlet migrations in a specific schema
    sqlx::query("SET search_path = 'outlet'").execute(&pool).await?;
    PostgresHandler::<Value, Value>::migrator().run(&pool).await?;
    sqlx::query("SET search_path = 'public'").execute(&pool).await?;
     
    // Create handler with schema-specific pool configured for outlet schema
    let outlet_pool = sqlx::postgres::PgPoolOptions::new()
        .after_connect(|conn, _meta| {
            Box::pin(async move {
                conn.execute("SET search_path = 'outlet';").await?;
                Ok(())
            })
        })
        .connect("postgresql://user:pass@localhost/db")
        .await?;
    let handler = PostgresHandler::<Value, Value>::from_pool(outlet_pool).await?;
    Ok(())
}
Source

pub fn repository(&self) -> RequestRepository<TReq, TRes>

Get a repository for querying logged requests and responses.

Returns a RequestRepository with the same type parameters as this handler, allowing for type-safe querying of request and response bodies.

Trait Implementations§

Source§

impl<TReq, TRes> Clone for PostgresHandler<TReq, TRes>
where TReq: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static + Clone, TRes: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static + Clone,

Source§

fn clone(&self) -> PostgresHandler<TReq, TRes>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<TReq, TRes> RequestHandler for PostgresHandler<TReq, TRes>
where TReq: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static, TRes: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static,

Source§

async fn handle_request(&self, data: RequestData, correlation_id: u64)

Handle a captured HTTP request. Read more
Source§

async fn handle_response(&self, data: ResponseData, correlation_id: u64)

Handle a captured HTTP response. Read more

Auto Trait Implementations§

§

impl<TReq, TRes> Freeze for PostgresHandler<TReq, TRes>

§

impl<TReq = Value, TRes = Value> !RefUnwindSafe for PostgresHandler<TReq, TRes>

§

impl<TReq, TRes> Send for PostgresHandler<TReq, TRes>

§

impl<TReq, TRes> Sync for PostgresHandler<TReq, TRes>

§

impl<TReq, TRes> Unpin for PostgresHandler<TReq, TRes>
where TReq: Unpin, TRes: Unpin,

§

impl<TReq = Value, TRes = Value> !UnwindSafe for PostgresHandler<TReq, TRes>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,