{"id":20261134,"url":"https://github.com/rameshovyas/feeling-axum","last_synced_at":"2026-06-08T00:31:07.099Z","repository":{"id":196304489,"uuid":"585806790","full_name":"rameshovyas/feeling-axum","owner":"rameshovyas","description":"Feeling awesome with Axum","archived":false,"fork":false,"pushed_at":"2023-03-06T03:37:27.000Z","size":75,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-03T18:48:51.796Z","etag":null,"topics":["axum","axum-framework","backend-development","rust-backend","rust-lang","web-api"],"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/rameshovyas.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}},"created_at":"2023-01-06T05:56:28.000Z","updated_at":"2025-02-28T06:00:30.000Z","dependencies_parsed_at":"2023-09-24T09:03:33.446Z","dependency_job_id":null,"html_url":"https://github.com/rameshovyas/feeling-axum","commit_stats":null,"previous_names":["rameshovyas/feeling-axum"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rameshovyas/feeling-axum","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rameshovyas%2Ffeeling-axum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rameshovyas%2Ffeeling-axum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rameshovyas%2Ffeeling-axum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rameshovyas%2Ffeeling-axum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rameshovyas","download_url":"https://codeload.github.com/rameshovyas/feeling-axum/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rameshovyas%2Ffeeling-axum/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34043822,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-07T02:00:07.652Z","response_time":124,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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","axum-framework","backend-development","rust-backend","rust-lang","web-api"],"created_at":"2024-11-14T11:24:04.870Z","updated_at":"2026-06-08T00:31:07.066Z","avatar_url":"https://github.com/rameshovyas.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# feeling-axum\nFeeling awesome with Axum - A Rust Framework for building RESTful APIs.\n\n# Table of contents\n1. [Introduction to axum](#introduction)\n2. [Hello World Application in Axum Rust](#hello_world)  \n3. [Routing in Axum Rust](#routing)\n4. [Posting a String Data in Axum Rust](#post_string)\n5. [Posting JSON Data in Axum Rust](#post_json)\n6. [Dealing with Path Variables in Axum Rust](#path_variables)\n7. [Handling Query Parameters in Axum Rust](#query_params)\n8. [Extracting User Agent - Standard Headers in Axum Rust ](#user_agent)\n9. [Extracting Data from Custom Headers in Axum Rust](#custom_headers)\n10. [CORS in Axum Rust](#cors)\n11. [Sharing data among middleware layers in Axum Rust](#shared_data)\n12. [Returning HTTP Response in Axum Rust](#http_response)\n13. [Returning JSON Data in Axum Rust](#json_response)\n14. [Validating Incoming JSON Data in Axum Rust](#validate_json)\n15. [Using SeaORM to connect with postgres database in Axum Rust](#db_seaorm)\n16. [Passing Data To Route Handlers in Axum Rust](#passing_data)\n17. [Inserting Data in Database using Sea ORM in Axum Rust](#insert_data)\n\n## Introduction to axum\u003ca name=\"introduction\"\u003e\u003c/a\u003e\n[Axum](\"https://crates.io/crates/axum\") is a web application framework for Rust programming language. It is developed by the same people who developed [tokio](\"https://tokio.rs/\"). \n\n## Hello World Application in Axum Rust \u003ca name=\"hello_world\"\u003e\u003c/a\u003e\nThis is a very simple http server that has a single route \"/\", demonstrating how we can use axum to spin a simple web server. \nYou can find the complete source code in **[hello_world](\"https://github.com/rameshovyas/feeling-axum/tree/main/hello_world)** directory.\n \n## Routing in Axum Rust \u003ca name=\"routing\"\u003e\u003c/a\u003e\nThis simple axum application explains how we can add different routes with different HTTP methods in our application. We have seprated the routing logic in a seprate module viz. routes that eventually imports respective route handlers from their respective code files. You can find this application in **routing** directory in this repo.\n\n## Posting a String Data in Axum Rust\u003ca name=\"post_string\"\u003e\u003c/a\u003e\nA very simple application written in axum Rust that demonstartes how we can post a string data to an api endpoint. This application creates an api endpoint that accepts a string data via HTTP POST method and echos back to the client to verify what has been extracted at api endpoint. The extraction of string in axum is very simple we just have a parameter ('body' here) of type string in the route handler, which eventually returns the same data.\n```\npub async fn echo_post_string(body: String) -\u003e String {\n    body\n}\n```\nThe sample application can be found in **post_string** directory in this repo.\n\n## Posting JSON Data in Axum Rust \u003ca name=\"post_json\"\u003e\u003c/a\u003e\nAxum web application showing how to post JSON data and extract it on server fo rprocessing. It is a simple application that fetches posted JSON into a struct and then creates a new struct for JSON response from the server. We have use **serde** to deserialize and serialize json request and response. Below is the simple route handler for the same.\n\n```\nuse axum::{Json};\nuse serde::{Deserialize,Serialize};\n\n//struct for posted json data\n#[derive(Serialize,Deserialize, Debug)]\npub struct PostedJsonData {\n    data : String,\n}\n\n// struct for json response from server\n#[derive(Serialize)]\npub struct JsonResponseFromServer {\n    data : String,\n    message_from_server: String\n}\n\n// route handler that extract incoming jsn data and creates a new json response from it.\npub async fn echo_post_json( Json(body): Json\u003cPostedJsonData\u003e) -\u003e Json\u003cJsonResponseFromServer\u003e {\n       Json(JsonResponseFromServer { data: body.data, message_from_server: \"Thank you for posting JSON data\".to_owned()})\n}\n```\n\nThis project is available in **post_json** directory of this repo.\n\n## Dealing with Path Variables in Axum Rust \u003ca name=\"path_variables\"\u003e\u003c/a\u003e\nSimple application in axum web that demonstrates how we can extract path variables from url in an api call.\nPath variables can be mapped as parameters to route handler functions. See below code that defines a route handler for **http://localhost/25**. The value **25** will be mapped to the id variable in the route handler. Using **Path** we can extract it as shown in code below:\n\n#### Routes\n```\npub fn create_routes() -\u003e Router\u003c(),Body\u003e {\n    Router::new()\n           .route(\"/path_variables/:id\", get(path_variables))\n}\n\n```\n\n#### Route handler function\n```\nuse axum::extract::Path;\n\npub async fn path_variables(Path(id) : Path\u003ci32\u003e) -\u003eString {\n    id.to_string()\n}\n```\nThe complete project can be found in **path_variables** directory in this repo.\n\n## Handling Query Parameters in Axum Rust \u003ca name=\"query_params\"\u003e\u003c/a\u003e\nAs we have see in previous section regarding path variables, how we can extract path variables simply mapping it with parametrs to handler function. Query parameters are bit different to deal with as they are not part of path. Query parameters are list of key value pairs seprated by a **\u0026** and are added to the url after **?**. To deal with query parameter we need to do bit like we have handled json data in previous section. We will be creating a struct representing our query parameters and like JSON we need to deserialize it so we will be again using **serde** . Here we have also used Serialize as we will be returning a JSON response. Below code show how we can handle this type of url : http://localhost:3000/query_params?category=programming\u0026year=2023 . Here we have two query params (category and year). We have just echoed back the query parameters in JSON format for now, but the logic for handling query parameters is explained.\n\n```\nuse axum::{extract::Query, Json};\nuse serde::{Serialize,Deserialize};\n\n#[derive(Serialize,Deserialize)]\npub struct QueryParams {\n    category : String,\n    year: i32\n}\npub async fn query_params(Query(query): Query\u003cQueryParams\u003e) -\u003e Json\u003cQueryParams\u003e {\n    Json(query)\n}\n```\n#### The JSON response we will be getting\n```\n{\n  \"category\": \"programming\",\n  \"year\": 2023\n}\n```\n\nThe complete project can be found in **query_params** directory of this repo.\n\n\n## Extracting User Agent - Standard Headers in Axum Rust \u003ca name=\"user_agent\"\u003e\u003c/a\u003e\nTo extract standard header data for eg. user agent we will be using **TypedHeader** extractor. For this we need to add **header** feature to axum in cargo.toml file, that can be done as follows\n\u003e cargo add axum -F headers\n\nAn example route handler for extracting user agent is as follows : \n\n```\nuse axum::{TypedHeader, headers::UserAgent};\npub async fn user_agent(TypedHeader(user_agent) : TypedHeader\u003cUserAgent\u003e) -\u003e String{\n    user_agent.to_string()\n}\n```\nThe complete project can be found in **std_headers** directory of this repo.\n\n## Extracting Data from Custom Headers in Axum Rust \u003ca name=\"custom_headers\"\u003e\u003c/a\u003e\nMany times we need to pass custom data withing headers, in axum how to extract custom headers is very simple we just need to use **HeaderMap** for this. HeaderMap can extract custom header data.\n\n```\nuse axum::http::HeaderMap;\n\npub async fn custom_headers(headers : HeaderMap) -\u003e String{\n   let message_value = headers.get(\"x-message\").unwrap();\n   let message = message_value.to_str().unwrap().to_owned();\n   message\n}\n\n```\n\nThe complete project can be found in **custom_headers** directory of this repo.\n\n## CORS in Axum Rust \u003ca name=\"cors\"\u003e\u003c/a\u003e\nAxum does not have any middleware system of its own, where as it uses middleware from **tower** and **tower-http**. So we need to add that into our project by the following command.\n\u003e cargo add tower-http -F cors\n\nAfter adding tower-http with cors feature, we need to add the following code for adding corslayer and routes.\n```\npub fn create_routes() -\u003e Router\u003c(),Body\u003e {\n   \n    //Setting up the CORS Layer\n    let cors = CorsLayer::new()\n        .allow_methods([Method::GET,Method::POST])\n        .allow_origin(Any);\n    \n    Router::new()\n            .route(\"/\", get(index))\n            .route(\"/users\",get(users))\n            .route(\"/echo_post_string\", post(echo_post_string))\n            .route(\"/echo_post_json\", post(echo_post_json))\n            .route(\"/path_variables/:id\", get(path_variables))\n            .route(\"/query_params\", get(query_params))\n            .route(\"/user_agent\", get(user_agent))\n            .route(\"/custom_headers\", get(custom_headers))\n            .layer(cors) // Adding the CorsLayer at the last so that it effects all the routes\n}\n```\n\nThe complete project can be found in **cors** directory of this repo.\n\n## Sharing data among middleware layers in Axum Rust \u003ca name=\"shared_data\"\u003e\u003c/a\u003e\nThis demo project show how we can use shared data amon middleware layers in axum. The conecpt is very simple we just added a layer with the dat ausing **Extension** . Now this shared data can be extracted from any route using the same Extension. The rule is we have to keep all routes where we want to share data above the layer in the routing sequence.\n\nThe route routing sequence should be : \n\n```\nmod index;\nmod users;\nmod echo_post_string;\nmod echo_post_json;\nmod path_variables;\nmod query_params;\nmod user_agent;\nmod custom_headers;\nmod middleware_data;\n\nuse axum::{Router, body::Body, routing::get,routing::post, http::Method, Extension};\nuse index::index;\nuse tower_http::cors::{CorsLayer, Any};\nuse users::users;\nuse echo_post_string::echo_post_string;\nuse echo_post_json::echo_post_json;\nuse path_variables::path_variables;\nuse query_params::query_params;\nuse user_agent::user_agent;\nuse custom_headers::custom_headers;\nuse middleware_data::middleware_data;\n\n//Strcture representing shared data\n#[derive(Clone)]\npub struct SharedData {\n    pub data: String,\n}\n\n\n// public function that returns handle to all routers\npub fn create_routes() -\u003e Router\u003c(),Body\u003e {\n   \n    //Setting up the CORS Layer\n    let cors = CorsLayer::new()\n        .allow_methods([Method::GET,Method::POST])\n        .allow_origin(Any);\n\n    //Instantiating shared data\n    let shared_data = SharedData { data : \"This is shared data\".to_owned(),} ;   \n    Router::new()\n            .route(\"/\", get(index))\n            .route(\"/users\",get(users))\n            .route(\"/echo_post_string\", post(echo_post_string))\n            .route(\"/echo_post_json\", post(echo_post_json))\n            .route(\"/path_variables/:id\", get(path_variables))\n            .route(\"/query_params\", get(query_params))\n            .route(\"/user_agent\", get(user_agent))\n            .route(\"/custom_headers\", get(custom_headers))\n            .route(\"/middleware_data\", get(middleware_data))\n            .layer(cors) // Adding the CorsLayer at the last so that it effects all the routes\n\n            //adding layer for shared data\n            .layer(Extension(shared_data))\n}\n\n```\n\nAnd the this shared data can be extracted in the route handler as below : \n\n```\nuse axum::Extension;\nuse super::SharedData;\n\npub async fn middleware_data(Extension(shared_data):Extension\u003cSharedData\u003e) -\u003eString {\n    shared_data.data\n}\n```\nFind the complete project in **shared_data** directory.\n\n## Returning HTTP Response in Axum Rust\u003ca name=\"http_response\"\u003e\u003c/a\u003e\nThis project demonstrates how we can return specific HTTP response from a route. For example if we want a route to respond 201 instead 200, we have to do modify our route handlers like below : \n\n```\nuse axum::http::StatusCode;\nuse axum::response::IntoResponse;\n\n// Anything that implements IntoResponse can be returned from a handler\n// Use `impl IntoResponse` to avoid writing the whole type\npub async fn status_codes() -\u003eimpl IntoResponse {\n    (\n        StatusCode::CREATED,\n        \"This is 201 response and not 200\".into_response()\n    )\n}\n```\nThe complete project is in **status_codes** directory.\n\n\n## Returning JSON Data in Axum Rust\u003ca name=\"json_response\"\u003e\u003c/a\u003e\nTo return JSON data from a route we need to have a struct for the data and using **axum::Json** we can convert the struct data to JSON data, see the following route handler doing this.\n\n```\nuse axum::Json;\nuse serde::Serialize;\n\n#[derive(Serialize)]\npub struct Data {\n    username: String,\n    age :i32,\n}\n\npub async fn return_json() -\u003e Json\u003cData\u003e {\n    let data = Data {username:\"ramesh\".to_owned(), age:21,};\n    Json(data)\n}\n```\nThe complete project is available in **returning_json** directory.\n\n## Validating Incoming JSON Data in Axum Rust\u003ca name=\"validate_json\"\u003e\u003c/a\u003e\nTo validate incoming JSON data we need to deserialize with serde, the following route handler does an example validation.\n\n```\nuse axum::Json;\nuse serde::Deserialize;\n\n#[derive(Deserialize)]\npub struct RequestData {\n    username : String,\n    password : String, \n    name : Option\u003cString\u003e,   \n}\n\npub async fn validate_json(Json(data) : Json\u003cRequestData\u003e){\n    \n}\n```\n\nThe **Option\u003cString\u003e** specifies that this field is optional field.\n\nThe complete project can be found at **validate_json** directory.\n\n## Using SeaORM to connect with postgres database in Axum Rust\u003ca name=\"db_seaorm\"\u003e\u003c/a\u003e\nA simple project in axum rust to connect with postgres database and create models for the underline table so that data can be accessed inside the rust code. We have created **.env** file to store environment variable for database connection string. For handling environment variables we have used **dotenvy and dotenvy-macro** crates and for **orm** we have used **sea-orm**. The **sea-orm** itself requires **tokio** for async that is why that also has been included in the project refrence.\n\nWe have used **sea-orl-cli** to generate model files\n\u003e sea-orm-cli generate entity -o src/database\n\nThis command generated model files in **src/database** directory.\n\nThe complete project can be found at **db_seaorm** directory.\n\n## Passing Data To Route Handlers in Axum Rust\u003ca name=\"passing_data\"\u003e\u003c/a\u003e\nTo pass data between route handlers we need to create a middleware layer extension below all the routes in which we wnat that data to be shared. See the routing and route handler code below : \n\n### Routing logic\n```\nuse axum::{Router, body::Body, routing::get,routing::post, Extension};\nuse passing_data::passing_data;\nuse sea_orm::DatabaseConnection;\n\n// public function that returns handle to all routers\npub fn create_routes(database: DatabaseConnection) -\u003e Router\u003c(),Body\u003e {\n    Router::new()\n           .route(\"/passing_data\", post(passing_data))\n\n           //Creating extension layer to share this database connectuion with all other routes\n           .layer(Extension(database))\n}\n```\n### Route Handler\n```\nuse axum::Extension;\nuse sea_orm::DatabaseConnection;\n\npub async fn passing_data(Extension(database) : Extension\u003cDatabaseConnection\u003e){\n\n}\n```\n\n## Inserting Data in Database using Sea ORM in Axum Rust \u003ca name=\"insert_data\"\u003e\u003c/a\u003e\nDemo project shows how we can use sea orm to insert a record in postgress database.\n\n```\nuse axum::Extension;\nuse sea_orm::{DatabaseConnection,Set, ActiveModelTrait};\nuse crate::database::users;\nuse chrono::{self, Utc};\npub async  fn create_user(Extension(database) : Extension\u003cDatabaseConnection\u003e){\n    \n    let new_user = users::ActiveModel {\n        email :  Set(\"ramesh@vyas.com\".to_owned()),\n        password :Set(\"123456\".to_owned()),\n        name : Set(\"Ramesh Vyas\".to_owned()),\n        created_on : Set(Utc::now().naive_utc()),     \n        ..Default::default()\n    };\n\n    let result = new_user.save(\u0026database).await.unwrap();\n    dbg!(result);\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frameshovyas%2Ffeeling-axum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frameshovyas%2Ffeeling-axum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frameshovyas%2Ffeeling-axum/lists"}