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

OpenAPI Explorer #440

Merged
merged 3 commits into from
Dec 6, 2022
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
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.