Learning-Rust.Github.io: Labs: Project 1 – RESTful API Workspace

dumindunuwan1 pts0 comments

Building a Containerized RESTful API · Learning Rust

Close

In this series,<br>We build a production-ready containerized RESTful API server application using Axum, Tokio, Tower, Serde, Toasty ORM, Garde, Utoipa with Docker and PostgreSQL.<br>Hyper, Axum, Tokio and Tower: The most prominent HTTP server ecosystem at the time of writing.<br>Toasty ORM: The most promising Object-Relational Mapper (ORM), built by the creators of Tokio and Axum.<br>Serde and Utoipa: The most prominent serialization framework and OpenAPI 3.1 specification generator.<br>Garde: The most promising and most feature-rich validation library in Rust at the time of writing.

Database Design<br>To keep this series simple, we use only a single database table named books.<br>Column NameDatatypeNot NullPrimary Keycreated_atTIMESTAMPTZ✅updated_atTIMESTAMPTZ✅idUUID✅✅published_dateDATE✅statusSMALLINT✅titleTEXT✅descriptionTEXTimage_urlTEXT<br>Important<br>For high-traffic systems with very large PostgreSQL tables that containing millions/billions of rows, arranging fixed-width columns by decreasing alignment requirements can reduce tuple alignment padding; potentially minimize row/ storage size. This technique is called &ldquo;Column Tetris &rdquo;.<br>For this optimization, order fixed-width table columns by decreasing alignment requirements.8-byte alignment types: bigint, bigserial, double precision/ float8, timestamp, timestamptz, time, interval<br>4-byte alignment types: integer, serial, real/ float4, uuid, date<br>2-byte alignment types: smallint, smallserial<br>1-byte alignment types: boolean<br>Variable-width types (at last): numeric, text, character varying/ varchar, bytea

However, it&rsquo;s ok to follow a more readable column format, when your table schema changes frequently.

Endpoints<br>NameHTTP MethodRouteList BooksGET/v1/booksCreate BookPOST/v1/booksRead BookGET/v1/books/{id}Update BookPUT/v1/books/{id}Delete BookDELETE/v1/books/{id}HealthGET/livezRequest (POST/PUT)<br>"title": "Harry Potter and the Deathly Hallows",<br>"description": "It is the seventh and final novel in the Harry Potter series",<br>"image_url": "https://upload.wikimedia.org/wikipedia/en/a/a9/Harry_Potter_and_the_Deathly_Hallows.jpg",<br>"published_date": "2007-07-21",<br>"status": "verified"<br>Response (GET/POST/PUT)<br>"created_at": "2027-01-01T00:00:00.123456Z",<br>"updated_at": "2027-01-01T00:00:00.123456Z",<br>"id": "01bbbbbb-bbbb-7bbb-8bbb-bbbbbbbbbbbb",<br>"published_date": "2007-07-21",<br>"status": "verified",<br>"title": "Harry Potter and the Deathly Hallows",<br>"description": "It is the seventh and final novel in the Harry Potter series",<br>"image_url": "https://upload.wikimedia.org/wikipedia/en/a/a9/Harry_Potter_and_the_Deathly_Hallows.jpg"

Note<br>The list endpoint returns an array of above response JSON.

Form Validation<br>"errors": {<br>"title": "Must be at least 1 character long",<br>"image_url": "Must be a valid URL"<br>Project Structure<br>rest_api_workspace<br>├── crates<br>│ ├── book_service<br>│ │ ├── src<br>│ │ │ ├── bin<br>│ │ │ │ ├── app.rs<br>│ │ │ │ ├── migration.rs<br>│ │ │ │ └── apidoc.rs<br>│ │ │ ├── app<br>│ │ │ │ ├── mod.rs<br>│ │ │ │ ├── book<br>│ │ │ │ │ ├── mod.rs<br>│ │ │ │ │ ├── handler.rs<br>│ │ │ │ │ └── payload.rs<br>│ │ │ │ └── shared<br>│ │ │ │ ├── mod.rs<br>│ │ │ │ ├── pagination.rs<br>│ │ │ │ └── validation.rs<br>│ │ │ ├── models<br>│ │ │ │ ├── mod.rs<br>│ │ │ │ └── book.rs<br>│ │ │ ├── config.rs<br>│ │ │ ├── errors.rs<br>│ │ │ ├── state.rs<br>│ │ │ ├── routes.rs<br>│ │ │ ├── openapi.rs<br>│ │ │ └── lib.rs<br>│ │ ├── Toasty.toml<br>│ │ ├── toasty<br>│ │ │ ├── history.toml<br>│ │ │ ├── migrations<br>│ │ │ │ └── 0000_migration.sql<br>│ │ │ └── snapshots<br>│ │ │ └── 0000_snapshot.toml<br>│ │ ├── Cargo.toml<br>│ │ ├── openapi.yaml<br>│ │ ├── compose.yml<br>│ │ ├── prod.Dockerfile<br>│ │ ├── Dockerfile<br>│ │ └── justfile<br>│ └── README.md<br>├── Cargo.lock<br>├── Cargo.toml<br>├── rustfmt.toml<br>├── LICENSE<br>├── README.md<br>└── justfile<br>Containerization Environment<br>EnvironmentRust Image TypeRust Image SizePostgres Image TypePostgres Image SizeDevelopmentrust:1.97-slim~ 900 MBpostgres:18-alpine~ 300MBProductiondistroless/static-debian13:nonroot~ 30 MB

Close

alignment toml types series toasty books

Related Articles