Skip to content

Commit

Permalink
Merge branch 'master' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
sunli829 committed Sep 6, 2023
2 parents 559f5d7 + 27a77b7 commit ed5fea6
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 12 deletions.
2 changes: 1 addition & 1 deletion poem-openapi-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "poem-openapi-derive"
version = "3.0.4"
version = "3.0.5"
authors.workspace = true
edition.workspace = true
license.workspace = true
Expand Down
4 changes: 2 additions & 2 deletions poem-openapi-derive/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,11 @@ fn generate_operation(
let (oai_path, new_path) = convert_oai_path(&path)?;
let oai_path = prefix_path
.as_ref()
.map(|prefix| quote! { (::std::string::ToString::to_string(#prefix) + #oai_path) })
.map(|prefix| quote! { #crate_name::__private::join_path(#prefix, #oai_path) })
.unwrap_or_else(|| quote! { ::std::string::ToString::to_string(#oai_path) });
let new_path: TokenStream = prefix_path
.as_ref()
.map(|prefix| quote! { (::std::string::ToString::to_string(#prefix) + #new_path) })
.map(|prefix| quote! { #crate_name::__private::join_path(#prefix, #new_path) })
.unwrap_or_else(|| quote! { ::std::string::ToString::to_string(#new_path) });

if item_method.sig.inputs.is_empty() {
Expand Down
4 changes: 4 additions & 0 deletions poem-openapi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

# [3.0.5] 2023-09-06

- fixes [#648](https://github.com/poem-web/poem/issues/648)

# [3.0.4] 2023-09-02

- allow using expressions as `prefix_path` parameter [#635](https://github.com/poem-web/poem/issues/635)
Expand Down
2 changes: 1 addition & 1 deletion poem-openapi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "poem-openapi"
version = "3.0.4"
version = "3.0.5"
authors.workspace = true
edition.workspace = true
license.workspace = true
Expand Down
3 changes: 2 additions & 1 deletion poem-openapi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ pub mod validation;

mod base;
mod openapi;
mod path_util;
#[cfg(any(
feature = "swagger-ui",
feature = "rapidoc",
Expand Down Expand Up @@ -184,5 +185,5 @@ pub mod __private {
pub use serde;
pub use serde_json;

pub use crate::{auth::CheckerReturn, base::UrlQuery};
pub use crate::{auth::CheckerReturn, base::UrlQuery, path_util::join_path};
}
45 changes: 45 additions & 0 deletions poem-openapi/src/path_util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
fn normalize_path(path: &str) -> String {
if path.is_empty() {
"/".to_string()
} else if !path.starts_with('/') {
format!("/{}", path)
} else {
path.to_string()
}
}

#[doc(hidden)]
pub fn join_path(base: &str, path: &str) -> String {
let base = normalize_path(base);
let path = normalize_path(path);

if path == "/" {
return base;
}

if base.ends_with('/') {
base + path.trim_start_matches('/')
} else {
base + &path
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_join_path() {
assert_eq!(join_path("", "/abc"), "/abc");
assert_eq!(join_path("/abc", "/def"), "/abc/def");
assert_eq!(join_path("/abc", "def"), "/abc/def");
assert_eq!(join_path("abc/def", "ghi"), "/abc/def/ghi");
assert_eq!(join_path("/", "/ghi"), "/ghi");
assert_eq!(join_path("/", "/"), "/");
assert_eq!(join_path("/abc", ""), "/abc");
assert_eq!(join_path("", ""), "/");
assert_eq!(join_path("/abc/", "/"), "/abc/");
assert_eq!(join_path("/abc/", "/def"), "/abc/def");
assert_eq!(join_path("/abc/", "/def/"), "/abc/def/");
}
}
104 changes: 97 additions & 7 deletions poem-openapi/tests/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ fn tag() {
}

#[tokio::test]
async fn common_attributes() {
async fn common_tags() {
#[derive(Tags)]
enum MyTags {
UserOperations,
Expand All @@ -97,6 +97,24 @@ async fn common_attributes() {
meta.paths[0].operations[0].tags,
vec!["CommonOperations", "UserOperations"]
);
}

#[tokio::test]
async fn prefix_path() {
struct Api;

#[OpenApi(prefix_path = "/hello")]
impl Api {
#[oai(path = "/world", method = "get")]
async fn test(&self) {}

#[oai(path = "/", method = "get")]
async fn test1(&self) {}
}

let meta: MetaApi = Api::meta().remove(0);
assert_eq!(meta.paths[0].path, "/hello/world");
assert_eq!(meta.paths[1].path, "/hello");

let ep = OpenApiService::new(Api, "test", "1.0");
TestClient::new(ep)
Expand All @@ -105,29 +123,101 @@ async fn common_attributes() {
.await
.assert_status_is_ok();

let ep = OpenApiService::new(Api, "test", "1.0");
TestClient::new(ep)
.get("/hello")
.send()
.await
.assert_status_is_ok();

const PREFIX: &str = "/hello2";

struct Api2;

#[OpenApi(prefix_path = PREFIX, tag = "MyTags::CommonOperations")]
#[OpenApi(prefix_path = PREFIX)]
impl Api2 {
#[oai(path = "/world", method = "get", tag = "MyTags::UserOperations")]
#[oai(path = "/world", method = "get")]
async fn test(&self) {}

#[oai(path = "/", method = "get")]
async fn test1(&self) {}
}

let meta: MetaApi = Api2::meta().remove(0);
assert_eq!(meta.paths[0].path, "/hello2/world");
assert_eq!(
meta.paths[0].operations[0].tags,
vec!["CommonOperations", "UserOperations"]
);
assert_eq!(meta.paths[1].path, "/hello2");

let ep = OpenApiService::new(Api2, "test", "1.0");
TestClient::new(ep)
.get("/hello2/world")
.send()
.await
.assert_status_is_ok();

let ep = OpenApiService::new(Api2, "test", "1.0");
TestClient::new(ep)
.get("/hello2")
.send()
.await
.assert_status_is_ok();

struct Api3;

#[OpenApi(prefix_path = "/hello3/")]
impl Api3 {
#[oai(path = "/world", method = "get")]
async fn test(&self) {}

#[oai(path = "/", method = "get")]
async fn test1(&self) {}
}

let meta: MetaApi = Api3::meta().remove(0);
assert_eq!(meta.paths[0].path, "/hello3/world");
assert_eq!(meta.paths[1].path, "/hello3/");

let ep = OpenApiService::new(Api3, "test", "1.0");
TestClient::new(ep)
.get("/hello3/world")
.send()
.await
.assert_status_is_ok();

let ep = OpenApiService::new(Api3, "test", "1.0");
TestClient::new(ep)
.get("/hello3/")
.send()
.await
.assert_status_is_ok();

struct Api4;

#[OpenApi(prefix_path = "")]
impl Api4 {
#[oai(path = "/world", method = "get")]
async fn test(&self) {}

#[oai(path = "/", method = "get")]
async fn test1(&self) {}
}

let meta: MetaApi = Api4::meta().remove(0);
assert_eq!(meta.paths[0].path, "/world");
assert_eq!(meta.paths[1].path, "/");

let ep = OpenApiService::new(Api4, "test", "1.0");
TestClient::new(ep)
.get("/world")
.send()
.await
.assert_status_is_ok();

let ep = OpenApiService::new(Api4, "test", "1.0");
TestClient::new(ep)
.get("/")
.send()
.await
.assert_status_is_ok();
}

#[tokio::test]
Expand Down

0 comments on commit ed5fea6

Please sign in to comment.