Skip to content

Commit

Permalink
Improve the support for OpenAPI docs
Browse files Browse the repository at this point in the history
  • Loading branch information
photino committed Sep 4, 2023
1 parent 3151817 commit d7e5561
Show file tree
Hide file tree
Showing 24 changed files with 446 additions and 30 deletions.
15 changes: 15 additions & 0 deletions examples/actix-app/assets/docs/rapidoc.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
</head>
<body>
<rapi-doc spec-url="$specUrl" heading-text="RapiDoc"
schema-style="table" default-schema-tab="schema"
show-method-in-nav-bar="as-colored-block" sort-endpoints-by="method"
persist-auth="true" allow-spec-file-download="true"
primary-color="#2d87e2">
</rapi-doc>
</body>
</html>
3 changes: 3 additions & 0 deletions examples/actix-app/config/config.dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,6 @@ span = { "http.method" = "string", "http.target" = "string", "http.status_code"

[connector.variables]
app-name = "data-cube"

[openapi]
custom-html = "assets/docs/rapidoc.html"
3 changes: 3 additions & 0 deletions examples/actix-app/config/config.prod.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,6 @@ span = { "http.method" = "string", "http.target" = "string", "http.status_code"

[connector.variables]
app-name = "data-cube"

[openapi]
show-docs = false
17 changes: 17 additions & 0 deletions examples/actix-app/config/openapi/OPENAPI.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[info]
title = "DataCube API"
description = """
An example for [actix-web] integration.
[actix-web]: https://crates.io/crates/actix-web
"""
contact = { url = "https://github.com/photino/zino" }
license = "MIT"

[security_schemes.jwt_auth]
type = "http"
scheme = "bearer"
bearer_format = "JWT"

[[securities]]
name = "jwt_auth"
9 changes: 6 additions & 3 deletions examples/actix-app/config/openapi/auth.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
name = "Authentication"

[[endpoints]]
path = "/auth/login"
method = "POST"
description = "Account login"
summary = "Account login"
securities = []

[endpoints.body]
type = "object"
Expand All @@ -11,9 +14,9 @@ password = { type = "string", format = "password", description = "User password"
[[endpoints]]
path = "/auth/refresh"
method = "GET"
description = "Refresh access token"
summary = "Refreshes access token"

[[endpoints]]
path = "/auth/logout"
method = "POST"
description = "Account logout"
summary = "Account logout"
9 changes: 8 additions & 1 deletion examples/actix-app/config/openapi/tag.toml
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
name = "Tags"

[[endpoints]]
path = "/tag/new"
method = "POST"
summary = "Creates a new tag"

[endpoints.body]
schema = "newTag"

[[endpoints]]
path = "/tag/{tag_id}/delete"
method = "POST"
summary = "Deletes a tag by ID"

[[endpoints]]
path = "/tag/{tag_id}/update"
method = "POST"
summary = "Updates a tag by ID"

[endpoints.body]
schema = "tagInfo"

[[endpoints]]
path = "/tag/{tag_id}/view"
method = "GET"
summary = "Gets a tag by ID"

[[endpoints]]
path = "/tag/list"
method = "GET"
summary = "Finds a list of tags"

[endpoints.query]
category = { type = "string", description = "Tag category" }
Expand Down Expand Up @@ -58,4 +65,4 @@ translations = [
translations = [
["Active", "😄"],
["Inactive", "😴"],
]
]
10 changes: 10 additions & 0 deletions examples/actix-app/config/openapi/user.toml
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
name = "Users"

[[endpoints]]
path = "/user/new"
method = "POST"
summary = "Creates a new user"

[endpoints.body]
schema = "newUser"

[[endpoints]]
path = "/user/{user_id}/delete"
method = "POST"
summary = "Deletes a user by ID"

[[endpoints]]
path = "/user/{user_id}/update"
method = "POST"
summary = "Updates a user by ID"

[endpoints.body]
schema = "userInfo"

[[endpoints]]
path = "/user/{user_id}/view"
method = "GET"
summary = "Gets a user by ID"

[[endpoints]]
path = "/user/list"
method = "GET"
summary = "Finds a list of users"

[endpoints.query]
roles = { type = "string", description = "User roles" }
Expand All @@ -31,13 +38,15 @@ tags = { type = "string", description = "User tags" }
[[endpoints]]
path = "/user/import"
method = "POST"
summary = "Imports the user data"

[endpoints.body]
schema = "userData"

[[endpoints]]
path = "/user/export"
method = "GET"
summary = "Exports the user data"

[endpoints.query]
format = { type = "string", enum = ["csv", "json", "jsonlines", "msgpack"], default = "json", description = "File format" }
Expand Down Expand Up @@ -100,3 +109,4 @@ translations = [
["$span:24h", "Updated within 1 day"],
["$span:7d", "Updated within 1 week"],
]

7 changes: 7 additions & 0 deletions examples/actix-app/src/middleware/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ where
user_session.set_session_id(session_id);
}
req.set_data(user_session);
} else {
return Box::pin(async move {
let message = "401 Unauthorized: login is required";
let rejection = Rejection::with_message(message).context(&req).into();
let result: zino::Result<Self::Response> = Err(rejection);
return result.map_err(|err| err.into());
});
}

let req = ServiceRequest::from(req);
Expand Down
15 changes: 15 additions & 0 deletions examples/axum-app/assets/docs/rapidoc.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
</head>
<body>
<rapi-doc spec-url="$specUrl" heading-text="RapiDoc"
schema-style="table" default-schema-tab="schema"
show-method-in-nav-bar="as-colored-block" sort-endpoints-by="method"
persist-auth="true" allow-spec-file-download="true"
primary-color="#2d87e2">
</rapi-doc>
</body>
</html>
3 changes: 3 additions & 0 deletions examples/axum-app/config/config.dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,6 @@ span = { "http.method" = "string", "http.target" = "string", "http.status_code"

[connector.variables]
app-name = "data-cube"

[openapi]
custom-html = "assets/docs/rapidoc.html"
3 changes: 3 additions & 0 deletions examples/axum-app/config/config.prod.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,6 @@ span = { "http.method" = "string", "http.target" = "string", "http.status_code"

[connector.variables]
app-name = "data-cube"

[openapi]
show-docs = false
17 changes: 17 additions & 0 deletions examples/axum-app/config/openapi/OPENAPI.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[info]
title = "DataCube API"
description = """
An example for [axum] integration.
[axum]: https://crates.io/crates/axum
"""
contact = { url = "https://github.com/photino/zino" }
license = "MIT"

[security_schemes.jwt_auth]
type = "http"
scheme = "bearer"
bearer_format = "JWT"

[[securities]]
name = "jwt_auth"
9 changes: 6 additions & 3 deletions examples/axum-app/config/openapi/auth.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
name = "Authentication"

[[endpoints]]
path = "/auth/login"
method = "POST"
description = "Account login"
summary = "Account login"
securities = []

[endpoints.body]
type = "object"
Expand All @@ -11,9 +14,9 @@ password = { type = "string", format = "password", description = "User password"
[[endpoints]]
path = "/auth/refresh"
method = "GET"
description = "Refresh access token"
summary = "Refreshes access token"

[[endpoints]]
path = "/auth/logout"
method = "POST"
description = "Account logout"
summary = "Account logout"
7 changes: 7 additions & 0 deletions examples/axum-app/config/openapi/tag.toml
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
name = "Tags"

[[endpoints]]
path = "/tag/new"
method = "POST"
summary = "Creates a new tag"

[endpoints.body]
schema = "newTag"

[[endpoints]]
path = "/tag/{tag_id}/delete"
method = "POST"
summary = "Deletes a tag by ID"

[[endpoints]]
path = "/tag/{tag_id}/update"
method = "POST"
summary = "Updates a tag by ID"

[endpoints.body]
schema = "tagInfo"

[[endpoints]]
path = "/tag/{tag_id}/view"
method = "GET"
summary = "Gets a tag by ID"

[[endpoints]]
path = "/tag/list"
method = "GET"
summary = "Finds a list of tags"

[endpoints.query]
category = { type = "string", description = "Tag category" }
Expand Down
9 changes: 9 additions & 0 deletions examples/axum-app/config/openapi/user.toml
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
name = "Users"

[[endpoints]]
path = "/user/new"
method = "POST"
summary = "Creates a new user"

[endpoints.body]
schema = "newUser"

[[endpoints]]
path = "/user/{user_id}/delete"
method = "POST"
summary = "Deletes a user by ID"

[[endpoints]]
path = "/user/{user_id}/update"
method = "POST"
summary = "Updates a user by ID"

[endpoints.body]
schema = "userInfo"

[[endpoints]]
path = "/user/{user_id}/view"
method = "GET"
summary = "Gets a user by ID"

[[endpoints]]
path = "/user/list"
method = "GET"
summary = "Finds a list of users"

[endpoints.query]
roles = { type = "string", description = "User roles" }
Expand All @@ -31,13 +38,15 @@ tags = { type = "string", description = "User tags" }
[[endpoints]]
path = "/user/import"
method = "POST"
summary = "Imports the user data"

[endpoints.body]
schema = "userData"

[[endpoints]]
path = "/user/export"
method = "GET"
summary = "Exports the user data"

[endpoints.query]
format = { type = "string", enum = ["csv", "json", "jsonlines", "msgpack"], default = "json", description = "File format" }
Expand Down
2 changes: 1 addition & 1 deletion examples/axum-app/src/middleware/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub async fn init_user_session(mut req: Request, next: Next<Body>) -> Result<Res
}
Err(err) => reject!(req, unauthorized, err),
}
} else if req.request_method() == "POST" {
} else {
reject!(req, unauthorized, "login is required");
}
Ok(next.run(req.into()).await)
Expand Down
9 changes: 6 additions & 3 deletions zino-core/src/application/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::{
thread,
};
use toml::value::Table;
use utoipa::openapi::{Info, OpenApi, OpenApiBuilder};
use utoipa::openapi::{OpenApi, OpenApiBuilder};

mod metrics_exporter;
mod secret_key;
Expand Down Expand Up @@ -101,10 +101,13 @@ pub trait Application {
#[inline]
fn openapi() -> OpenApi {
OpenApiBuilder::new()
.info(Info::new(Self::name(), Self::version()))
.paths(openapi::default_paths())
.paths(openapi::default_paths()) // should come first to load OpenAPI files
.components(Some(openapi::default_components()))
.tags(Some(openapi::default_tags()))
.servers(Some(openapi::default_servers()))
.security(Some(openapi::default_securities()))
.external_docs(openapi::default_external_docs())
.info(openapi::openapi_info(Self::name(), Self::version()))
.build()
}

Expand Down
Loading

0 comments on commit d7e5561

Please sign in to comment.