Skip to content

Commit

Permalink
OpenAPI Explorer (#440)
Browse files Browse the repository at this point in the history
* Add openapi explorer api viewer

* Specify font family for openapi explorer

* Fix mislabeled comment
  • Loading branch information
FallingSnow authored Dec 6, 2022
1 parent a37b07a commit ec3deb8
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 16 deletions.
1 change: 1 addition & 0 deletions poem-openapi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ categories = ["network-programming", "asynchronous"]
swagger-ui = []
rapidoc = []
redoc = []
openapi-explorer = []
email = ["email_address"]
hostname = ["hostname-validator"]
static-files = ["poem/static-files"]
Expand Down
33 changes: 17 additions & 16 deletions poem-openapi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,23 @@ important business implementations.

To avoid compiling unused dependencies, Poem gates certain features, some of which are disabled by default:

| Feature | Description |
|--------------|----------------------------------------------------------------------------------|
| chrono | Integrate with the [`chrono` crate](https://crates.io/crates/chrono). |
| time | Integrate with the [`time` crate](https://crates.io/crates/time). |
| humantime | Integrate with the [`humantime` crate](https://crates.io/crates/humantime) |
| swagger-ui | Add swagger UI support |
| rapidoc | Add RapiDoc UI support |
| redoc | Add Redoc UI support |
| email | Support for email address string |
| hostname | Support for hostname string |
| uuid | Integrate with the [`uuid` crate](https://crates.io/crates/uuid) |
| url | Integrate with the [`url` crate](https://crates.io/crates/url) |
| bson | Integrate with the [`bson` crate](https://crates.io/crates/bson) |
| rust_decimal | Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal) |
| static-files | Support for static file response |
| websocket | Support for websocket |
| Feature | Description |
|------------------|----------------------------------------------------------------------------------|
| chrono | Integrate with the [`chrono` crate](https://crates.io/crates/chrono). |
| time | Integrate with the [`time` crate](https://crates.io/crates/time). |
| humantime | Integrate with the [`humantime` crate](https://crates.io/crates/humantime) |
| openapi-explorer | Add OpenAPI Explorer support |
| swagger-ui | Add swagger UI support |
| rapidoc | Add RapiDoc UI support |
| redoc | Add Redoc UI support |
| email | Support for email address string |
| hostname | Support for hostname string |
| uuid | Integrate with the [`uuid` crate](https://crates.io/crates/uuid) |
| url | Integrate with the [`url` crate](https://crates.io/crates/url) |
| bson | Integrate with the [`bson` crate](https://crates.io/crates/bson) |
| rust_decimal | Integrate with the [`rust_decimal` crate](https://crates.io/crates/rust_decimal) |
| static-files | Support for static file response |
| websocket | Support for websocket |

## Safety

Expand Down
21 changes: 21 additions & 0 deletions poem-openapi/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,27 @@ impl<T, W> OpenApiService<T, W> {
}
}

/// Create the OpenAPI Explorer endpoint.
#[must_use]
#[cfg(feature = "openapi-explorer")]
pub fn openapi_explorer(&self) -> impl Endpoint
where
T: OpenApi,
W: Webhook,
{
crate::ui::openapi_explorer::create_endpoint(&self.spec())
}

/// Create the OpenAPI Explorer HTML
#[cfg(feature = "openapi-explorer")]
pub fn openapi_explorer_html(&self) -> String
where
T: OpenApi,
W: Webhook,
{
crate::ui::openapi_explorer::create_html(&self.spec())
}

/// Create the Swagger UI endpoint.
#[must_use]
#[cfg(feature = "swagger-ui")]
Expand Down
2 changes: 2 additions & 0 deletions poem-openapi/src/ui/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#[cfg(feature = "openapi-explorer")]
pub(crate) mod openapi_explorer;
#[cfg(feature = "rapidoc")]
pub(crate) mod rapidoc;
#[cfg(feature = "redoc")]
Expand Down
42 changes: 42 additions & 0 deletions poem-openapi/src/ui/openapi_explorer/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use poem::{endpoint::make_sync, web::Html, Endpoint};

const REDOC_JS: &str = include_str!("openapi-explorer.min.js");

const REDOC_TEMPLATE: &str = r#"
<!DOCTYPE html>
<html>
<head>
<title>OpenAPI Explorer</title>
<!-- needed for adaptive design -->
<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 type="text/css">
:root {
--font-regular: Montserrat;
}
</style>
<script charset="UTF-8">{:script}</script>
</head>
<body>
<openapi-explorer></openapi-explorer>
<script>
let spec = {:spec};
document.getElementsByTagName('openapi-explorer')[0].loadSpec(spec).catch(console.error);
</script>
</body>
</html>
"#;

pub(crate) fn create_html(document: &str) -> String {
REDOC_TEMPLATE
.replace("{:script}", REDOC_JS)
.replace("{:spec}", document)
}

pub(crate) fn create_endpoint(document: &str) -> impl Endpoint {
let ui_html = create_html(document);
poem::Route::new().at("/", make_sync(move |_| Html(ui_html.clone())))
}
5 changes: 5 additions & 0 deletions poem-openapi/src/ui/openapi_explorer/openapi-explorer.min.js

Large diffs are not rendered by default.

0 comments on commit ec3deb8

Please sign in to comment.