chore(deps): Update to axum 0.7

This commit is contained in:
Felipe 2024-01-19 18:24:12 -03:00
parent 0191a7e2c1
commit 7d67ac830b
Signed by: pitbuster
SSH key fingerprint: SHA256:NLWXDJvkNDPTnUszcKt0McVeXWKTe5Lz0cIocZbA/pY
5 changed files with 435 additions and 313 deletions

592
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -5,33 +5,37 @@ edition = "2021"
license = "AGPL-3.0"
[dependencies]
axum = { version = "0.6.20", default-features = false, features = [
anyhow = "1.0.79"
axum = { version = "0.7.4", default-features = false, features = [
"json",
"tracing",
"tokio",
] }
dotenvy = "0.15.7"
futures = { version = "0.3.30", default-features = false }
serde = { version = "1.0.195", features = ["derive"] }
serde_json = "1.0.111"
sqlx = { version = "0.7.3", default-features = false, features = [
"macros",
"migrate",
"runtime-tokio",
"sqlite",
"tls-rustls",
] }
tokio = { version = "1.35.1", default-features = false, features = [
"macros",
"rt-multi-thread",
"signal",
] }
tower-http = { version = "0.5.1", default-features = false, features = ["fs"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.17", default-features = false, features = [
tracing-subscriber = { version = "0.3.18", default-features = false, features = [
"env-filter",
"tracing",
"fmt",
"tracing",
"tracing-log",
] }
tokio = { version = "1.34.0", default-features = false, features = [
"macros",
"signal",
"rt-multi-thread",
] }
dotenvy = "0.15.7"
tower-http = { version = "0.4.4", default-features = false, features = ["fs"] }
serde = { version = "1.0.192", features = ["derive"] }
serde_json = "1.0.108"
futures = { version = "0.3.29", default-features = false }
axum-test-helper = "0.3.0"
sqlx = { version = "0.7.2", default-features = false, features = [
"runtime-tokio",
"tls-rustls",
"macros",
"migrate",
"sqlite",
] }
anyhow = "1.0.75"
[dev-dependencies]
# axum-test-helper = "0.3.0"
axum-test = "14.2.2"

View file

@ -1,5 +1,5 @@
##### Builder ####
FROM rust:1.73-alpine as builder
FROM rust:1.75-alpine3.19 as builder
# Install dependencies
RUN apk add --no-cache sqlite npm musl-dev fd minify && npm install -g typescript
@ -36,7 +36,7 @@ WORKDIR /usr/src/huellas/ts-client/
# Install dependencies
RUN npm ci
# Transpile and delete the first line of jvascript ts-client
# Transpile and delete the first line of javascript ts-client
RUN tsc && sed -i '1d' build/client.js
# Minify static files
@ -46,7 +46,7 @@ RUN fd -e html . '/usr/src/huellas/static/' -x minify -r -o {} {} \
################
##### Runtime
FROM alpine:3.18 AS Runtime
FROM alpine:3.19 AS Runtime
RUN apk add --no-cache sqlite

View file

@ -37,8 +37,8 @@ async fn main() -> Result<()> {
let port = str::parse(&port).unwrap_or(3000);
let address = SocketAddr::from(([0, 0, 0, 0], port));
tracing::debug!("listening on {}", address);
axum::Server::bind(&address)
.serve(app.into_make_service())
let listener = tokio::net::TcpListener::bind(address).await?;
axum::serve(listener, app.into_make_service())
.with_graceful_shutdown(shutdown_signal())
.await?;

View file

@ -126,17 +126,19 @@ mod tests {
#![cfg(test)]
use super::places_routes;
use crate::place::Place;
use anyhow::{Context, Result};
use axum::http::StatusCode;
use axum::Router;
use axum_test_helper::TestClient;
use axum_test::TestServer;
use sqlx::sqlite::SqlitePool;
fn client(pool: &SqlitePool) -> TestClient {
fn server(pool: &SqlitePool) -> Result<TestServer> {
let router = Router::new().nest("/places", places_routes(pool.clone()));
TestClient::new(router)
TestServer::new(router)
}
async fn get_from_db(pool: &SqlitePool, id: i64) -> Place {
async fn get_from_db(pool: &SqlitePool, id: i64) -> Result<Place> {
sqlx::query_as!(
Place,
r#"SELECT id, name, address, open_hours, icon, description, url,
@ -147,12 +149,12 @@ mod tests {
)
.fetch_one(pool)
.await
.expect("Couldn't get from DB")
.context("Couldn't get from DB")
}
#[sqlx::test]
async fn test_add_place(pool: SqlitePool) {
let client = client(&pool);
async fn test_add_place(pool: SqlitePool) -> Result<()> {
let server = server(&pool)?;
let mut place = Place {
id: None,
name: "Sherlock Holmes".to_owned(),
@ -165,25 +167,25 @@ mod tests {
url: Some("https://www.sherlock-holmes.co.uk/".to_owned()),
};
// Insert the place
let res = client.put("/places").json(&place).send().await;
let res = server.put("/places").json(&place).await;
// We should get a success on the request
assert_eq!(res.status(), StatusCode::OK);
let res_place: Place = serde_json::from_value(res.json().await).unwrap();
assert_eq!(res.status_code(), StatusCode::OK);
let res_place: Place = res.json();
// The inserted place should have an ID
assert!(res_place.id.is_some());
// Add the returned ID to the original place
place.id = res_place.id;
// And now they should be equal
assert_eq!(place, res_place);
// TODO: actually query the DB to check the place was inserted
// confirm that the places stored in the DB are also the same
let db_place = get_from_db(&pool, place.id.unwrap()).await;
// Check against the place stored in the DB
let db_place = get_from_db(&pool, place.id.unwrap()).await?;
assert_eq!(place, db_place);
Ok(())
}
#[sqlx::test]
async fn test_get_places(pool: SqlitePool) {
let client = client(&pool);
async fn test_get_places(pool: SqlitePool) -> Result<()> {
let server = server(&pool)?;
let mut places = vec![
Place {
id: None,
@ -210,29 +212,30 @@ mod tests {
];
// insert the places
for p in &mut places {
let res = client.put("/places").json(&p).send().await;
let res = server.put("/places").json(&p).await;
// We should get a success on the request
assert_eq!(res.status(), StatusCode::OK);
let res_place: Place = serde_json::from_value(res.json().await).unwrap();
assert_eq!(res.status_code(), StatusCode::OK);
let res_place: Place = res.json();
// The inserted place should have an ID
assert!(res_place.id.is_some());
// Add the returned ID to the original place
p.id = res_place.id;
}
// and fetch them
let res = client.get("/places").send().await;
let res = server.get("/places").await;
// We should get a success on the request
assert_eq!(res.status(), StatusCode::OK);
let mut res_places: Vec<Place> = serde_json::from_value(res.json().await).unwrap();
assert_eq!(res.status_code(), StatusCode::OK);
let mut res_places: Vec<Place> = res.json();
// and they should be equal
places.sort_by(|a, b| a.id.cmp(&b.id));
res_places.sort_by(|a, b| a.id.cmp(&b.id));
assert_eq!(places, res_places);
Ok(())
}
#[sqlx::test]
async fn test_delete(pool: SqlitePool) {
let client = client(&pool);
async fn test_delete(pool: SqlitePool) -> Result<()> {
let server = server(&pool)?;
let mut places = vec![
Place {
id: None,
@ -259,35 +262,45 @@ mod tests {
];
// insert the places
for p in &mut places {
let res = client.put("/places").json(&p).send().await;
let res = server.put("/places").json(&p).await;
// We should get a success on the request
assert_eq!(res.status(), StatusCode::OK);
let res_place: Place = serde_json::from_value(res.json().await).unwrap();
assert_eq!(res.status_code(), StatusCode::OK);
let res_place: Place = res.json();
// The inserted place should have an ID
assert!(res_place.id.is_some());
// Add the returned ID to the original place
p.id = res_place.id;
}
// delete the first one
let res = client
let res = server
.delete(&format!("/places/{}", places[0].id.unwrap()))
.send()
.await;
// We should get a success on the request
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.status_code(), StatusCode::OK);
// fetch the remaining places
let res = client.get("/places").send().await;
let res = server.get("/places").await;
// We should get a success on the request
assert_eq!(res.status(), StatusCode::OK);
let res_places: Vec<Place> = serde_json::from_value(res.json().await).unwrap();
assert_eq!(res.status_code(), StatusCode::OK);
let res_places: Vec<Place> = res.json();
// we should only get the second place
assert_eq!(&places[1..], res_places.as_slice());
Ok(())
}
#[sqlx::test]
async fn test_update(pool: SqlitePool) {
let client = client(&pool);
async fn test_delete_not_existing(pool: SqlitePool) -> Result<()> {
let server = server(&pool)?;
// Try to delete a non-existing place
let res = server.delete("/places/33").await;
// We should get the corresponding status code
assert_eq!(res.status_code(), StatusCode::NOT_FOUND);
Ok(())
}
#[sqlx::test]
async fn test_update(pool: SqlitePool) -> Result<()> {
let server = server(&pool)?;
let mut places = vec![
Place {
id: None,
@ -313,25 +326,26 @@ mod tests {
},
];
// insert original place
let res = client.put("/places").json(&places[0]).send().await;
let res = server.put("/places").json(&places[0]).await;
// We should get a success on the request
assert_eq!(res.status(), StatusCode::OK);
let res_place: Place = serde_json::from_value(res.json().await).unwrap();
assert_eq!(res.status_code(), StatusCode::OK);
let res_place: Place = res.json();
// The inserted place should have an ID
assert!(res_place.id.is_some());
// Add the returned ID to the new place so we can do the update
places[1].id = res_place.id;
// update the place
let res = client.put("/places").json(&places[1]).send().await;
let res = server.put("/places").json(&places[1]).await;
// We should get a success on the request
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.status_code(), StatusCode::OK);
// fetch the places
let res = client.get("/places").send().await;
let res = server.get("/places").await;
// We should get a success on the request
assert_eq!(res.status(), StatusCode::OK);
let res_places: Vec<Place> = serde_json::from_value(res.json().await).unwrap();
assert_eq!(res.status_code(), StatusCode::OK);
let res_places: Vec<Place> = res.json();
// we should get the updated place
assert_eq!(&places[1..], res_places.as_slice());
Ok(())
}
}