diff --git a/Cargo.toml b/Cargo.toml index 51573ed..10ec390 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,6 @@ tokio = { version = "1.47.1", features = ["full", "rt-multi-thread", "signal"] } tower-http = { version = "0.6.6", features = ["trace"] } tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } + +[features] +no-auth = [] diff --git a/README.md b/README.md index e69de29..c2a758e 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,144 @@ +# PureNotify Backend + +This is the backend service for the PureNotify application, written in Rust. It's built to be a high-performance, reliable, and scalable foundation for sending notifications. + +## 🚀 Features + +- **Asynchronous:** Built with `tokio` and `axum` for non-blocking I/O and high concurrency. +- **Configurable:** Easily configure the application using environment variables. +- **Logging:** Integrated structured logging with `tracing` for better observability. +- **Graceful Shutdown:** Ensures the server shuts down cleanly without dropping active connections. +- **Health Check:** A dedicated endpoint to monitor the service's health. + +## 🛠️ Technologies Used + +- **[Rust](https://www.rust-lang.org/)**: The core programming language. +- **[Axum](https://github.com/tokio-rs/axum)**: A web application framework that focuses on ergonomics and modularity. +- **[Tokio](https://tokio.rs/)**: An asynchronous runtime for the Rust programming language. +- **[Serde](https://serde.rs/)**: A framework for serializing and deserializing Rust data structures efficiently. +- **[Dotenvy](https://github.com/dotenv-rs/dotenv)**: For loading environment variables from a `.env` file. +- **[Tracing](https://github.com/tokio-rs/tracing)**: A framework for instrumenting Rust programs to collect structured, event-based diagnostic information. + +## ⚙️ Getting Started + +Follow these instructions to get a copy of the project up and running on your local machine for development and testing purposes. + +### Prerequisites + +You need to have the Rust toolchain installed on your system. If you don't have it, you can install it from [rustup.rs](https://rustup.rs/). + +```sh +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +### Installation & Running + +1. **Clone the repository:** + + ```sh + git clone https://github.com/your-username/purenotify_backend.git + cd purenotify_backend + ``` + +2. **Create a `.env` file:** + Copy the example environment file to create your own local configuration. + + ```sh + cp .env.example .env + ``` + + You can modify the `.env` file to change the server's configuration. + +3. **Build the project:** + + ```sh + cargo build + ``` + +4. **Run the application:** + For development, you can run the project directly with `cargo run`: + ```sh + cargo run + ``` + For a release build, run: + ```sh + cargo run --release + ``` + +The server will start, and you should see log output in your terminal indicating that it's running. + +## 🔧 Configuration + +The application is configured using environment variables. These can be set in a `.env` file in the project root or directly in your shell. + +- `BIND_ADDRESS`: The IP address and port the server should listen on. + - **Default:** `127.0.0.1:3000` +- `RUST_LOG`: Controls the log level for the application. + - **Example:** `RUST_LOG=info,purenotify_backend=debug` will set the default log level to `info` and the log level for this crate to `debug`. + - **Default:** Reads from the environment; if not set, logging may be minimal. + +## API Endpoints + +Here are the available API endpoints for the service. + +### Health Check + +- **Endpoint:** `/health` +- **Method:** `GET` +- **Description:** Used to verify that the service is running and healthy. +- **Success Response:** + - **Code:** `200 OK` + - **Content:** `{"status": "ok"}` + +#### Example Usage + +You can use `curl` to check the health of the service: + +```sh +curl http://127.0.0.1:3000/health +``` + +**Expected Output:** + +```json +{ + "status": "ok" +} +``` + +## 📂 Project Structure + +The project follows a standard Rust project layout. The main application logic is located in the `src/` directory. + +``` +src/ +├── main.rs # Application entry point, server setup +├── config.rs # Configuration management +├── handlers/ # Business logic for handling requests +│ └── health/ +│ └── health.rs +├── routes/ # API route definitions +│ └── health/ +│ └── health.rs +└── utils/ # Utility functions and shared modules +``` + +- `main.rs`: Initializes the server, logging, configuration, and wires up the routes. +- `config.rs`: Defines the `Config` struct and handles loading configuration from the environment. +- `handlers/`: Contains the core logic for each API endpoint. Each handler is responsible for processing a request and returning a response. +- `routes/`: Defines the Axum `Router` for different parts of the application. These modules map URL paths to their corresponding handlers. +- `utils/`: A place for helper functions or modules that are used across different parts of the application. + +## 🤝 Contributing + +Contributions are welcome! If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome. + +1. Fork the repository. +2. Create your feature branch (`git checkout -b feature/fooBar`). +3. Commit your changes (`git commit -am 'Add some fooBar'`). +4. Push to the branch (`git push origin feature/fooBar`). +5. Create a new Pull Request. + +## 📄 License + +This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. diff --git a/src/config.rs b/src/config.rs index 38f207e..b3727de 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,7 +7,7 @@ use std::str::FromStr; #[derive(Debug)] pub struct Config { pub bind_address: SocketAddr, - pub database_url: Option, + // pub database_url: Option, } impl Config { @@ -24,11 +24,11 @@ impl Config { return Err("In no-auth mode, BIND_ADDRESS must be 127.0.0.1".to_string()); } - let database_url = env::var("DATABASE_URL").ok(); + // let database_url = env::var("DATABASE_URL").ok(); Ok(Self { bind_address, - database_url, + // database_url, }) } } diff --git a/src/health.rs b/src/handlers/health/health.rs similarity index 86% rename from src/health.rs rename to src/handlers/health/health.rs index d0136bd..dc8f051 100644 --- a/src/health.rs +++ b/src/handlers/health/health.rs @@ -1,4 +1,4 @@ -// src/health.rs +// src/handlers/health/health.rs use axum::Json; use axum::http::StatusCode; diff --git a/src/handlers/health/mod.rs b/src/handlers/health/mod.rs new file mode 100644 index 0000000..ca22caf --- /dev/null +++ b/src/handlers/health/mod.rs @@ -0,0 +1,3 @@ +// src/handlers/health/mod.rs + +pub mod health; diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs new file mode 100644 index 0000000..953b839 --- /dev/null +++ b/src/handlers/mod.rs @@ -0,0 +1,3 @@ +// src/handlers/mod.rs + +pub mod health; diff --git a/src/main.rs b/src/main.rs index 1cfae13..f0ce410 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use std::process::exit; -use axum::{Router, routing::get}; +use axum::Router; use dotenvy::dotenv; use tokio::signal; use tower_http::trace::TraceLayer; @@ -10,7 +10,8 @@ use tracing::{error, info}; use tracing_subscriber::{EnvFilter, fmt, prelude::*}; mod config; -mod health; +mod handlers; +mod routes; use config::Config; @@ -41,7 +42,8 @@ async fn main() { // Build the Axum router let app = Router::new() - .route("/health", get(health::health)) + // .nest("/health", routes::health::health::health_routes()) + .nest("/health", routes::health::health::health_routes()) .layer(TraceLayer::new_for_http()); // Run the server diff --git a/src/routes/health/health.rs b/src/routes/health/health.rs new file mode 100644 index 0000000..a13a476 --- /dev/null +++ b/src/routes/health/health.rs @@ -0,0 +1,9 @@ +// src/routes/health/health.rs + +use axum::{Router, routing::get}; + +use crate::handlers::health::health::health; + +pub fn health_routes() -> Router { + Router::new().route("/", get(health)) +} diff --git a/src/routes/health/mod.rs b/src/routes/health/mod.rs new file mode 100644 index 0000000..33c3aa4 --- /dev/null +++ b/src/routes/health/mod.rs @@ -0,0 +1,4 @@ +// src/routes/health/mod.rs + +pub mod health; + diff --git a/src/routes/mod.rs b/src/routes/mod.rs new file mode 100644 index 0000000..e81b416 --- /dev/null +++ b/src/routes/mod.rs @@ -0,0 +1,3 @@ +// src/routes/mod.rs + +pub mod health;