Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move body related types from ntex::http #474

Merged
merged 3 commits into from
Nov 30, 2024
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
1 change: 1 addition & 0 deletions ntex-compio/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ path = "src/lib.rs"
ntex-bytes = "0.1"
ntex-io = "2.5"
ntex-util = "2"
ntex-rt = "0.4"
log = "0.4"
compio = { version = "0.13.0", features = ["macros", "runtime", "io", "io-uring", "polling"], default-features = false }
4 changes: 4 additions & 0 deletions ntex-http/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changes

## [0.1.13] - 2024-01-xx

* Move body related types from ntex::http

## [0.1.12] - 2024-01-16

* Update http dependency
Expand Down
9 changes: 7 additions & 2 deletions ntex-http/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ntex-http"
version = "0.1.12"
version = "0.1.13"
authors = ["ntex contributors <[email protected]>"]
description = "Http types for ntex framework"
keywords = ["network", "framework", "async", "futures"]
Expand All @@ -20,9 +20,14 @@ http = "1"
log = "0.4"
fxhash = "0.2.1"
itoa = "1.0.4"
ntex-bytes = "0.1.21"
ntex-bytes = "0.1"
serde = "1"
futures-core = { version = "0.3", default-features = false, features = ["alloc"] }

[dev-dependencies]
bincode = "1"
serde_json = "1"
ntex = "2"
ntex-util = "2"
ntex-macros = "0.1.3"
futures-util = { version = "0.3", default-features = false, features = ["alloc"] }
80 changes: 33 additions & 47 deletions ntex/src/http/body.rs → ntex-http/src/body.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Traits and structures to aid consuming and writing HTTP payloads.
use std::{
error::Error, fmt, marker::PhantomData, mem, pin::Pin, task::Context, task::Poll,
};

use crate::util::{Bytes, BytesMut, Stream};
use futures_core::Stream;
use ntex_bytes::{Bytes, BytesMut};

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
/// Body size hint
Expand All @@ -19,8 +21,9 @@ impl BodySize {
}
}

/// Type that provides this trait can be streamed to a peer.
/// Interface for types that can be streamed to a peer.
pub trait MessageBody: 'static {
/// Message body size hind
fn size(&self) -> BodySize;

fn poll_next_chunk(
Expand All @@ -30,10 +33,12 @@ pub trait MessageBody: 'static {
}

impl MessageBody for () {
#[inline]
fn size(&self) -> BodySize {
BodySize::Empty
}

#[inline]
fn poll_next_chunk(
&mut self,
_: &mut Context<'_>,
Expand All @@ -43,10 +48,12 @@ impl MessageBody for () {
}

impl<T: MessageBody> MessageBody for Box<T> {
#[inline]
fn size(&self) -> BodySize {
self.as_ref().size()
}

#[inline]
fn poll_next_chunk(
&mut self,
cx: &mut Context<'_>,
Expand All @@ -56,6 +63,7 @@ impl<T: MessageBody> MessageBody for Box<T> {
}

#[derive(Debug)]
/// Represents http response body
pub enum ResponseBody<B> {
Body(B),
Other(Body),
Expand Down Expand Up @@ -86,10 +94,12 @@ impl<B> From<Body> for ResponseBody<B> {
}

impl<B> ResponseBody<B> {
#[inline]
pub fn new(body: B) -> Self {
ResponseBody::Body(body)
}

#[inline]
pub fn take_body(&mut self) -> ResponseBody<B> {
std::mem::replace(self, ResponseBody::Other(Body::None))
}
Expand All @@ -106,13 +116,15 @@ impl<B: MessageBody> ResponseBody<B> {
}

impl<B: MessageBody> MessageBody for ResponseBody<B> {
#[inline]
fn size(&self) -> BodySize {
match self {
ResponseBody::Body(ref body) => body.size(),
ResponseBody::Other(ref body) => body.size(),
}
}

#[inline]
fn poll_next_chunk(
&mut self,
cx: &mut Context<'_>,
Expand Down Expand Up @@ -154,12 +166,13 @@ impl Body {
}

/// Create body from generic message body.
pub fn from_message<B: MessageBody + 'static>(body: B) -> Body {
pub fn from_message<B: MessageBody>(body: B) -> Body {
Body::Message(Box::new(body))
}
}

impl MessageBody for Body {
#[inline]
fn size(&self) -> BodySize {
match self {
Body::None => BodySize::None,
Expand Down Expand Up @@ -253,12 +266,6 @@ impl From<BytesMut> for Body {
}
}

impl From<serde_json::Value> for Body {
fn from(v: serde_json::Value) -> Body {
Body::Bytes(v.to_string().into())
}
}

impl<S> From<SizedStream<S>> for Body
where
S: Stream<Item = Result<Bytes, Box<dyn Error>>> + Unpin + 'static,
Expand Down Expand Up @@ -551,11 +558,12 @@ where

#[cfg(test)]
mod tests {
use futures_util::stream;
use std::{future::poll_fn, io};

use futures_util::stream;
use ntex_util::future::Ready;

use super::*;
use crate::util::Ready;

impl Body {
pub(crate) fn get_ref(&self) -> &[u8] {
Expand All @@ -566,16 +574,7 @@ mod tests {
}
}

impl ResponseBody<Body> {
pub(crate) fn get_ref(&self) -> &[u8] {
match *self {
ResponseBody::Body(ref b) => b.get_ref(),
ResponseBody::Other(ref b) => b.get_ref(),
}
}
}

#[crate::rt_test]
#[ntex::test]
async fn test_static_str() {
assert_eq!(Body::from("").size(), BodySize::Sized(0));
assert_eq!(Body::from("test").size(), BodySize::Sized(4));
Expand All @@ -593,7 +592,7 @@ mod tests {
assert!(poll_fn(|cx| "".poll_next_chunk(cx)).await.is_none());
}

#[crate::rt_test]
#[ntex::test]
async fn test_static_bytes() {
assert_eq!(Body::from(b"test".as_ref()).size(), BodySize::Sized(4));
assert_eq!(Body::from(b"test".as_ref()).get_ref(), b"test");
Expand All @@ -615,7 +614,7 @@ mod tests {
assert!(poll_fn(|cx| (&b""[..]).poll_next_chunk(cx)).await.is_none());
}

#[crate::rt_test]
#[ntex::test]
async fn test_vec() {
assert_eq!(Body::from(Vec::from("test")).size(), BodySize::Sized(4));
assert_eq!(Body::from(Vec::from("test")).get_ref(), b"test");
Expand All @@ -640,7 +639,7 @@ mod tests {
.is_none());
}

#[crate::rt_test]
#[ntex::test]
async fn test_bytes() {
let mut b = Bytes::from("test");
assert_eq!(Body::from(b.clone()).size(), BodySize::Sized(4));
Expand All @@ -654,7 +653,7 @@ mod tests {
assert!(poll_fn(|cx| b.poll_next_chunk(cx)).await.is_none(),);
}

#[crate::rt_test]
#[ntex::test]
async fn test_bytes_mut() {
let mut b = Body::from(BytesMut::from("test"));
assert_eq!(b.size(), BodySize::Sized(4));
Expand All @@ -675,7 +674,7 @@ mod tests {
assert!(poll_fn(|cx| b.poll_next_chunk(cx)).await.is_none(),);
}

#[crate::rt_test]
#[ntex::test]
async fn test_string() {
let mut b = "test".to_owned();
assert_eq!(Body::from(b.clone()).size(), BodySize::Sized(4));
Expand All @@ -691,20 +690,20 @@ mod tests {
assert!(poll_fn(|cx| b.poll_next_chunk(cx)).await.is_none(),);
}

#[crate::rt_test]
#[ntex::test]
async fn test_unit() {
assert_eq!(().size(), BodySize::Empty);
assert!(poll_fn(|cx| ().poll_next_chunk(cx)).await.is_none());
}

#[crate::rt_test]
#[ntex::test]
async fn test_box() {
let mut val = Box::new(());
assert_eq!(val.size(), BodySize::Empty);
assert!(poll_fn(|cx| val.poll_next_chunk(cx)).await.is_none());
}

#[crate::rt_test]
#[ntex::test]
#[allow(clippy::eq_op)]
async fn test_body_eq() {
assert!(Body::None == Body::None);
Expand All @@ -717,27 +716,14 @@ mod tests {
assert!(Body::Bytes(Bytes::from_static(b"1")) != Body::None);
}

#[crate::rt_test]
#[ntex::test]
async fn test_body_debug() {
assert!(format!("{:?}", Body::None).contains("Body::None"));
assert!(format!("{:?}", Body::Empty).contains("Body::Empty"));
assert!(format!("{:?}", Body::Bytes(Bytes::from_static(b"1"))).contains('1'));
}

#[crate::rt_test]
async fn test_serde_json() {
use serde_json::json;
assert_eq!(
Body::from(serde_json::Value::String("test".into())).size(),
BodySize::Sized(6)
);
assert_eq!(
Body::from(json!({"test-key":"test-value"})).size(),
BodySize::Sized(25)
);
}

#[crate::rt_test]
#[ntex::test]
async fn body_stream() {
let st = BodyStream::new(stream::once(Ready::<_, io::Error>::Ok(Bytes::from("1"))));
assert!(format!("{:?}", st).contains("BodyStream"));
Expand All @@ -749,7 +735,7 @@ mod tests {
assert!(res.as_ref().is_some());
}

#[crate::rt_test]
#[ntex::test]
async fn boxed_body_stream() {
let st = BoxedBodyStream::new(stream::once(Ready::<_, Box<dyn Error>>::Ok(
Bytes::from("1"),
Expand All @@ -763,7 +749,7 @@ mod tests {
assert!(res.as_ref().is_some());
}

#[crate::rt_test]
#[ntex::test]
async fn body_skips_empty_chunks() {
let mut body = BodyStream::new(stream::iter(
["1", "", "2"]
Expand All @@ -780,7 +766,7 @@ mod tests {
);
}

#[crate::rt_test]
#[ntex::test]
async fn sized_skips_empty_chunks() {
let mut body = SizedStream::new(
2,
Expand Down
1 change: 1 addition & 0 deletions ntex-http/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Http protocol support.
#![deny(rust_2018_idioms, unreachable_pub, missing_debug_implementations)]

pub mod body;
pub mod error;
mod map;
mod serde;
Expand Down
4 changes: 2 additions & 2 deletions ntex/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ntex"
version = "2.8.0"
version = "2.9.0"
authors = ["ntex contributors <[email protected]>"]
description = "Framework for composable network services"
readme = "README.md"
Expand Down Expand Up @@ -62,7 +62,7 @@ brotli = ["dep:brotli2"]

[dependencies]
ntex-codec = "0.6"
ntex-http = "0.1.12"
ntex-http = "0.1.13"
ntex-router = "0.5"
ntex-service = "3.3"
ntex-macros = "0.1"
Expand Down
3 changes: 1 addition & 2 deletions ntex/src/http/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! Http protocol support.
pub mod body;
mod builder;
pub mod client;
mod config;
Expand Down Expand Up @@ -36,4 +35,4 @@ pub use crate::io::types::HttpProtocol;

// re-exports
pub use ntex_http::uri::{self, Uri};
pub use ntex_http::{HeaderMap, Method, StatusCode, Version};
pub use ntex_http::{body, HeaderMap, Method, StatusCode, Version};
Loading
Loading