Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ on:
- docs/**
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-ci
cancel-in-progress: true

jobs:
build:
strategy:
Expand Down
102 changes: 102 additions & 0 deletions src/extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,63 @@ impl From<&str> for ResponseException {
}
}

/// Response body buffer for if you need to accumulate response
/// body chunks before you're ready to build a response object.
#[derive(Clone, Debug, Default)]
pub struct BodyBuffer {
buffer: BytesMut,
}

impl BodyBuffer {
/// Create a new empty body
pub fn new() -> Self {
Self::default()
}

/// Create a body with initial content
pub fn from_bytes(bytes: impl Into<Bytes>) -> Self {
let bytes = bytes.into();
let mut buffer = BytesMut::with_capacity(bytes.len());
buffer.extend_from_slice(&bytes);
Self { buffer }
}

/// Append data to the body
pub fn append(&mut self, data: impl AsRef<[u8]>) {
self.buffer.extend_from_slice(data.as_ref());
}

/// Get the body content as bytes
pub fn as_bytes(&self) -> &[u8] {
&self.buffer
}

/// Convert the body to Bytes
pub fn into_bytes(self) -> Bytes {
self.buffer.freeze()
}

/// Convert the body to BytesMut
pub fn into_bytes_mut(self) -> BytesMut {
self.buffer
}

/// Get the length of the body
pub fn len(&self) -> usize {
self.buffer.len()
}

/// Check if the body is empty
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}

/// Clear the body
pub fn clear(&mut self) {
self.buffer.clear();
}
}

/// Extension trait for http::Request
///
/// This trait provides methods to access and modify socket information related
Expand Down Expand Up @@ -298,6 +355,21 @@ pub trait ResponseBuilderExt {

/// Set exception in response builder
fn exception(self, exception: impl Into<String>) -> http::response::Builder;

/// Set body in response builder
fn body_buffer(self, body: BodyBuffer) -> http::response::Builder;

/// Get mutable access to the log extension
fn log_mut(&mut self) -> &mut ResponseLog;

/// Get mutable access to the body extension
fn body_buffer_mut(&mut self) -> &mut BodyBuffer;

/// Append to the log extension
fn append_log(&mut self, data: impl AsRef<[u8]>) -> &mut Self;

/// Append to the body extension
fn append_body(&mut self, data: impl AsRef<[u8]>) -> &mut Self;
}

impl ResponseBuilderExt for http::response::Builder {
Expand All @@ -308,6 +380,36 @@ impl ResponseBuilderExt for http::response::Builder {
fn exception(self, exception: impl Into<String>) -> http::response::Builder {
self.extension(ResponseException::new(exception))
}

fn body_buffer(self, body: BodyBuffer) -> http::response::Builder {
self.extension(body)
}

fn log_mut(&mut self) -> &mut ResponseLog {
let extensions = self.extensions_mut().unwrap();
if extensions.get::<ResponseLog>().is_none() {
extensions.insert(ResponseLog::new());
}
extensions.get_mut::<ResponseLog>().unwrap()
}

fn body_buffer_mut(&mut self) -> &mut BodyBuffer {
let extensions = self.extensions_mut().unwrap();
if extensions.get::<BodyBuffer>().is_none() {
extensions.insert(BodyBuffer::new());
}
extensions.get_mut::<BodyBuffer>().unwrap()
}

fn append_log(&mut self, data: impl AsRef<[u8]>) -> &mut Self {
self.log_mut().append(data);
self
}

fn append_body(&mut self, data: impl AsRef<[u8]>) -> &mut Self {
self.body_buffer_mut().append(data);
self
}
}

#[cfg(test)]
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ pub mod types;
pub mod napi;

pub use extensions::{
RequestBuilderExt, RequestExt, ResponseBuilderExt, ResponseException, ResponseExt, ResponseLog,
SocketInfo,
BodyBuffer, RequestBuilderExt, RequestExt, ResponseBuilderExt, ResponseException, ResponseExt,
ResponseLog, SocketInfo,
};
pub use handler::Handler;
pub use types::{Request, Response};
Loading