Copied to Clipboard
On Windows CMD, use:
curl -X POST http://localhost:3000/users ^
-H "Content-Type: application/json" ^
-d "{\"name\":\"Talha\",\"email\":\"talha@example.com\"}"
Expected response:
{"id":1,"name":"Talha","email":"talha@example.com"}
Get All Users
Request:
GET http://localhost:3000/users
curl:
curl http://localhost:3000/users
Expected response:
[{"id":1,"name":"Talha","email":"talha@example.com"}]
Get One User
Request:
GET http://localhost:3000/users/1
curl:
curl http://localhost:3000/users/1
Expected response:
{"id":1,"name":"Talha","email":"talha@example.com"}
If the user does not exist, the API returns:
404 NOT FOUND
Update User
Request:
PUT http://localhost:3000/users/1
Body:
{"name":"Updated Talha","email":"updated@example.com"}
curl:
curl -X PUT http://localhost:3000/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"Updated Talha","email":"updated@example.com"}'
Windows CMD:
curl -X PUT http://localhost:3000/users/1 ^
-H "Content-Type: application/json" ^
-d "{\"name\":\"Updated Talha\",\"email\":\"updated@example.com\"}"
Expected response:
{"id":1,"name":"Updated Talha","email":"updated@example.com"}
Delete User
Request:
DELETE http://localhost:3000/users/1
curl:
curl -X DELETE http://localhost:3000/users/1
If deleted successfully, the API returns:
204 NO CONTENT
If the user does not exist, the API returns:
404 NOT FOUND
Why We Did Not Put Everything in main.rs
For very small examples, putting all code in main.rs is okay.
But as your project grows, main.rs becomes hard to read.
This structure is better:
main.rs -> application startup
db.rs -> database setup
state.rs -> shared state
models.rs -> data types
handlers.rs -> request handlers
This makes the project easier to understand, maintain, and extend.
Current Limitations
This project is beginner-friendly, but it is not fully production-ready yet.
For production, we should improve:
- Error handling instead of using
.unwrap()
- Database migrations instead of creating tables in code
- Validation for user input
- Separate service/repository layers for larger apps
- Environment variables for database URL
But this version is a strong starting point.
Final Thoughts
In this article, we built a CRUD API using Axum, SQLite, and sqlx.
We learned:
- How to connect Axum with SQLite
- How to use a database connection pool
- How to share database access using state
- How to create clean file structure
- How to write Create, Read, Update, and Delete handlers
- How to test the API using curl or Postman
SQLite is a great choice when you are learning database integration because it is simple, local, and does not require a separate database server.
Once you understand this, switching to PostgreSQL later will be much easier because sqlx supports both SQLite and PostgreSQL.