Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for scalar as alternative for swagger ui #458

Merged
merged 2 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion crates/oapi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ authors = ["Juha Kukkonen <[email protected]>", "Chrislearn Young <chrisle

[features]
default = []
full = ["swagger-ui", "rapidoc", "redoc", "chrono", "decimal", "url", "ulid", "uuid", "time", "smallvec", "indexmap", "yaml"]
full = ["swagger-ui", "scalar", "rapidoc", "redoc", "chrono", "decimal", "url", "ulid", "uuid", "time", "smallvec", "indexmap", "yaml"]
swagger-ui = ["dep:rust-embed"]
scalar = []
rapidoc = []
redoc = []
chrono = ["salvo-oapi-macros/chrono", "dep:chrono"]
Expand Down
4 changes: 4 additions & 0 deletions crates/oapi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ cfg_feature! {
#![feature ="swagger-ui"]
pub mod swagger_ui;
}
cfg_feature! {
#![feature ="scalar"]
pub mod scalar;
}
cfg_feature! {
#![feature ="rapidoc"]
pub mod rapidoc;
Expand Down
2 changes: 1 addition & 1 deletion crates/oapi/src/rapidoc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl RapiDoc {
///
/// ```rust
/// # use salvo_oapi::rapidoc::RapiDoc;
/// let doc = RapiDoc::new("/rapidoc/openapi.json");
/// let doc = RapiDoc::new("/openapi.json");
/// ```
pub fn new(spec_url: impl Into<String>) -> Self {
let spec_url = spec_url.into();
Expand Down
2 changes: 1 addition & 1 deletion crates/oapi/src/redoc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl ReDoc {
///
/// ```rust
/// # use salvo_oapi::redoc::ReDoc;
/// let doc = ReDoc::new("/rapidoc/openapi.json");
/// let doc = ReDoc::new("/openapi.json");
/// ```
pub fn new(spec_url: impl Into<String>) -> Self {
let spec_url = spec_url.into();
Expand Down
79 changes: 79 additions & 0 deletions crates/oapi/src/scalar/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//! This crate implements necessary boiler plate code to serve ReDoc via web server. It
//! works as a bridge for serving the OpenAPI documentation created with [`salvo`][salvo] library in the
//! ReDoc.
//!
//! [salvo]: <https://docs.rs/salvo/>
//!
use salvo_core::writing::Text;
use salvo_core::{async_trait, Depot, FlowCtrl, Handler, Request, Response, Router};

const INDEX_TMPL: &str = r#"
<!DOCTYPE html>
<html>
<head>
<title>Scalar</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700"
rel="stylesheet"
/>
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>

<body>
<script id="api-reference" data-url="{{spec_url}}"></script>
<script src="https://www.unpkg.com/@scalar/api-reference"></script>
</body>
</html>

"#;

/// Implements [`Handler`] for serving ReDoc.
#[derive(Clone, Debug)]
pub struct Scalar {
spec_url: String,
html: String,
}
impl Scalar {
/// Create a new [`ReDoc`] for given path.
///
/// Path argument will expose the ReDoc to the user and should be something that
/// the underlying application framework / library supports.
///
/// # Examples
///
/// ```rust
/// # use salvo_oapi::scalar::Scalar;
/// let doc = Scalar::new("/openapi.json");
/// ```
pub fn new(spec_url: impl Into<String>) -> Self {
let spec_url = spec_url.into();
Self {
html: INDEX_TMPL.replace("{{spec_url}}", &spec_url),
spec_url,
}
}

/// Returns the spec url.
pub fn sepec_url(&self) -> &str {
&self.spec_url
}

/// Consusmes the [`Scalar`] and returns [`Router`] with the [`Scalar`] as handler.
pub fn into_router(self, path: impl Into<String>) -> Router {
Router::with_path(path.into()).goal(self)
}
}

#[async_trait]
impl Handler for Scalar {
async fn handle(&self, _req: &mut Request, _depot: &mut Depot, res: &mut Response, _ctrl: &mut FlowCtrl) {
res.render(Text::Html(&self.html));
}
}
1 change: 1 addition & 0 deletions crates/salvo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,5 +229,6 @@ pub mod prelude {
pub use crate::oapi::swagger_ui::SwaggerUi;
pub use crate::oapi::rapidoc::RapiDoc;
pub use crate::oapi::redoc::ReDoc;
pub use crate::oapi::scalar::Scalar;
}
}
2 changes: 2 additions & 0 deletions examples/oapi-todos/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ async fn main() {
let router = router
.unshift(doc.into_router("/api-doc/openapi.json"))
.unshift(SwaggerUi::new("/api-doc/openapi.json").into_router("/swagger-ui"))
.unshift(Scalar::new("/api-doc/openapi.json").into_router("/scalar"))
.unshift(RapiDoc::new("/api-doc/openapi.json").into_router("/rapidoc"))
.unshift(ReDoc::new("/api-doc/openapi.json").into_router("/redoc"));

Expand Down Expand Up @@ -130,6 +131,7 @@ static INDEX_HTML: &str = r#"<!DOCTYPE html>
<body>
<ul>
<li><a href="swagger-ui" target="_blank">swagger-ui</a></li>
<li><a href="scalar" target="_blank">scalar</a></li>
<li><a href="rapidoc" target="_blank">rapidoc</a></li>
<li><a href="redoc" target="_blank">redoc</a></li>
</ul>
Expand Down