Skip to content

Commit

Permalink
remove generic type param from IntoCtx. (#1036)
Browse files Browse the repository at this point in the history
* remove generic type param from IntoCtx.

* doc test fix.

* codegen doc fix.

* fix example

* doc fmt fix.
  • Loading branch information
fakeshadow authored Jun 22, 2024
1 parent ea1f5a2 commit b05e8fa
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 67 deletions.
25 changes: 0 additions & 25 deletions codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,6 @@ pub fn state_impl(item: TokenStream) -> TokenStream {
/// `method = get` for example.
/// - `enclosed = <type>`: typed middleware applied to route.
/// - `enclosed_fn = <async function>`: async function as middleware applied to route
///
/// # Example
/// ```rust(no_run)
/// # use xitca_web::{codegen::route, handler::handler_service, service::Service, App, WebContext};
/// #[route("/", method = get, enclosed_fn = middleware_fn)]
/// async fn index() -> &'static str {
/// ""
/// }
///
/// async fn middleware_fn<S, C, B, Res, Err>(service: &S, ctx: WebContext<'_, C, B>) -> Result<Res, Err>
/// where
/// S: for<'r> Service<WebContext<'r, C, B>, Response = Res, Error = Err>
/// {
/// service.call(ctx).await
/// }
///
/// App::new()
/// // add generated index typed route to application.
/// .at_typed(index)
/// # .at("/nah", handler_service(nah));
///
/// # async fn nah(_: &WebContext<'_>) -> &'static str {
/// # // needed to infer the body type of request
/// # ""
/// # }
/// ```
#[proc_macro_attribute]
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
Expand Down
2 changes: 1 addition & 1 deletion examples/multi-http-services/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ xitca-service = "0.1"

openssl = "0.10.44"
quinn = { version = "0.11", features = ["ring"] }
rustls = "0.23"
rustls = { version = "0.23", default-features = false, features = ["ring"] }
rustls-pemfile = "2"
tracing = { version = "0.1.40", default-features = false }
tracing-subscriber = { version = "0.3.16", default-features = false, features = ["env-filter", "fmt"] }
14 changes: 6 additions & 8 deletions http/src/h2/proto/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,9 @@ where
(self.header_block.pseudo, self.header_block.fields)
}

#[cfg(feature = "unstable")]
pub fn pseudo_mut(&mut self) -> &mut Pseudo {
&mut self.header_block.pseudo
}
// pub fn pseudo_mut(&mut self) -> &mut Pseudo {
// &mut self.header_block.pseudo
// }

pub fn fields(&self) -> &HeaderMap {
&self.header_block.fields
Expand Down Expand Up @@ -371,10 +370,9 @@ impl Pseudo {
ResponsePseudo { status }
}

#[cfg(feature = "unstable")]
pub fn set_status(&mut self, value: StatusCode) {
self.status = Some(value);
}
// pub fn set_status(&mut self, value: StatusCode) {
// self.status = Some(value);
// }

pub fn set_scheme(&mut self, scheme: uri::Scheme) {
let bytes_str = match scheme.as_str() {
Expand Down
4 changes: 1 addition & 3 deletions http/src/util/middleware/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ use crate::http::{BorrowReq, BorrowReqMut};
/// State is roughly doing the same thing as `move ||` style closure capture. The difference comes
/// down to:
///
/// - The captured state is constructed lazily when [Service::call] method is
/// called.
///
/// - The captured state is constructed lazily when [Service::call] method is called.
/// - State can be referenced in nested types and beyond closures.
///
/// # Example:
Expand Down
10 changes: 8 additions & 2 deletions tls/src/rustls_uring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@ use self::buf::WriteBuf;
/// For now due to design limitation TlsStream offers concurrency with [AsyncBufRead::read] and
/// [AsyncBufWrite::write] but in either case the async function must run to completion and cancel
/// it prematurely would cause panic.
/// ```rust(no_run)
/// # async fn complete(stream: TlsStream<ServerConnection, TcpStream>) {
/// ```
/// use xitca_io::{
/// io_uring::{AsyncBufRead, AsyncBufWrite},
/// net::io_uring::TcpStream
/// };
/// use xitca_tls::rustls_uring::{ServerConnection, TlsStream};
///
/// async fn complete(stream: TlsStream<ServerConnection, TcpStream>) {
/// let _ = stream.read(vec![0; 128]).await;
/// let _ = stream.read(vec![0; 128]).await; // serialize read to complete is ok.
///
Expand Down
4 changes: 3 additions & 1 deletion web/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# unreleased
# unreleased 0.5.1
## Change
- remove generic type param from `IntoCtx` trait

# 0.5.0
## Add
Expand Down
2 changes: 1 addition & 1 deletion web/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "xitca-web"
version = "0.5.0"
version = "0.5.1"
edition = "2021"
license = "Apache-2.0"
description = "an async web framework"
Expand Down
40 changes: 30 additions & 10 deletions web/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,24 @@ type DefaultWebObject<C> = WebObject<C, RequestBody, WebResponse, RouterError<Er
type DefaultAppRouter<C> = AppRouter<RouteObject<(), DefaultWebObject<C>, Infallible>>;

// helper trait to poly between () and Box<dyn Fn()> as application state.
pub trait IntoCtx<C> {
fn into_ctx(self) -> impl Fn() -> BoxFuture<C> + Send + Sync;
pub trait IntoCtx {
type Ctx;

fn into_ctx(self) -> impl Fn() -> BoxFuture<Self::Ctx> + Send + Sync;
}

impl IntoCtx<()> for () {
fn into_ctx(self) -> impl Fn() -> BoxFuture<()> + Send + Sync {
impl IntoCtx for () {
type Ctx = ();

fn into_ctx(self) -> impl Fn() -> BoxFuture<Self::Ctx> + Send + Sync {
|| Box::pin(ready(Ok(())))
}
}

impl<C> IntoCtx<C> for CtxBuilder<C> {
fn into_ctx(self) -> impl Fn() -> BoxFuture<C> + Send + Sync {
impl<C> IntoCtx for CtxBuilder<C> {
type Ctx = C;

fn into_ctx(self) -> impl Fn() -> BoxFuture<Self::Ctx> + Send + Sync {
self
}
}
Expand Down Expand Up @@ -449,7 +455,7 @@ where
where
R::Response: ReadyService + for<'r> Service<WebContext<'r, C>, Response = WebResponse<ResB>, Error = SE>,
SE: for<'r> Service<WebContext<'r, C>, Response = WebResponse, Error = Infallible>,
CF: IntoCtx<C>,
CF: IntoCtx<Ctx = C>,
C: 'static,
{
let App { ctx_builder, router } = self;
Expand All @@ -469,7 +475,7 @@ where
SE: for<'r> Service<WebContext<'r, C>, Response = WebResponse, Error = Infallible> + 'static,
ResB: Stream<Item = Result<Bytes, BE>> + 'static,
BE: error::Error + Send + Sync + 'static,
CF: IntoCtx<C> + 'static,
CF: IntoCtx<Ctx = C> + 'static,
C: 'static,
{
struct BoxApp<S>(S);
Expand Down Expand Up @@ -508,7 +514,7 @@ where
R::Response: ReadyService + for<'r> Service<WebContext<'r, C>, Response = WebResponse<ResB>, Error = SE>,
SE: for<'r> Service<WebContext<'r, C>, Response = WebResponse, Error = Infallible> + 'static,
ResB: 'static,
CF: IntoCtx<C> + 'static,
CF: IntoCtx<Ctx = C> + 'static,
C: 'static,
{
crate::server::HttpServer::serve(self.finish())
Expand All @@ -535,14 +541,28 @@ where
}
}

impl<R, Arg, F> Service<Arg> for App<R, F>
impl<R, Arg> Service<Arg> for App<R>
where
R: Service<Arg>,
{
type Response = R::Response;
type Error = R::Error;

async fn call(&self, req: Arg) -> Result<Self::Response, Self::Error> {
self.router.call(req).await
}
}

impl<R, Arg, C> Service<Arg> for App<R, CtxBuilder<C>>
where
R: Service<Arg>,
{
type Response = R::Response;
type Error = R::Error;

async fn call(&self, req: Arg) -> Result<Self::Response, Self::Error> {
// TODO:
// enable nesting application state?
self.router.call(req).await
}
}
Expand Down
10 changes: 5 additions & 5 deletions web/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
//! In xitca-web error is treated as high level type and handled lazily.
//!
//! - high level:
//! An error type is represented firstly and mostly as a Rust type with useful trait bounds.It doesn't
//! necessarily mapped and/or converted into http response immediately. User is encouraged to pass the
//! error value around and convert it to http response on condition they prefer.
//! An error type is represented firstly and mostly as a Rust type with useful trait bounds.It doesn't
//! necessarily mapped and/or converted into http response immediately. User is encouraged to pass the
//! error value around and convert it to http response on condition they prefer.
//!
//! - lazy:
//! Since an error is passed as value mostly the error is handled lazily when the value is needed.
//! Including but not limiting to: formatting, logging, generating http response.
//! Since an error is passed as value mostly the error is handled lazily when the value is needed.
//! Including but not limiting to: formatting, logging, generating http response.
//!
//! # Example
//! ```rust
Expand Down
22 changes: 11 additions & 11 deletions web/src/middleware/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,24 +263,24 @@
//! ```
//! The main take away from the table should be:
//! - a type enclosed by middleware(s) is always the last one to take ownership of input request
//! and the first one to take ownership of output response (it's tasked with producing it)
//! and the first one to take ownership of output response (it's tasked with producing it)
//! - a middleware always take ownership of input before the type it enclosed on and always take
//! ownership of output response after
//! ownership of output response after
//! - multiple middlewares always go in a reverse order between input request and output
//! response: the input request goes from bottom to top.(in above example it goes from
//! `middleware2 -> middleware1 -> handler`). And the output response goes from top to bottom
//! (in above example it goes from `handler -> middleware1 -> middleware2`)
//! response: the input request goes from bottom to top.(in above example it goes from
//! `middleware2 -> middleware1 -> handler`). And the output response goes from top to bottom
//! (in above example it goes from `handler -> middleware1 -> middleware2`)
//! - `enclosed` and `enclosed_fn` share the same ordering rule however they are mixed in usage
//!
//! # Type mutation
//! - In [`WebContext<'_, C, B>`] type the last generic type param `B` is for http body type.
//! middleware and service are free to transform it's type and constraint it's inner/next service
//! to accept the new type as it's request http body type. [`DeCompress`] and [`Limit`] middleware are
//! examples of this practice. [`TypeEraser`] middleware on the other hand can be used to reserve the
//! type mutation and restore `B` type to it's default as [`RequestBody`] type. In this case web context
//! can be written in short form as [`WebContext<'_, C>`].
//! middleware and service are free to transform it's type and constraint it's inner/next service
//! to accept the new type as it's request http body type. [`DeCompress`] and [`Limit`] middleware are
//! examples of this practice. [`TypeEraser`] middleware on the other hand can be used to reserve the
//! type mutation and restore `B` type to it's default as [`RequestBody`] type. In this case web context
//! can be written in short form as [`WebContext<'_, C>`].
//! - [`WebResponse<B>`] type share the characteristic as web context type. The `B` type can be transform
//! into new type by services and middleware while type eraser is able to reverse the process.
//! into new type by services and middleware while type eraser is able to reverse the process.
//!
//! [`App::with_state`]: crate::App::with_state
//! [`Service`]: crate::service::Service
Expand Down

0 comments on commit b05e8fa

Please sign in to comment.