Skip to content

Commit 64c1aa7

Browse files
authored
axum-extra: Use json!() macro (#9960)
This seems a bit easier to use than the `Json(json!(...))` construct and is apparently even a bit faster since it does not need to allocate as much memory.
1 parent fa7b413 commit 64c1aa7

36 files changed

+152
-122
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ aws-ip-ranges = "=0.913.0"
4444
aws-sdk-cloudfront = "=1.52.0"
4545
aws-sdk-sqs = "=1.49.0"
4646
axum = { version = "=0.7.8", features = ["macros", "matched-path"] }
47-
axum-extra = { version = "=0.9.5", features = ["cookie-signed", "typed-header"] }
47+
axum-extra = { version = "=0.9.5", features = ["cookie-signed", "erased-json", "typed-header"] }
4848
base64 = "=0.22.1"
4949
bigdecimal = { version = "=0.4.6", features = ["serde"] }
5050
bon = "=3.0.0"

src/controllers/category.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ use crate::util::errors::AppResult;
66
use crate::util::RequestUtils;
77
use crate::views::{EncodableCategory, EncodableCategoryWithSubcategories};
88
use axum::extract::Path;
9-
use axum::Json;
9+
use axum_extra::json;
10+
use axum_extra::response::ErasedJson;
1011
use diesel::QueryDsl;
1112
use diesel_async::RunQueryDsl;
1213
use http::request::Parts;
13-
use serde_json::Value;
1414

1515
/// Handles the `GET /categories` route.
16-
pub async fn index(app: AppState, req: Parts) -> AppResult<Json<Value>> {
16+
pub async fn index(app: AppState, req: Parts) -> AppResult<ErasedJson> {
1717
// FIXME: There are 69 categories, 47 top level. This isn't going to
1818
// grow by an OoM. We need a limit for /summary, but we don't need
1919
// to paginate this.
@@ -35,14 +35,14 @@ pub async fn index(app: AppState, req: Parts) -> AppResult<Json<Value>> {
3535
// Query for the total count of categories
3636
let total = Category::count_toplevel(&mut conn).await?;
3737

38-
Ok(Json(json!({
38+
Ok(json!({
3939
"categories": categories,
4040
"meta": { "total": total },
41-
})))
41+
}))
4242
}
4343

4444
/// Handles the `GET /categories/:category_id` route.
45-
pub async fn show(state: AppState, Path(slug): Path<String>) -> AppResult<Json<Value>> {
45+
pub async fn show(state: AppState, Path(slug): Path<String>) -> AppResult<ErasedJson> {
4646
let mut conn = state.db_read().await?;
4747

4848
let cat: Category = Category::by_slug(&slug).first(&mut conn).await?;
@@ -71,11 +71,11 @@ pub async fn show(state: AppState, Path(slug): Path<String>) -> AppResult<Json<V
7171
parent_categories: parents,
7272
};
7373

74-
Ok(Json(json!({ "category": cat_with_subcats })))
74+
Ok(json!({ "category": cat_with_subcats }))
7575
}
7676

7777
/// Handles the `GET /category_slugs` route.
78-
pub async fn slugs(state: AppState) -> AppResult<Json<Value>> {
78+
pub async fn slugs(state: AppState) -> AppResult<ErasedJson> {
7979
let mut conn = state.db_read().await?;
8080

8181
let slugs: Vec<Slug> = categories::table
@@ -91,5 +91,5 @@ pub async fn slugs(state: AppState) -> AppResult<Json<Value>> {
9191
description: String,
9292
}
9393

94-
Ok(Json(json!({ "category_slugs": slugs })))
94+
Ok(json!({ "category_slugs": slugs }))
9595
}

src/controllers/crate_owner_invitation.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,19 @@ use crate::views::{
1515
};
1616
use axum::extract::Path;
1717
use axum::Json;
18+
use axum_extra::json;
19+
use axum_extra::response::ErasedJson;
1820
use chrono::{Duration, Utc};
1921
use diesel::pg::Pg;
2022
use diesel::sql_types::Bool;
2123
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
2224
use http::request::Parts;
2325
use indexmap::IndexMap;
24-
use serde_json::Value;
2526
use std::collections::{HashMap, HashSet};
2627
use tokio::runtime::Handle;
2728

2829
/// Handles the `GET /api/v1/me/crate_owner_invitations` route.
29-
pub async fn list(app: AppState, req: Parts) -> AppResult<Json<Value>> {
30+
pub async fn list(app: AppState, req: Parts) -> AppResult<ErasedJson> {
3031
let mut conn = app.db_read().await?;
3132
let auth = AuthCheck::only_cookie().check(&req, &mut conn).await?;
3233
spawn_blocking(move || {
@@ -59,10 +60,10 @@ pub async fn list(app: AppState, req: Parts) -> AppResult<Json<Value>> {
5960
})
6061
.collect::<AppResult<Vec<EncodableCrateOwnerInvitationV1>>>()?;
6162

62-
Ok(Json(json!({
63+
Ok(json!({
6364
"crate_owner_invitations": crate_owner_invitations,
6465
"users": users,
65-
})))
66+
}))
6667
})
6768
.await
6869
}
@@ -275,7 +276,7 @@ struct OwnerInvitation {
275276
}
276277

277278
/// Handles the `PUT /api/v1/me/crate_owner_invitations/:crate_id` route.
278-
pub async fn handle_invite(state: AppState, req: BytesRequest) -> AppResult<Json<Value>> {
279+
pub async fn handle_invite(state: AppState, req: BytesRequest) -> AppResult<ErasedJson> {
279280
let (parts, body) = req.0.into_parts();
280281

281282
let crate_invite: OwnerInvitation =
@@ -299,14 +300,14 @@ pub async fn handle_invite(state: AppState, req: BytesRequest) -> AppResult<Json
299300
invitation.decline(&mut conn).await?;
300301
}
301302

302-
Ok(Json(json!({ "crate_owner_invitation": crate_invite })))
303+
Ok(json!({ "crate_owner_invitation": crate_invite }))
303304
}
304305

305306
/// Handles the `PUT /api/v1/me/crate_owner_invitations/accept/:token` route.
306307
pub async fn handle_invite_with_token(
307308
state: AppState,
308309
Path(token): Path<String>,
309-
) -> AppResult<Json<Value>> {
310+
) -> AppResult<ErasedJson> {
310311
let mut conn = state.db_write().await?;
311312
let invitation = CrateOwnerInvitation::find_by_token(&token, &mut conn).await?;
312313

@@ -315,10 +316,10 @@ pub async fn handle_invite_with_token(
315316
let crate_id = invitation.crate_id;
316317
invitation.accept(&mut conn, config).await?;
317318

318-
Ok(Json(json!({
319+
Ok(json!({
319320
"crate_owner_invitation": {
320321
"crate_id": crate_id,
321322
"accepted": true,
322323
},
323-
})))
324+
}))
324325
}

src/controllers/helpers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use crate::util::errors::AppResult;
22
use axum::response::{IntoResponse, Response};
3-
use axum::Json;
3+
use axum_extra::json;
44

55
pub(crate) mod pagination;
66

77
pub(crate) use self::pagination::Paginate;
88

99
pub fn ok_true() -> AppResult<Response> {
1010
let json = json!({ "ok": true });
11-
Ok(Json(json).into_response())
11+
Ok(json.into_response())
1212
}

src/controllers/keyword.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ use crate::tasks::spawn_blocking;
66
use crate::util::errors::AppResult;
77
use crate::views::EncodableKeyword;
88
use axum::extract::{Path, Query};
9-
use axum::Json;
9+
use axum_extra::json;
10+
use axum_extra::response::ErasedJson;
1011
use diesel::prelude::*;
1112
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
1213
use http::request::Parts;
13-
use serde_json::Value;
1414

1515
#[derive(Deserialize)]
1616
pub struct IndexQuery {
1717
sort: Option<String>,
1818
}
1919

2020
/// Handles the `GET /keywords` route.
21-
pub async fn index(state: AppState, qp: Query<IndexQuery>, req: Parts) -> AppResult<Json<Value>> {
21+
pub async fn index(state: AppState, qp: Query<IndexQuery>, req: Parts) -> AppResult<ErasedJson> {
2222
use crate::schema::keywords;
2323

2424
let mut query = keywords::table.into_boxed();
@@ -41,18 +41,18 @@ pub async fn index(state: AppState, qp: Query<IndexQuery>, req: Parts) -> AppRes
4141
.map(Keyword::into)
4242
.collect::<Vec<EncodableKeyword>>();
4343

44-
Ok(Json(json!({
44+
Ok(json!({
4545
"keywords": kws,
4646
"meta": { "total": total },
47-
})))
47+
}))
4848
})
4949
.await
5050
}
5151

5252
/// Handles the `GET /keywords/:keyword_id` route.
53-
pub async fn show(Path(name): Path<String>, state: AppState) -> AppResult<Json<Value>> {
53+
pub async fn show(Path(name): Path<String>, state: AppState) -> AppResult<ErasedJson> {
5454
let mut conn = state.db_read().await?;
5555
let kw = Keyword::find_by_keyword(&mut conn, &name).await?;
5656

57-
Ok(Json(json!({ "keyword": EncodableKeyword::from(kw) })))
57+
Ok(json!({ "keyword": EncodableKeyword::from(kw) }))
5858
}

src/controllers/krate/downloads.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ use crate::sql::to_char;
1010
use crate::util::errors::{crate_not_found, AppResult};
1111
use crate::views::EncodableVersionDownload;
1212
use axum::extract::Path;
13-
use axum::Json;
13+
use axum_extra::json;
14+
use axum_extra::response::ErasedJson;
1415
use diesel::prelude::*;
1516
use diesel_async::RunQueryDsl;
16-
use serde_json::Value;
1717
use std::cmp;
1818

1919
/// Handles the `GET /crates/:crate_id/downloads` route.
20-
pub async fn downloads(state: AppState, Path(crate_name): Path<String>) -> AppResult<Json<Value>> {
20+
pub async fn downloads(state: AppState, Path(crate_name): Path<String>) -> AppResult<ErasedJson> {
2121
let mut conn = state.db_read().await?;
2222

2323
use diesel::dsl::*;
@@ -68,10 +68,10 @@ pub async fn downloads(state: AppState, Path(crate_name): Path<String>) -> AppRe
6868
downloads: i64,
6969
}
7070

71-
Ok(Json(json!({
71+
Ok(json!({
7272
"version_downloads": downloads,
7373
"meta": {
7474
"extra_downloads": extra,
7575
},
76-
})))
76+
}))
7777
}

src/controllers/krate/follow.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ use crate::schema::*;
88
use crate::util::errors::{crate_not_found, AppResult};
99
use axum::extract::Path;
1010
use axum::response::Response;
11-
use axum::Json;
11+
use axum_extra::json;
12+
use axum_extra::response::ErasedJson;
1213
use diesel::prelude::*;
1314
use diesel_async::{AsyncPgConnection, RunQueryDsl};
1415
use http::request::Parts;
15-
use serde_json::Value;
1616

1717
async fn follow_target(
1818
crate_name: &str,
@@ -66,7 +66,7 @@ pub async fn following(
6666
app: AppState,
6767
Path(crate_name): Path<String>,
6868
req: Parts,
69-
) -> AppResult<Json<Value>> {
69+
) -> AppResult<ErasedJson> {
7070
use diesel::dsl::exists;
7171

7272
let mut conn = app.db_read_prefer_primary().await?;
@@ -80,5 +80,5 @@ pub async fn following(
8080
.get_result::<bool>(&mut conn)
8181
.await?;
8282

83-
Ok(Json(json!({ "following": following })))
83+
Ok(json!({ "following": following }))
8484
}

src/controllers/krate/metadata.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,20 @@ use crate::views::{
2020
};
2121
use axum::extract::Path;
2222
use axum::response::{IntoResponse, Response};
23-
use axum::Json;
23+
use axum_extra::json;
24+
use axum_extra::response::ErasedJson;
2425
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
2526
use http::request::Parts;
26-
use serde_json::Value;
2727
use std::cmp::Reverse;
2828
use std::str::FromStr;
2929

3030
/// Handles the `GET /crates/new` special case.
31-
pub async fn show_new(app: AppState, req: Parts) -> AppResult<Json<Value>> {
31+
pub async fn show_new(app: AppState, req: Parts) -> AppResult<ErasedJson> {
3232
show(app, Path("new".to_string()), req).await
3333
}
3434

3535
/// Handles the `GET /crates/:crate_id` route.
36-
pub async fn show(app: AppState, Path(name): Path<String>, req: Parts) -> AppResult<Json<Value>> {
36+
pub async fn show(app: AppState, Path(name): Path<String>, req: Parts) -> AppResult<ErasedJson> {
3737
let conn = app.db_read().await?;
3838
spawn_blocking(move || {
3939
use diesel::RunQueryDsl;
@@ -157,12 +157,12 @@ pub async fn show(app: AppState, Path(name): Path<String>, req: Parts) -> AppRes
157157
.map(Category::into)
158158
.collect::<Vec<EncodableCategory>>()
159159
});
160-
Ok(Json(json!({
160+
Ok(json!({
161161
"crate": encodable_crate,
162162
"versions": encodable_versions,
163163
"keywords": encodable_keywords,
164164
"categories": encodable_cats,
165-
})))
165+
}))
166166
})
167167
.await
168168
}
@@ -237,7 +237,7 @@ pub async fn readme(
237237
) -> Response {
238238
let redirect_url = app.storage.readme_location(&crate_name, &version);
239239
if req.wants_json() {
240-
Json(json!({ "url": redirect_url })).into_response()
240+
json!({ "url": redirect_url }).into_response()
241241
} else {
242242
redirect(redirect_url)
243243
}
@@ -248,7 +248,7 @@ pub async fn reverse_dependencies(
248248
app: AppState,
249249
Path(name): Path<String>,
250250
req: Parts,
251-
) -> AppResult<Json<Value>> {
251+
) -> AppResult<ErasedJson> {
252252
use diesel_async::RunQueryDsl;
253253

254254
let mut conn = app.db_read().await?;
@@ -295,9 +295,9 @@ pub async fn reverse_dependencies(
295295
})
296296
.collect::<Vec<_>>();
297297

298-
Ok(Json(json!({
298+
Ok(json!({
299299
"dependencies": rev_deps,
300300
"versions": versions,
301301
"meta": { "total": total },
302-
})))
302+
}))
303303
}

0 commit comments

Comments
 (0)