feat!: use msgpack instead of json #40
3 changed files with 406 additions and 413 deletions
763
Cargo.lock
generated
763
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
13
Cargo.toml
13
Cargo.toml
|
|
@ -5,18 +5,17 @@ edition = "2021"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.79"
|
anyhow = "1.0.80"
|
||||||
axum = { version = "0.7.4", default-features = false, features = [
|
axum = { version = "0.7.4", default-features = false, features = [
|
||||||
"json",
|
|
||||||
"tracing",
|
"tracing",
|
||||||
"tokio",
|
"tokio",
|
||||||
"http1",
|
"http1",
|
||||||
"http2",
|
"http2",
|
||||||
] }
|
] }
|
||||||
|
axum-msgpack = "0.4.0"
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
futures = { version = "0.3.30", default-features = false }
|
futures = { version = "0.3.30", default-features = false }
|
||||||
serde = { version = "1.0.195", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
serde_json = "1.0.111"
|
|
||||||
sqlx = { version = "0.7.3", default-features = false, features = [
|
sqlx = { version = "0.7.3", default-features = false, features = [
|
||||||
"macros",
|
"macros",
|
||||||
"migrate",
|
"migrate",
|
||||||
|
|
@ -24,12 +23,12 @@ sqlx = { version = "0.7.3", default-features = false, features = [
|
||||||
"sqlite",
|
"sqlite",
|
||||||
"tls-rustls",
|
"tls-rustls",
|
||||||
] }
|
] }
|
||||||
tokio = { version = "1.35.1", default-features = false, features = [
|
tokio = { version = "1.36.0", default-features = false, features = [
|
||||||
"macros",
|
"macros",
|
||||||
"rt-multi-thread",
|
"rt-multi-thread",
|
||||||
"signal",
|
"signal",
|
||||||
] }
|
] }
|
||||||
tower-http = { version = "0.5.1", default-features = false, features = ["fs"] }
|
tower-http = { version = "0.5.2", default-features = false, features = ["fs"] }
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = { version = "0.3.18", default-features = false, features = [
|
tracing-subscriber = { version = "0.3.18", default-features = false, features = [
|
||||||
"env-filter",
|
"env-filter",
|
||||||
|
|
@ -39,4 +38,4 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features =
|
||||||
] }
|
] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
axum-test = "14.2.2"
|
axum-test = { version = "14.4.0", features = ["msgpack"] }
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use axum::extract::{Json, Path, State};
|
use axum::extract::{Path, State};
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::routing::{delete, get};
|
use axum::routing::{delete, get};
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
|
use axum_msgpack::MsgPack;
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use sqlx::sqlite::SqlitePool;
|
use sqlx::sqlite::SqlitePool;
|
||||||
|
|
||||||
|
|
@ -15,7 +16,7 @@ where
|
||||||
(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
|
(StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_places(State(pool): State<SqlitePool>) -> Result<Json<Vec<Place>>> {
|
async fn get_places(State(pool): State<SqlitePool>) -> Result<MsgPack<Vec<Place>>> {
|
||||||
let places = sqlx::query!(
|
let places = sqlx::query!(
|
||||||
r#"SELECT id, name, address, open_hours, icon, description, url,
|
r#"SELECT id, name, address, open_hours, icon, description, url,
|
||||||
longitude as "longitude: f64", latitude as "latitude: f64"
|
longitude as "longitude: f64", latitude as "latitude: f64"
|
||||||
|
|
@ -38,13 +39,13 @@ async fn get_places(State(pool): State<SqlitePool>) -> Result<Json<Vec<Place>>>
|
||||||
.await
|
.await
|
||||||
.map_err(internal_error)?;
|
.map_err(internal_error)?;
|
||||||
|
|
||||||
Ok(Json(places))
|
Ok(MsgPack(places))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn upsert_place(
|
async fn upsert_place(
|
||||||
State(pool): State<SqlitePool>,
|
State(pool): State<SqlitePool>,
|
||||||
Json(place): Json<Place>,
|
MsgPack(place): MsgPack<Place>,
|
||||||
) -> Result<Json<Place>> {
|
) -> Result<MsgPack<Place>> {
|
||||||
if place.id.is_some() {
|
if place.id.is_some() {
|
||||||
update_place(pool, place).await
|
update_place(pool, place).await
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -52,7 +53,7 @@ async fn upsert_place(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn insert_place(pool: SqlitePool, mut place: Place) -> Result<Json<Place>> {
|
async fn insert_place(pool: SqlitePool, mut place: Place) -> Result<MsgPack<Place>> {
|
||||||
let id = sqlx::query_scalar!(
|
let id = sqlx::query_scalar!(
|
||||||
r#"INSERT INTO places
|
r#"INSERT INTO places
|
||||||
(name, address, open_hours, icon, description, longitude, latitude, url)
|
(name, address, open_hours, icon, description, longitude, latitude, url)
|
||||||
|
|
@ -72,10 +73,10 @@ async fn insert_place(pool: SqlitePool, mut place: Place) -> Result<Json<Place>>
|
||||||
.map_err(internal_error)?;
|
.map_err(internal_error)?;
|
||||||
|
|
||||||
place.id = Some(id);
|
place.id = Some(id);
|
||||||
Ok(Json(place))
|
Ok(MsgPack(place))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_place(pool: SqlitePool, place: Place) -> Result<Json<Place>> {
|
async fn update_place(pool: SqlitePool, place: Place) -> Result<MsgPack<Place>> {
|
||||||
let result = sqlx::query!(
|
let result = sqlx::query!(
|
||||||
r#"UPDATE places
|
r#"UPDATE places
|
||||||
SET (name, address, open_hours, icon, description, longitude, latitude, url)
|
SET (name, address, open_hours, icon, description, longitude, latitude, url)
|
||||||
|
|
@ -96,7 +97,7 @@ async fn update_place(pool: SqlitePool, place: Place) -> Result<Json<Place>> {
|
||||||
.map_err(internal_error)?;
|
.map_err(internal_error)?;
|
||||||
|
|
||||||
if result.rows_affected() == 1 {
|
if result.rows_affected() == 1 {
|
||||||
Ok(Json(place))
|
Ok(MsgPack(place))
|
||||||
} else {
|
} else {
|
||||||
Err((StatusCode::NOT_FOUND, "".to_owned()))
|
Err((StatusCode::NOT_FOUND, "".to_owned()))
|
||||||
}
|
}
|
||||||
|
|
@ -167,10 +168,10 @@ mod tests {
|
||||||
url: Some("https://www.sherlock-holmes.co.uk/".to_owned()),
|
url: Some("https://www.sherlock-holmes.co.uk/".to_owned()),
|
||||||
};
|
};
|
||||||
// Insert the place
|
// Insert the place
|
||||||
let res = server.put("/places").json(&place).await;
|
let res = server.put("/places").msgpack(&place).await;
|
||||||
// We should get a success on the request
|
// We should get a success on the request
|
||||||
assert_eq!(res.status_code(), StatusCode::OK);
|
assert_eq!(res.status_code(), StatusCode::OK);
|
||||||
let res_place: Place = res.json();
|
let res_place: Place = res.msgpack();
|
||||||
// The inserted place should have an ID
|
// The inserted place should have an ID
|
||||||
assert!(res_place.id.is_some());
|
assert!(res_place.id.is_some());
|
||||||
// Add the returned ID to the original place
|
// Add the returned ID to the original place
|
||||||
|
|
@ -212,10 +213,10 @@ mod tests {
|
||||||
];
|
];
|
||||||
// insert the places
|
// insert the places
|
||||||
for p in &mut places {
|
for p in &mut places {
|
||||||
let res = server.put("/places").json(&p).await;
|
let res = server.put("/places").msgpack(&p).await;
|
||||||
// We should get a success on the request
|
// We should get a success on the request
|
||||||
assert_eq!(res.status_code(), StatusCode::OK);
|
assert_eq!(res.status_code(), StatusCode::OK);
|
||||||
let res_place: Place = res.json();
|
let res_place: Place = res.msgpack();
|
||||||
// The inserted place should have an ID
|
// The inserted place should have an ID
|
||||||
assert!(res_place.id.is_some());
|
assert!(res_place.id.is_some());
|
||||||
// Add the returned ID to the original place
|
// Add the returned ID to the original place
|
||||||
|
|
@ -225,7 +226,7 @@ mod tests {
|
||||||
let res = server.get("/places").await;
|
let res = server.get("/places").await;
|
||||||
// We should get a success on the request
|
// We should get a success on the request
|
||||||
assert_eq!(res.status_code(), StatusCode::OK);
|
assert_eq!(res.status_code(), StatusCode::OK);
|
||||||
let mut res_places: Vec<Place> = res.json();
|
let mut res_places: Vec<Place> = res.msgpack();
|
||||||
// and they should be equal
|
// and they should be equal
|
||||||
places.sort_by(|a, b| a.id.cmp(&b.id));
|
places.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
res_places.sort_by(|a, b| a.id.cmp(&b.id));
|
res_places.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
|
|
@ -262,10 +263,10 @@ mod tests {
|
||||||
];
|
];
|
||||||
// insert the places
|
// insert the places
|
||||||
for p in &mut places {
|
for p in &mut places {
|
||||||
let res = server.put("/places").json(&p).await;
|
let res = server.put("/places").msgpack(&p).await;
|
||||||
// We should get a success on the request
|
// We should get a success on the request
|
||||||
assert_eq!(res.status_code(), StatusCode::OK);
|
assert_eq!(res.status_code(), StatusCode::OK);
|
||||||
let res_place: Place = res.json();
|
let res_place: Place = res.msgpack();
|
||||||
// The inserted place should have an ID
|
// The inserted place should have an ID
|
||||||
assert!(res_place.id.is_some());
|
assert!(res_place.id.is_some());
|
||||||
// Add the returned ID to the original place
|
// Add the returned ID to the original place
|
||||||
|
|
@ -282,7 +283,7 @@ mod tests {
|
||||||
let res = server.get("/places").await;
|
let res = server.get("/places").await;
|
||||||
// We should get a success on the request
|
// We should get a success on the request
|
||||||
assert_eq!(res.status_code(), StatusCode::OK);
|
assert_eq!(res.status_code(), StatusCode::OK);
|
||||||
let res_places: Vec<Place> = res.json();
|
let res_places: Vec<Place> = res.msgpack();
|
||||||
// we should only get the second place
|
// we should only get the second place
|
||||||
assert_eq!(&places[1..], res_places.as_slice());
|
assert_eq!(&places[1..], res_places.as_slice());
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -326,16 +327,16 @@ mod tests {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
// insert original place
|
// insert original place
|
||||||
let res = server.put("/places").json(&places[0]).await;
|
let res = server.put("/places").msgpack(&places[0]).await;
|
||||||
// We should get a success on the request
|
// We should get a success on the request
|
||||||
assert_eq!(res.status_code(), StatusCode::OK);
|
assert_eq!(res.status_code(), StatusCode::OK);
|
||||||
let res_place: Place = res.json();
|
let res_place: Place = res.msgpack();
|
||||||
// The inserted place should have an ID
|
// The inserted place should have an ID
|
||||||
assert!(res_place.id.is_some());
|
assert!(res_place.id.is_some());
|
||||||
// Add the returned ID to the new place so we can do the update
|
// Add the returned ID to the new place so we can do the update
|
||||||
places[1].id = res_place.id;
|
places[1].id = res_place.id;
|
||||||
// update the place
|
// update the place
|
||||||
let res = server.put("/places").json(&places[1]).await;
|
let res = server.put("/places").msgpack(&places[1]).await;
|
||||||
// We should get a success on the request
|
// We should get a success on the request
|
||||||
assert_eq!(res.status_code(), StatusCode::OK);
|
assert_eq!(res.status_code(), StatusCode::OK);
|
||||||
|
|
||||||
|
|
@ -343,7 +344,7 @@ mod tests {
|
||||||
let res = server.get("/places").await;
|
let res = server.get("/places").await;
|
||||||
// We should get a success on the request
|
// We should get a success on the request
|
||||||
assert_eq!(res.status_code(), StatusCode::OK);
|
assert_eq!(res.status_code(), StatusCode::OK);
|
||||||
let res_places: Vec<Place> = res.json();
|
let res_places: Vec<Place> = res.msgpack();
|
||||||
// we should get the updated place
|
// we should get the updated place
|
||||||
assert_eq!(&places[1..], res_places.as_slice());
|
assert_eq!(&places[1..], res_places.as_slice());
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue