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,
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,
Sourcepub async fn new(database_url: &str) -> Result<Self, PostgresHandlerError>
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(())
}
Sourcepub async fn from_pool(pool: PgPool) -> Result<Self, PostgresHandlerError>
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(())
}
Sourcepub fn migrator() -> Migrator
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(())
}
Sourcepub fn repository(&self) -> RequestRepository<TReq, TRes>
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,
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>
fn clone(&self) -> PostgresHandler<TReq, TRes>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreSource§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,
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)
async fn handle_request(&self, data: RequestData, correlation_id: u64)
Source§async fn handle_response(&self, data: ResponseData, correlation_id: u64)
async fn handle_response(&self, data: ResponseData, correlation_id: u64)
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>
impl<TReq = Value, TRes = Value> !UnwindSafe for PostgresHandler<TReq, TRes>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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