Skip to content
43 changes: 34 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"cot-cli",
"cot-codegen",
"cot-macros",
"cot-core",
# Examples
"examples/admin",
"examples/custom-error-pages",
Expand Down Expand Up @@ -76,6 +77,7 @@ clap-verbosity-flag = { version = "3", default-features = false }
clap_complete = "4"
clap_mangen = "0.2.31"
cot = { version = "0.5.0", path = "cot" }
cot_core = { version = "0.5.0", path = "cot-core" }
cot_codegen = { version = "0.5.0", path = "cot-codegen" }
cot_macros = { version = "0.5.0", path = "cot-macros" }
criterion = "0.8"
Expand Down
49 changes: 49 additions & 0 deletions cot-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[package]
name = "cot_core"
version = "0.5.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"] }
Copy link

Copilot AI Jan 18, 2026

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 cot crate. This creates a circular dependency structure where cot depends on cot_core, and cot_core has a dev-dependency on cot for 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.

Suggested change
cot = { workspace = true, features = ["test"] }

Copilot uses AI. Check for mistakes.
futures.workspace = true
tokio.workspace = true

[features]
default = []
json = []
13 changes: 8 additions & 5 deletions cot/src/body.rs → cot-core/src/body.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! HTTP body type.
//!
//! This module provides the [`Body`] type for representing HTTP bodies,
//! supporting both fixed in-memory buffers and streaming data sources.

use std::error::Error as StdError;
use std::fmt::{Debug, Formatter};
use std::pin::Pin;
Expand All @@ -9,7 +14,7 @@ use http_body::{Frame, SizeHint};
use http_body_util::combinators::BoxBody;
use sync_wrapper::SyncWrapper;

use crate::error::error_impl::impl_into_cot_error;
use crate::error::impl_into_cot_error;
use crate::{Error, Result};

/// A type that represents an HTTP request or response body.
Expand Down Expand Up @@ -166,7 +171,8 @@ impl Body {
}

#[must_use]
pub(crate) fn axum(inner: axum::body::Body) -> Self {
#[doc(hidden)]
pub fn axum(inner: axum::body::Body) -> Self {
Self::new(BodyInner::Axum(SyncWrapper::new(inner)))
}

Expand Down Expand Up @@ -261,9 +267,6 @@ impl_into_cot_error!(ReadRequestBody, BAD_REQUEST);

#[cfg(test)]
mod tests {
use std::pin::Pin;
use std::task::{Context, Poll};

use futures::stream;
use http_body::Body as HttpBody;

Expand Down
14 changes: 14 additions & 0 deletions cot-core/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! 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 uncaught_panic;

pub use error_impl::{Error, impl_into_cot_error};
pub use method_not_allowed::MethodNotAllowed;
pub use uncaught_panic::UncaughtPanic;
13 changes: 7 additions & 6 deletions cot/src/error/backtrace.rs → cot-core/src/error/backtrace.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// inline(never) is added to make sure there is a separate frame for this
// function so that it can be used to find the start of the backtrace.
#[inline(never)]
pub(crate) fn __cot_create_backtrace() -> Backtrace {
#[must_use]
pub fn __cot_create_backtrace() -> Backtrace {
let mut backtrace = Vec::new();
let mut start = false;
backtrace::trace(|frame| {
Expand All @@ -21,19 +22,19 @@ pub(crate) fn __cot_create_backtrace() -> Backtrace {
}

#[derive(Debug, Clone)]
pub(crate) struct Backtrace {
pub struct Backtrace {
frames: Vec<StackFrame>,
}

impl Backtrace {
#[must_use]
pub(crate) fn frames(&self) -> &[StackFrame] {
pub fn frames(&self) -> &[StackFrame] {
&self.frames
}
}

#[derive(Debug, Clone)]
pub(crate) struct StackFrame {
pub struct StackFrame {
symbol_name: Option<String>,
filename: Option<String>,
lineno: Option<u32>,
Expand All @@ -42,15 +43,15 @@ pub(crate) struct StackFrame {

impl StackFrame {
#[must_use]
pub(crate) fn symbol_name(&self) -> String {
pub fn symbol_name(&self) -> String {
self.symbol_name
.as_deref()
.unwrap_or("<unknown>")
.to_string()
}

#[must_use]
pub(crate) fn location(&self) -> String {
pub fn location(&self) -> String {
if let Some(filename) = self.filename.as_deref() {
let mut s = filename.to_owned();

Expand Down
47 changes: 4 additions & 43 deletions cot/src/error/error_impl.rs → cot-core/src/error/error_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::StatusCode;
// Need to rename Backtrace to CotBacktrace, because otherwise it triggers special behavior
// in the thiserror library
use crate::error::backtrace::{__cot_create_backtrace, Backtrace as CotBacktrace};
use crate::error::not_found::NotFound;

/// An error that can occur while using Cot.
pub struct Error {
Expand Down Expand Up @@ -151,46 +150,6 @@ impl Error {
Self::internal(error)
}

/// Create a new "404 Not Found" error without a message.
///
/// # Examples
///
/// ```
/// use cot::Error;
///
/// let error = Error::not_found();
/// ```
#[must_use]
#[deprecated(
note = "Use `cot::Error::from(cot::error::NotFound::new())` instead",
since = "0.4.0"
)]
pub fn not_found() -> Self {
Self::from(NotFound::new())
}

/// Create a new "404 Not Found" error with a message.
///
/// Note that the message is only displayed when Cot's debug mode is
/// enabled. It will not be exposed to the user in production.
///
/// # Examples
///
/// ```
/// use cot::Error;
///
/// let id = 123;
/// let error = Error::not_found_message(format!("User with id={id} not found"));
/// ```
#[must_use]
#[deprecated(
note = "Use `cot::Error::from(cot::error::NotFound::with_message())` instead",
since = "0.4.0"
)]
pub fn not_found_message(message: String) -> Self {
Self::from(NotFound::with_message(message))
}

/// Returns the HTTP status code associated with this error.
///
/// This method returns the appropriate HTTP status code that should be
Expand All @@ -216,7 +175,8 @@ impl Error {
}

#[must_use]
pub(crate) fn backtrace(&self) -> &CotBacktrace {
#[doc(hidden)]
pub fn backtrace(&self) -> &CotBacktrace {
&self.repr.backtrace
}

Expand Down Expand Up @@ -319,6 +279,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 {
Expand All @@ -335,7 +296,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}")]
Expand Down
File renamed without changes.
Loading
Loading