Skip to content

Commit

Permalink
Merge pull request #9 from kotborealis/dyn-spec
Browse files Browse the repository at this point in the history
Dyn spec
  • Loading branch information
Wicpar authored Sep 26, 2023
2 parents d9f3331 + 742119f commit 7b77f7b
Show file tree
Hide file tree
Showing 22 changed files with 127 additions and 546 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
Cargo.lock
.idea
9 changes: 0 additions & 9 deletions .idea/modules.xml

This file was deleted.

18 changes: 0 additions & 18 deletions .idea/swagger-ui.iml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

324 changes: 0 additions & 324 deletions .idea/workspace.xml

This file was deleted.

2 changes: 1 addition & 1 deletion actix-web-swagger-ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "actix-web-swagger-ui"
version = "0.1.0"
authors = ["Tarkin25 <[email protected]>"]
edition = "2018"
edition = "2021"
exclude = [
".idea"
]
Expand Down
29 changes: 14 additions & 15 deletions actix-web-swagger-ui/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use actix_files::file_extension_to_mime;
use actix_utils::future::ok;
use actix_utils::future::{ok, ready};
use actix_web::http::header::{ContentType, LOCATION};
use actix_web::web::{self, ServiceConfig};
use actix_web::{HttpRequest, HttpResponse, Route};
Expand All @@ -12,15 +12,15 @@ const CONFIG_FILE_PATH: &str = "/swagger-ui-config.json";
pub fn swagger(spec: Spec, config: Config) -> impl FnOnce(&mut ServiceConfig) {
let mut routes: Vec<(String, Route)> = vec![];

let config_route = config_route(config, spec.name.clone());
routes.push(("/swagger-ui-config.json".into(), config_route));
let config_route = config_route(config, spec.name.clone().into_owned());
routes.push(("/swagger-ui-config.json".to_owned(), config_route));

let spec_path = spec.name.clone();
let spec_path = spec.name.clone().into_owned();
let spec_route = spec_route(spec);
routes.push((spec_path, spec_route));

let index_route = index_route();
routes.push(("".into(), index_route));
routes.push(("".to_owned(), index_route));

for file in Assets::iter() {
let filename = file.as_ref();
Expand All @@ -43,18 +43,18 @@ fn config_route(config: Config, spec_name: String) -> Route {
let mut config = config.clone();
config.url = format!("{}/{}", path, &spec_name);

HttpResponse::Ok().json(config)
ready(HttpResponse::Ok().json(config))
})
}

fn spec_route(spec: Spec) -> Route {
let content_type = content_type(&spec.name);
let content = Vec::from(spec.content);
let content = spec.content.into_owned();

web::to(move || {
HttpResponse::Ok()
ready(HttpResponse::Ok()
.content_type(content_type.clone())
.body(content.clone())
.body(content.clone()))
})
}

Expand All @@ -65,9 +65,9 @@ fn index_route() -> Route {
let config_url = format!("{}{}", path, CONFIG_FILE_PATH);
let index_url = format!("{}/index.html?configUrl={}", path, config_url);

HttpResponse::Found()
ready(HttpResponse::Found()
.append_header((LOCATION, index_url))
.finish()
.finish())
})
}

Expand Down Expand Up @@ -101,8 +101,7 @@ fn extension(filename: &str) -> &str {
mod tests {
use std::fs;
use actix_http::Request;
use actix_web::body::Body;
use actix_web::{http, test::{TestRequest, call_service, init_service, read_body}, web::scope, App};
use actix_web::{ test::{TestRequest, call_service, init_service, read_body}, web::scope, App};
use actix_web::dev::ServiceResponse;
use actix_web::web::Bytes;

Expand All @@ -111,8 +110,8 @@ mod tests {
macro_rules! init_app {
($scope:expr) => {{
let spec = Spec {
name: "openapi.json".into(),
content: include_bytes!("../../swagger-ui/examples/openapi.json"),
name: std::borrow::Cow::Borrowed("openapi.json"),
content: std::borrow::Cow::Borrowed(include_bytes!("../../swagger-ui/examples/openapi.json")),
};
let config = Config::default();
let app = App::new()
Expand Down
5 changes: 3 additions & 2 deletions rocket-swagger-ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "rocket-swagger-ui"
version = "0.1.5"
authors = ["kotborealis <[email protected]>"]
edition = "2018"
edition = "2021"
exclude = [
".idea"
]
Expand All @@ -17,4 +17,5 @@ repository = "https://github.com/kotborealis/swagger-ui"
swagger-ui = { version = "0.1", path = "../swagger-ui" }
rocket = "0.4.7"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.64"
serde_json = "1.0.64"
derive_builder = "0.12.0"
6 changes: 3 additions & 3 deletions rocket-swagger-ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ fn mime_type(filename: &str) -> ContentType {
pub fn routes(spec: Spec, mut config: Config) -> Vec<Route> {
let spec_handler =
ContentHandler::bytes(
mime_type(spec.name.as_str()),
Vec::from(spec.content),
mime_type(spec.name.as_ref()),
spec.content.into_owned(),
);

let spec_name: &str =
Path::new(&spec.name)
Path::new(spec.name.as_ref())
.file_name()
.unwrap_or("openapi.json".as_ref())
.to_str()
Expand Down
3 changes: 2 additions & 1 deletion swagger-ui/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
Cargo.lock
.idea
.idea
.dist
14 changes: 12 additions & 2 deletions swagger-ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "swagger-ui"
version = "0.1.5"
authors = ["kotborealis <[email protected]>"]
edition = "2018"
edition = "2021"
exclude = [
".idea"
]
Expand All @@ -24,4 +24,14 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.64"

rocket-swagger-ui = { version = "0.1", optional = true }
# actix-web-swagger-ui = { version = "0.1", optional = true }
# actix-web-swagger-ui = { version = "0.1", optional = true }

[build-dependencies]
reqwest = { version = "0.11.20", features = ["json", "stream", "rustls"] }
futures = "0.3.28"
futures-executor = "0.3.28"
tokio = { version = "1.32.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0.75"
async-recursion = "1.0.5"
77 changes: 77 additions & 0 deletions swagger-ui/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use std::path::PathBuf;
use anyhow::Context;
use async_recursion::async_recursion;
use serde::Deserialize;
use futures::StreamExt;
use reqwest::{Client, IntoUrl};

#[derive(Deserialize)]
#[serde(rename_all="snake_case")]
enum EntryType {
File,
Dir
}

#[derive(Deserialize)]
struct FolderEntry {
name: String,
url: String,
r#type: EntryType,
download_url: Option<String>
}

#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum OneOrMany<T> {
/// Single value
One(T),
/// Array of values
Vec(Vec<T>),
}
impl<T> From<OneOrMany<T>> for Vec<T> {
fn from(from: OneOrMany<T>) -> Self {
match from {
OneOrMany::One(val) => vec![val],
OneOrMany::Vec(vec) => vec,
}
}
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let out_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?).join(".dist");
download_folder("https://api.github.com/repos/swagger-api/swagger-ui/contents/dist", out_dir).await?;
Ok(())
}

#[async_recursion]
async fn download_folder(url: &str, to: impl Into<PathBuf> + Send + 'static) -> anyhow::Result<()> {
let entries: Vec<_> = reqwest()?.get(url).send().await.with_context(||format!("failed to query folder data for {url}"))?.json::<OneOrMany<FolderEntry>>().await.with_context(||format!("failed to parse json for {url}"))?.into();
let ref path = to.into();
futures::future::try_join_all(entries.into_iter().map(|entry| async move {
match entry.r#type {
EntryType::File => download_file(entry.download_url.unwrap(), path.clone().join(entry.name)).await,
EntryType::Dir => download_folder(&entry.url, path.clone().join(entry.name)).await
}
})).await?;
Ok(())
}

async fn download_file(url: impl IntoUrl + Send, to: impl Into<PathBuf> + Send) -> anyhow::Result<()> {
let path = to.into();
if let Some(parent) = path.parent() {
tokio::fs::create_dir_all(parent).await?;
}
let mut byte_stream = reqwest()?.get(url).send().await?.bytes_stream();
let mut tmp_file = tokio::fs::File::create(path).await?;
while let Some(item) = byte_stream.next().await {
tokio::io::copy(&mut item?.as_ref(), &mut tmp_file).await?;
}
Ok(())
}

fn reqwest() -> anyhow::Result<Client> {
Ok(Client::builder()
.user_agent("reqwest")
.build()?)
}
Binary file removed swagger-ui/dist/favicon-16x16.png
Binary file not shown.
Binary file removed swagger-ui/dist/favicon-32x32.png
Binary file not shown.
60 changes: 0 additions & 60 deletions swagger-ui/dist/index.html

This file was deleted.

Loading

0 comments on commit 7b77f7b

Please sign in to comment.