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, migrator};
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?;
migrator().run(&pool).await?;
// Create handler
let handler = PostgresHandler::<MyBodyType, MyBodyType>::new("postgresql://user:pass@localhost/db").await?;
Ok(())
}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(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(())
}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)
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<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