Project: Eerste rust API | |
---|---|
Naam | Eerste rust API |
Door | Squirl |
Status | Afgerond |
Madskillz | Rust, systemd |
Doel / Omschrijving | |
Process om een API framework te kiezen in rust | |
Alle Projecten - Project Toevoegen |
- Doel
Voor dat ik begin met dit project gebruikte ik veel FastAPI, wat geschreven is in python. Werkt best goed, maar wat wel vaker is in python, het schaalt niet echt lekker, en de verdere problemen bij python. Wat FastAPI wel heel erg goed doet is documentatie maken (en type checking van input en outputs met pydantic), en je krijgt toegang tot alle libraries.
Ik heb veel goede en minder goede dingen gehoord over Rust, maar het is bijzonder snel met memory safety. Dus klinkt het als een goede volgende stap naast C. Als requirements voor de API heb ik leesbaarheid hoog staan, en heb geen zin om zelf documentatie te schrijven.
- Project doel
Ik zit al een tijdje met het idee om een service te maken zoals IP Chicken (een service om je externe ip terug te krijgen). Dit lijkt me leuk en handig om zo iets te hebben :shrug:.
Mn idee is om de nieuwe API achter een nginx instance te hangen en met 'proxy_pass X-Real-IP' het caller IP door te geven aan de service. Dit zal vast makkelijker kunnen, of zelfs in nginx, maar ik wil rust leren en heb een hopelijk eenvoudig project nodig.
- Framework zoektocht
Ik ben niet van plan om zelf een framework te maken, of met sockets te werken. Dus ik heb een framework nodig die veel voor me doet, maar niet te veel.
Tijdens het zoeken ben ik iemand tegen gekomen met een blog die ongeveer het zelfde doet als dat ik zou willen. Deze blog serie vergelijkt meerdere API frameworks, die hostbaar zijn en documentatie genereren. Spoiler alert! de blog serie komt uit op het Rocket framework.
- Doen wat de blog doet
De blog is uitgekomen op Rocket, met best goede vergelijkingen en onderbouwingen. Ik heb er meerdere dagen ingestoken om een goed werkende API te krijgen. Ik was behoorlijk stuk aan het gaan over hoe ik documentatie bij een endpoint krijg, en kreeg het maar niet op redelijke manier voor elkaar :/.
- Space kennis
Ik heb een rondvraag gedaan binnen spacechat of er iemand bezig is of ervaring heeft met rust. En YES, iemand is met rust mensen aan het werken! Van die deelnemer heb ik het Abacus project van de nederlandse kiesraad door gekregen, DIT WAS HEEL ERG FIJN!!!!!!1!!
Ik ben naar de backend gegaan, en zag binnen de sources 'authentication' staan, en daarna een [https://github.com/kiesraad/abacus/blob/main/backend/src/authentication/api.rs api.rs, daar moet wel wat bruikbaars in zitten. Abacus werkt met het Axum framework, en gebruikt utopia om documentatie te maken en serveren. Vanuit FastAPI ben in een nieuwere versie van de OpenAPI documentatie gewend, het ziet er net iets anders uit maar werkt het zelfde.
Er is een functie 'whoami', en deze zag er best leesbaar uit:
#[utoipa::path( get, path = "/api/user/whoami", responses( (status = 200, description = "The current user name and id", body = LoginResponse), (status = 401, description = "Invalid user session", body = ErrorResponse), (status = 500, description = "Internal server error", body = ErrorResponse), ), )] async fn whoami(user: Option<User>) -> Result<impl IntoResponse, APIError> { let user = user.ok_or(AuthenticationError::UserNotFound)?; Ok(Json(LoginResponse::from(&user))) }
Mischien nog wel leesbaarder dan een vergelijkbare API in FastAPI.... (en IMO betere defenities van responses).
- Doen wat de kiesraad doet
De code van Abacus ziet er erg leesbaar en begrijpelijk uit (note: komt van iemand die nieuw is met rust)!
Axum code ziet er uit zoals ik het ken vanuit FastAPI, het ziet er leesbaar uit en met goede online documentatie en veel features. Ik kan niet anders dan hier een werkende API van te maken.
- Axum IP API
Ik ben begonnen (zoals ik met vrijwel elke api doe) een ping endpoint te maken, en deze gedocumenteerd te krijgen. Een soort 'hello world'. De hello world was wat Axum docs copypasten, en de Axum-Utopia was wat copypasten, en het werkt gewoon, zonder poespas zonder rare of lastig te begrijpen code. Alles werkte gewoon.
Vervolgens een dag ofzo bezig geweest om de Rust code te compileren (ik snap rust nog niet echt goed, maar heb het wel werkend gekregen!), daarna werkte het gewoon!
Ik ben de dagen ernaa bezig geweest om systemd te leren, zodat ik scriptjes heb om services te installeren en te updaten (vooralsnog meer regels script dan rust, whoops). Via de sripts is de API gedeployed op [1] met de API documentatie op het docs endpoint. Als laatste heb ik de code online gezet in een git repo. Mischien hebben anderen er ook nog wat aan, wie weet.
- Resultaat
Ik heb tot nu toe de meeste ervaring met embedded C, en vind Rust best lastig te begrijpen. Ik snap waarom het memory safe is, en ik snap ook waarom niet iedereen het gebruikt. Het voelt een beetje aan als C met restricties, en objecten (iiieeeeee OOP #opinionated). Met FastAPI heb ik aardig wat standaard python problemen gehad: Object is None, Oject bestaat niet, Object is niet van het goede type, je lijst index is out of bounds, etc.. Allemaal dingen waarbij ik het idee heb dat die problemen met Rust lastig tot onmogelijk zijn om te hebben.
Ik denk wel meer met Rust te gaan werken, en het snel in productie omgevingen te kunnen gebruiken. Mijn algehele indrug van Rust is dat ik het een rare taal vind, met veel restricties, en daardoor bijzonder fijn vind om te gebruiken.
Tot slot: ik raad Rust aan als je een fijne en snelle programeer taal wilt, waarbij je at runtime weinig tot geen onverwachte gedragingen gaat hebben.
The end: 18 mei 2025