-
-
Notifications
You must be signed in to change notification settings - Fork 36
refactor!: extract framework core to cot-core #444
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
base: master
Are you sure you want to change the base?
Changes from 16 commits
b3da91c
665082c
383b9f5
a6dd5f8
9dee0ae
2da6c5d
725f180
a4fa150
2994eca
266214e
c1c890a
ead28ff
d13c649
9b372af
0536013
ce1c634
cec103e
3aecce1
ea496f2
b3e3be5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| [package] | ||
| name = "cot_core" | ||
| version = "0.4.0" | ||
| description = "The Rust web framework for lazy developers - framework core." | ||
| categories = ["web-programming", "web-programming::http-server", "network-programming"] | ||
| edition.workspace = true | ||
| rust-version.workspace = true | ||
| license.workspace = true | ||
| homepage.workspace = true | ||
| repository.workspace = true | ||
| keywords.workspace = true | ||
| readme.workspace = true | ||
| authors.workspace = true | ||
|
|
||
| [lints] | ||
| workspace = true | ||
|
|
||
| [dependencies] | ||
| http.workspace = true | ||
| derive_more = { workspace = true, features = ["debug", "deref", "display", "from"] } | ||
| thiserror.workspace = true | ||
| serde.workspace = true | ||
| serde_json.workspace = true | ||
| backtrace.workspace = true | ||
| bytes.workspace = true | ||
| futures-core.workspace = true | ||
| http-body.workspace = true | ||
| http-body-util.workspace = true | ||
| sync_wrapper.workspace = true | ||
| axum.workspace = true | ||
| cot_macros.workspace = true | ||
| askama = { workspace = true, features = ["alloc"] } | ||
| tower-sessions.workspace = true | ||
| serde_path_to_error.workspace = true | ||
| indexmap.workspace = true | ||
| serde_html_form.workspace = true | ||
| form_urlencoded.workspace = true | ||
| tower.workspace = true | ||
| futures-util.workspace = true | ||
|
|
||
| [dev-dependencies] | ||
| async-stream.workspace = true | ||
| cot = { workspace = true, features = ["test"] } | ||
| futures.workspace = true | ||
| tokio.workspace = true | ||
|
|
||
| [features] | ||
| default = [] | ||
| json = [] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| //! Error handling types and utilities for Cot applications. | ||
| //! | ||
| //! This module provides error types, error handlers, and utilities for | ||
| //! handling various types of errors that can occur in Cot applications, | ||
| //! including 404 Not Found errors, uncaught panics, and custom error pages. | ||
|
|
||
| pub mod backtrace; | ||
| pub(crate) mod error_impl; | ||
| mod method_not_allowed; | ||
| mod not_found; | ||
| mod uncaught_panic; | ||
|
|
||
| pub use error_impl::{Error, impl_into_cot_error}; | ||
| pub use method_not_allowed::MethodNotAllowed; | ||
| pub use not_found::{Kind as NotFoundKind, NotFound}; | ||
| pub use uncaught_panic::UncaughtPanic; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -216,7 +216,7 @@ impl Error { | |
| } | ||
|
|
||
| #[must_use] | ||
| pub(crate) fn backtrace(&self) -> &CotBacktrace { | ||
| pub fn backtrace(&self) -> &CotBacktrace { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an implementation detail and cannot be exposed to users. The
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's problematic, it has to be public so that the error page can use it to show backtrace properly. The easiest solution would be to pull that to
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the error struct should be kept in the core crate. I can see several approaches here:
mod private {
pub struct Token;
}
pub struct MyStruct;
impl MyStruct {
pub fn restricted_method(&self, _: private::Token) {
println!("Restricted!");
}
}
#[doc(hidden)]
pub fn get_token() -> private::Token {
private::Token
}I'll let you pick the favorite one for the job.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I went with option 1. I want to keep this PR as change-light as possible and if it's used like that by other crates, I suppose it's good enough. If it's ever become a problem, we can change it then. |
||
| &self.repr.backtrace | ||
| } | ||
|
|
||
|
|
@@ -319,6 +319,7 @@ impl From<Error> for askama::Error { | |
| } | ||
| } | ||
|
|
||
| #[macro_export] | ||
| macro_rules! impl_into_cot_error { | ||
| ($error_ty:ty) => { | ||
| impl From<$error_ty> for $crate::Error { | ||
|
|
@@ -335,7 +336,7 @@ macro_rules! impl_into_cot_error { | |
| } | ||
| }; | ||
| } | ||
| pub(crate) use impl_into_cot_error; | ||
| pub use impl_into_cot_error; | ||
|
|
||
| #[derive(Debug, thiserror::Error)] | ||
| #[error("failed to render template: {0}")] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,9 @@ | ||
| //! Request handler traits and utilities. | ||
| //! | ||
| //! This module provides the [`RequestHandler`] trait, which is the core | ||
| //! abstraction for handling HTTP requests in Cot. It is automatically | ||
| //! implemented for async functions taking extractors and returning responses. | ||
|
|
||
| use std::future::Future; | ||
| use std::marker::PhantomData; | ||
| use std::pin::Pin; | ||
|
|
@@ -48,14 +54,14 @@ pub trait RequestHandler<T = ()> { | |
| fn handle(&self, request: Request) -> impl Future<Output = Result<Response>> + Send; | ||
| } | ||
|
|
||
| pub(crate) trait BoxRequestHandler { | ||
| pub trait BoxRequestHandler { | ||
| fn handle( | ||
| &self, | ||
| request: Request, | ||
| ) -> Pin<Box<dyn Future<Output = Result<Response>> + Send + '_>>; | ||
| } | ||
|
|
||
| pub(crate) fn into_box_request_handler<T, H: RequestHandler<T> + Send + Sync>( | ||
| pub fn into_box_request_handler<T, H: RequestHandler<T> + Send + Sync>( | ||
| handler: H, | ||
| ) -> impl BoxRequestHandler { | ||
| struct Inner<T, H>(H, PhantomData<fn() -> T>); | ||
|
|
@@ -142,6 +148,7 @@ macro_rules! impl_request_handler_from_request { | |
| }; | ||
| } | ||
|
|
||
| #[macro_export] | ||
| macro_rules! handle_all_parameters { | ||
| ($name:ident) => { | ||
| $name!(); | ||
|
|
@@ -227,19 +234,21 @@ macro_rules! handle_all_parameters_from_request { | |
| }; | ||
| } | ||
|
|
||
| pub(crate) use handle_all_parameters; | ||
| pub use handle_all_parameters; | ||
|
|
||
| handle_all_parameters!(impl_request_handler); | ||
| handle_all_parameters_from_request!(impl_request_handler_from_request); | ||
|
|
||
| #[rustfmt::skip] // `wrap_comments` breaks local links | ||
| /// A wrapper around a handler that's used in | ||
| /// [`Bootstrapper`](cot::Bootstrapper). | ||
| /// [`Bootstrapper`](../../cot/project/struct.Bootstrapper.html). | ||
| /// | ||
| /// It is returned by | ||
| /// [`Bootstrapper::into_bootstrapped_project`](cot::Bootstrapper::finish). | ||
| /// Typically, you don't need to interact with this type directly, except for | ||
| /// creating it in [`Project::middlewares`](cot::Project::middlewares) through | ||
| /// the [`RootHandlerBuilder::build`](cot::project::RootHandlerBuilder::build) | ||
| /// [`Bootstrapper::finish()`](../../cot/project/struct.Bootstrapper.html#method.finish). | ||
| /// Typically, you don't need to interact with this type directly, except | ||
| /// for creating it in | ||
| /// [`Project::middlewares()`](../../cot/project/trait.Project.html#method.middlewares) through the | ||
| /// [`RootHandlerBuilder::build()`](../../cot/project/struct.RootHandlerBuilder.html#method.build) | ||
|
||
| /// method. | ||
| /// | ||
| /// # Examples | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| //! HTTP header constants. | ||
| //! | ||
| //! This module provides commonly used content type header values. | ||
|
|
||
| pub const HTML_CONTENT_TYPE: &str = "text/html; charset=utf-8"; | ||
| pub const MULTIPART_FORM_CONTENT_TYPE: &str = "multipart/form-data"; | ||
| pub const URLENCODED_FORM_CONTENT_TYPE: &str = "application/x-www-form-urlencoded"; | ||
| #[cfg(feature = "json")] | ||
| pub const JSON_CONTENT_TYPE: &str = "application/json"; | ||
| pub const PLAIN_TEXT_CONTENT_TYPE: &str = "text/plain; charset=utf-8"; | ||
| pub const OCTET_STREAM_CONTENT_TYPE: &str = "application/octet-stream"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cot-core crate has a circular dev-dependency on the main
cotcrate. This creates a circular dependency structure wherecotdepends oncot_core, andcot_corehas a dev-dependency oncotfor tests. While this is technically allowed for dev-dependencies in Rust, it can complicate the build process and may cause issues with certain tools or workflows. Consider whether the tests in cot-core can be restructured to avoid depending on the main cot crate, or whether they can be moved to the main cot crate's test suite instead.