{"id":48147533,"url":"https://github.com/kavinda-100/simple-axum-sqlx-api","last_synced_at":"2026-04-04T17:01:44.877Z","repository":{"id":340928416,"uuid":"1168197861","full_name":"kavinda-100/simple-axum-sqlx-api","owner":"kavinda-100","description":"A production-ready REST API built with Rust, Axum, and SQLx, featuring a clean architecture pattern similar to Express.js MVC structure. This project demonstrates best practices for building scalable, maintainable web services in Rust.","archived":false,"fork":false,"pushed_at":"2026-02-27T07:16:44.000Z","size":46,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-27T12:42:36.859Z","etag":null,"topics":["axum","postgresql","rest-api","rust","sqlx"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kavinda-100.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-27T05:41:10.000Z","updated_at":"2026-02-27T07:16:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kavinda-100/simple-axum-sqlx-api","commit_stats":null,"previous_names":["kavinda-100/simple-axum-sqlx-api"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/kavinda-100/simple-axum-sqlx-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kavinda-100%2Fsimple-axum-sqlx-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kavinda-100%2Fsimple-axum-sqlx-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kavinda-100%2Fsimple-axum-sqlx-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kavinda-100%2Fsimple-axum-sqlx-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kavinda-100","download_url":"https://codeload.github.com/kavinda-100/simple-axum-sqlx-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kavinda-100%2Fsimple-axum-sqlx-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31407391,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["axum","postgresql","rest-api","rust","sqlx"],"created_at":"2026-04-04T17:01:41.861Z","updated_at":"2026-04-04T17:01:44.454Z","avatar_url":"https://github.com/kavinda-100.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🚗 Simple Axum SQLx API\n\nA production-ready REST API built with Rust, Axum, and SQLx, featuring a clean architecture pattern similar to Express.js MVC structure. This project demonstrates best practices for building scalable, maintainable web services in Rust.\n\n[![Rust](https://img.shields.io/badge/rust-1.75%2B-orange.svg)](https://www.rust-lang.org/)\n[![Axum](https://img.shields.io/badge/axum-0.8-blue.svg)](https://github.com/tokio-rs/axum)\n[![SQLx](https://img.shields.io/badge/sqlx-0.8-green.svg)](https://github.com/launchbadge/sqlx)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\n## ✨ Features\n\n- 🏗️ **Clean Architecture** - Organized into Models, Controllers, and Routes\n- 🔄 **API Versioning** - Built-in support for API versioning (`/api/v1`)\n- 📦 **Consistent Response Format** - Standardized JSON responses across all endpoints\n- 🗃️ **Database Migrations** - Automatic schema migrations with SQLx\n- ⚡ **Async/Await** - Built on Tokio for high-performance async operations\n- 🔒 **Type Safety** - Leveraging Rust's type system for compile-time guarantees\n- 📝 **Full CRUD** - Complete Create, Read, Update, Delete operations\n- 🩺 **Health Check** - Built-in health monitoring endpoint\n\n## 🛠️ Technologies Used\n\n| Technology     | Purpose                                            |\n| -------------- | -------------------------------------------------- |\n| **Rust**       | Programming language                               |\n| **Axum**       | Web framework built on Tokio                       |\n| **SQLx**       | Async SQL toolkit with compile-time query checking |\n| **Tokio**      | Async runtime                                      |\n| **PostgreSQL** | Database                                           |\n| **Serde**      | Serialization/deserialization                      |\n| **Chrono**     | Date and time handling                             |\n| **dotenv**     | Environment variable management                    |\n\n## 📁 Project Structure\n\n```\nsrc/\n├── main.rs                      # Application entry point\n├── db/\n│   └── mod.rs                   # Database connection \u0026 migrations\n├── models/\n│   ├── mod.rs\n│   └── vehicle.rs               # Vehicle data models\n├── controllers/\n│   ├── mod.rs\n│   ├── root_controller.rs       # Root \u0026 health endpoints\n│   └── vehicle_controller.rs    # Vehicle business logic\n├── routes/\n│   ├── mod.rs\n│   ├── api.rs                   # Main route composition\n│   └── vehicle_routes.rs        # Vehicle route definitions\n└── utils/\n    ├── mod.rs\n    └── response.rs              # Standard API response wrapper\n```\n\n## 🚀 Getting Started\n\n### Prerequisites\n\n- Rust 1.75 or higher\n- PostgreSQL 12 or higher\n- Cargo (comes with Rust)\n\n### Installation\n\n1. **Clone the repository**\n\n    ```bash\n    git clone https://github.com/kavinda-100/simple-axum-sqlx-api.git\n    cd simple-axum-sqlx-api\n    ```\n\n2. **Set up PostgreSQL**\n\n    ```bash\n    # Create database\n    createdb vehicles_db\n\n    # Or using psql\n    psql -U postgres\n    CREATE DATABASE vehicles_db;\n    ```\n\n3. **Configure environment variables**\n\n    Create a `.env` file in the project root:\n\n    ```env\n    DATABASE_URL=postgresql://postgres:your_password@localhost:5432/vehicles_db\n    PORT=5000\n    ```\n\n4. **Install dependencies and run**\n\n    ```bash\n    # Build the project\n    cargo build\n\n    # Run the application\n    cargo run\n    ```\n\n    The server will start on `http://0.0.0.0:5000`\n\n### Database Migrations\n\nMigrations run automatically on startup. The SQLx migration files are located in the `migrations/` directory:\n\n```sql\n-- migrations/0001_init_tables.sql\nCREATE TABLE IF NOT EXISTS vehicles (\n    id SERIAL PRIMARY KEY,\n    make VARCHAR(255) NOT NULL,\n    model VARCHAR(255) NOT NULL,\n    year INT NOT NULL,\n    vin VARCHAR(255) UNIQUE NOT NULL,\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n```\n\n## 📚 API Documentation\n\n### Base URL\n\n```\nhttp://localhost:5000\n```\n\n### Response Format\n\nAll API responses follow a consistent structure:\n\n```json\n{\n\t\"success\": true,\n\t\"status_code\": 200,\n\t\"message\": \"Descriptive message\",\n\t\"data\": {\n\t\t/* Response data */\n\t}\n}\n```\n\n### Endpoints\n\n#### Root Endpoints\n\n| Method | Endpoint  | Description                  |\n| ------ | --------- | ---------------------------- |\n| GET    | `/`       | Welcome message and API info |\n| GET    | `/health` | Health check endpoint        |\n\n##### Example: Root Response\n\n```http\nGET /\n\nResponse:\n{\n  \"message\": \"Welcome to the Vehicle API!\",\n  \"version\": \"1.0\",\n  \"endpoints\": {\n    \"vehicles\": \"/api/v1/vehicles\"\n  }\n}\n```\n\n---\n\n#### Vehicle Endpoints\n\nBase path: `/api/v1/vehicles`\n\n##### 1. Get All Vehicles\n\n```http\nGET /api/v1/vehicles\n```\n\n**Response:** `200 OK`\n\n```json\n{\n\t\"success\": true,\n\t\"status_code\": 200,\n\t\"message\": \"Successfully fetched all vehicles\",\n\t\"data\": [\n\t\t{\n\t\t\t\"id\": 1,\n\t\t\t\"make\": \"Toyota\",\n\t\t\t\"model\": \"Corolla\",\n\t\t\t\"year\": 2020,\n\t\t\t\"vin\": \"1HGBH41JXMN109186\",\n\t\t\t\"created_at\": \"2026-02-27T05:11:13.806911\",\n\t\t\t\"updated_at\": \"2026-02-27T05:11:13.806911\"\n\t\t},\n\t\t{\n\t\t\t\"id\": 2,\n\t\t\t\"make\": \"BMW\",\n\t\t\t\"model\": \"X5\",\n\t\t\t\"year\": 2025,\n\t\t\t\"vin\": \"5UXCR6C0XJLL12345\",\n\t\t\t\"created_at\": \"2026-02-27T05:14:36.899771\",\n\t\t\t\"updated_at\": \"2026-02-27T05:14:36.899771\"\n\t\t}\n\t]\n}\n```\n\n##### 2. Get Vehicle by ID\n\n```http\nGET /api/v1/vehicles/:id\n```\n\n**Response:** `200 OK`\n\n```json\n{\n\t\"success\": true,\n\t\"status_code\": 200,\n\t\"message\": \"Vehicle found\",\n\t\"data\": {\n\t\t\"id\": 1,\n\t\t\"make\": \"Toyota\",\n\t\t\"model\": \"Corolla\",\n\t\t\"year\": 2020,\n\t\t\"vin\": \"1HGBH41JXMN109186\",\n\t\t\"created_at\": \"2026-02-27T05:11:13.806911\",\n\t\t\"updated_at\": \"2026-02-27T05:11:13.806911\"\n\t}\n}\n```\n\n**Error:** `404 Not Found`\n\n```json\n{\n\t\"status_code\": 404\n}\n```\n\n##### 3. Create Vehicle\n\n```http\nPOST /api/v1/vehicles\nContent-Type: application/json\n\n{\n  \"make\": \"Tesla\",\n  \"model\": \"Model 3\",\n  \"year\": 2024,\n  \"vin\": \"5YJ3E1EA1KF123456\"\n}\n```\n\n**Response:** `201 Created`\n\n```json\n{\n\t\"success\": true,\n\t\"status_code\": 201,\n\t\"message\": \"Vehicle created successfully\",\n\t\"data\": {\n\t\t\"id\": 4,\n\t\t\"make\": \"Tesla\",\n\t\t\"model\": \"Model 3\",\n\t\t\"year\": 2024,\n\t\t\"vin\": \"5YJ3E1EA1KF123456\",\n\t\t\"created_at\": \"2026-02-27T07:00:00.000000\",\n\t\t\"updated_at\": \"2026-02-27T07:00:00.000000\"\n\t}\n}\n```\n\n##### 4. Update Vehicle\n\n```http\nPOST /api/v1/vehicles/:id\nContent-Type: application/json\n\n{\n  \"make\": \"Tesla\",\n  \"model\": \"Model S\",\n  \"year\": 2024,\n  \"vin\": \"5YJ3E1EA1KF123456\"\n}\n```\n\n**Response:** `200 OK`\n\n```json\n{\n\t\"success\": true,\n\t\"status_code\": 200,\n\t\"message\": \"Vehicle updated successfully\",\n\t\"data\": {\n\t\t\"id\": 4,\n\t\t\"make\": \"Tesla\",\n\t\t\"model\": \"Model S\",\n\t\t\"year\": 2024,\n\t\t\"vin\": \"5YJ3E1EA1KF123456\",\n\t\t\"created_at\": \"2026-02-27T07:00:00.000000\",\n\t\t\"updated_at\": \"2026-02-27T07:15:00.000000\"\n\t}\n}\n```\n\n##### 5. Delete Vehicle\n\n```http\nDELETE /api/v1/vehicles/:id\n```\n\n**Response:** `200 OK` (with JSON body)\n\n```json\n{\n\t\"success\": true,\n\t\"status_code\": 204,\n\t\"message\": \"Vehicle deleted successfully\",\n\t\"data\": null\n}\n```\n\n**Error:** `404 Not Found`\n\n```json\n{\n\t\"status_code\": 404\n}\n```\n\n### Status Codes\n\n| Code | Description                 |\n| ---- | --------------------------- |\n| 200  | Success                     |\n| 201  | Created                     |\n| 204  | No Content (Delete success) |\n| 404  | Not Found                   |\n| 500  | Internal Server Error       |\n\n## 🧪 Testing with API.http\n\nThe project includes an `API.http` file for testing with REST Client extensions:\n\n```http\n@baseUrl = http://localhost:5000\n@apiV1 = http://localhost:5000/api/v1\n\n### Get all vehicles\nGET {{apiV1}}/vehicles\n\n### Create a new vehicle\nPOST {{apiV1}}/vehicles\nContent-Type: application/json\n\n{\n  \"make\": \"Toyota\",\n  \"model\": \"Camry\",\n  \"year\": 2024,\n  \"vin\": \"4T1B11HK1KU123456\"\n}\n```\n\n## 🏗️ Development Guide\n\n### Adding a New Resource\n\nTo add a new resource (e.g., `users`), follow these steps:\n\n1. **Define Database Schema** (create a new migration file in `migrations/`)\n\n    ```sql\n    -- migrations/0002_create_users_table.sql\n    CREATE TABLE IF NOT EXISTS users (\n        id SERIAL PRIMARY KEY,\n        name VARCHAR(255) NOT NULL,\n        email VARCHAR(255) UNIQUE NOT NULL,\n        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n    );\n    ```\n\n2. **Create Model** (`src/models/user.rs`)\n\n    ```rust\n    use serde::{Deserialize, Serialize};\n    use sqlx::FromRow;\n\n    #[derive(Deserialize, Debug)]\n    pub struct UserPayload {\n        pub name: String,\n        pub email: String,\n    }\n\n    #[derive(Serialize, FromRow, Debug)]\n    pub struct User {\n        pub id: i32,\n        pub name: String,\n        pub email: String,\n    }\n    ```\n\n3. **Create Controller** (`src/controllers/user_controller.rs`)\n\n    ```rust\n    use axum::{Json, extract::State, http::StatusCode};\n    use sqlx::PgPool;\n    use crate::models::user::{User, UserPayload};\n    use crate::utils::response::ApiResponse;\n\n    pub async fn get_all_users(\n        State(pool): State\u003cPgPool\u003e\n    ) -\u003e Result\u003cJson\u003cApiResponse\u003cVec\u003cUser\u003e\u003e\u003e, StatusCode\u003e {\n        // Implementation\n    }\n    ```\n\n4. **Create Routes** (`src/routes/user_routes.rs`)\n\n    ```rust\n    use axum::{Router, routing::get};\n    use sqlx::PgPool;\n    use crate::controllers::user_controller::get_all_users;\n\n    pub fn user_routes(pool: PgPool) -\u003e Router {\n        Router::new()\n            .route(\"/users\", get(get_all_users))\n            .with_state(pool)\n    }\n    ```\n\n5. **Register Routes** (in `src/routes/api.rs`)\n    ```rust\n    fn api_v1_routes(pool: PgPool) -\u003e Router {\n        Router::new()\n            .merge(vehicle_routes(pool.clone()))\n            .merge(user_routes(pool.clone()))  // Add this\n    }\n    ```\n\n### Database Queries\n\nSQLx provides compile-time query checking. Example:\n\n```rust\nlet vehicle = sqlx::query_as::\u003c_, Vehicle\u003e(\n    \"SELECT * FROM vehicles WHERE id = $1\"\n)\n.bind(id)\n.fetch_one(\u0026pool)\n.await?;\n```\n\n## 🔧 Configuration\n\nConfiguration is managed through environment variables:\n\n| Variable       | Description                  | Default  |\n| -------------- | ---------------------------- | -------- |\n| `DATABASE_URL` | PostgreSQL connection string | Required |\n| `PORT`         | Server port                  | 5000     |\n\n## 👨‍💻 Author\n\n**Kavinda**\n\n- GitHub: [@kavinda-100](https://github.com/kavinda-100)\n\n## 🙏 Acknowledgments\n\n- [Axum](https://github.com/tokio-rs/axum) - Excellent web framework\n- [SQLx](https://github.com/launchbadge/sqlx) - Powerful async SQL toolkit\n- [Tokio](https://tokio.rs/) - The async runtime for Rust\n\n---\n\n⭐ If you find this project helpful, please consider giving it a star!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkavinda-100%2Fsimple-axum-sqlx-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkavinda-100%2Fsimple-axum-sqlx-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkavinda-100%2Fsimple-axum-sqlx-api/lists"}