pub struct PostgresHandler<P = PgPool, TReq = Value, TRes = Value>where
P: PoolProvider,
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:
P: Pool provider implementingPoolProvidertrait for read/write routingTReqandTRes: Request and response body types for JSONB serialization
Use serde_json::Value for flexible JSON storage, or custom structs for typed storage.
Implementations§
Source§impl<P, TReq, TRes> PostgresHandler<P, TReq, TRes>where
P: PoolProvider,
TReq: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static,
TRes: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static,
impl<P, TReq, TRes> PostgresHandler<P, TReq, TRes>where
P: PoolProvider,
TReq: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static,
TRes: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static,
Sourcepub fn with_request_serializer<F>(self, serializer: F) -> Self
pub fn with_request_serializer<F>(self, serializer: F) -> Self
Add a custom request body serializer.
The serializer function takes raw bytes and should return a Result<TReq, String>.
If the serializer succeeds, the result will be stored as JSONB and body_parsed will be true.
If it fails, the raw content will be stored as a UTF-8 string and body_parsed will be false.
§Panics
This will panic if the serializer succeeds but the resulting TReq value cannot be
converted to JSON via serde_json::to_value(). This indicates a bug in the Serialize
implementation of TReq and should be fixed by the caller.
Sourcepub fn with_response_serializer<F>(self, serializer: F) -> Selfwhere
F: Fn(&RequestData, &ResponseData) -> Result<TRes, SerializationError> + Send + Sync + 'static,
pub fn with_response_serializer<F>(self, serializer: F) -> Selfwhere
F: Fn(&RequestData, &ResponseData) -> Result<TRes, SerializationError> + Send + Sync + 'static,
Add a custom response body serializer.
The serializer function takes raw bytes and should return a Result<TRes, String>.
If the serializer succeeds, the result will be stored as JSONB and body_parsed will be true.
If it fails, the raw content will be stored as a UTF-8 string and body_parsed will be false.
§Panics
This will panic if the serializer succeeds but the resulting TRes value cannot be
converted to JSON via serde_json::to_value(). This indicates a bug in the Serialize
implementation of TRes and should be fixed by the caller.
Sourcepub async fn from_pool_provider(
pool_provider: P,
) -> Result<Self, PostgresHandlerError>
pub async fn from_pool_provider( pool_provider: P, ) -> Result<Self, PostgresHandlerError>
Create a PostgreSQL handler from a pool provider.
Use this if you want to use a custom pool provider implementation
(such as DbPools for read/write separation).
This will NOT run migrations - use migrator() to run migrations separately.
§Arguments
pool_provider- Pool provider implementingPoolProvidertrait
§Examples
use outlet_postgres::{PostgresHandler, DbPools, migrator};
use sqlx::postgres::PgPoolOptions;
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 primary = PgPoolOptions::new()
.connect("postgresql://user:pass@primary/db").await?;
let replica = PgPoolOptions::new()
.connect("postgresql://user:pass@replica/db").await?;
// Run migrations on primary
migrator().run(&primary).await?;
// Create handler with read/write separation
let pools = DbPools::with_replica(primary, replica);
let handler = PostgresHandler::<_, MyBodyType, MyBodyType>::from_pool_provider(pools).await?;
Ok(())
}Sourcepub fn repository(&self) -> RequestRepository<P, TReq, TRes>
pub fn repository(&self) -> RequestRepository<P, 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.
Source§impl<TReq, TRes> PostgresHandler<PgPool, 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<PgPool, 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, migrator};
use serde::{Deserialize, Serialize};
#[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?;
migrator().run(&pool).await?;
// Create handler
let handler = PostgresHandler::<_, MyBodyType, 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, migrator};
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
migrator().run(&pool).await?;
// Create handler
let handler = PostgresHandler::<_, MyBodyType, MyBodyType>::from_pool(pool).await?;
Ok(())
}Trait Implementations§
Source§impl<P, TReq, TRes> Clone for PostgresHandler<P, TReq, TRes>where
P: PoolProvider + Clone,
TReq: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static + Clone,
TRes: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static + Clone,
impl<P, TReq, TRes> Clone for PostgresHandler<P, TReq, TRes>where
P: PoolProvider + Clone,
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<P, TReq, TRes>
fn clone(&self) -> PostgresHandler<P, TReq, TRes>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<P, TReq, TRes> RequestHandler for PostgresHandler<P, TReq, TRes>where
P: PoolProvider,
TReq: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static,
TRes: for<'de> Deserialize<'de> + Serialize + Send + Sync + 'static,
impl<P, TReq, TRes> RequestHandler for PostgresHandler<P, TReq, TRes>where
P: PoolProvider,
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)
async fn handle_request(&self, data: RequestData)
Source§async fn handle_response(
&self,
request_data: RequestData,
response_data: ResponseData,
)
async fn handle_response( &self, request_data: RequestData, response_data: ResponseData, )
Auto Trait Implementations§
impl<P, TReq, TRes> Freeze for PostgresHandler<P, TReq, TRes>where
P: Freeze,
impl<P = Pool<Postgres>, TReq = Value, TRes = Value> !RefUnwindSafe for PostgresHandler<P, TReq, TRes>
impl<P, TReq, TRes> Send for PostgresHandler<P, TReq, TRes>
impl<P, TReq, TRes> Sync for PostgresHandler<P, TReq, TRes>
impl<P, TReq, TRes> Unpin for PostgresHandler<P, TReq, TRes>where
P: Unpin,
impl<P = Pool<Postgres>, TReq = Value, TRes = Value> !UnwindSafe for PostgresHandler<P, 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