Skip to content

Commit 2dc2bd4

Browse files
committed
Merge branch 'master' into release
2 parents db15f1a + f6bec88 commit 2dc2bd4

File tree

175 files changed

+566
-572
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

175 files changed

+566
-572
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
# Switch to stable Rust
5656
- uses: actions-rs/toolchain@v1
5757
with:
58-
toolchain: 1.74.0
58+
toolchain: 1.75.0
5959
components: rustfmt, clippy
6060
override: true
6161
- name: Cache Rust
@@ -91,7 +91,7 @@ jobs:
9191
# Switch to stable Rust
9292
- uses: actions-rs/toolchain@v1
9393
with:
94-
toolchain: 1.74.0
94+
toolchain: 1.75.0
9595
components: rustfmt, clippy
9696
- name: Cache Rust
9797
uses: Swatinem/rust-cache@v2

.github/workflows/code-coverage.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- name: Install Stable Toolchain
2222
uses: dtolnay/rust-toolchain@stable
2323
with:
24-
toolchain: 1.74.0
24+
toolchain: 1.75.0
2525
components: rustfmt
2626
- name: Cache Rust
2727
uses: Swatinem/rust-cache@v2

Cargo.toml

+9-7
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ license = "MIT OR Apache-2.0"
1717
documentation = "https://docs.rs/poem/"
1818
homepage = "https://github.com/poem-web/poem"
1919
repository = "https://github.com/poem-web/poem"
20-
rust-version = "1.74"
20+
rust-version = "1.75"
2121

2222
[workspace.dependencies]
23-
poem = { path = "poem", version = "2.0.1", default-features = false }
24-
poem-derive = { path = "poem-derive", version = "2.0.1" }
25-
poem-openapi-derive = { path = "poem-openapi-derive", version = "4.0.1" }
26-
poem-grpc-build = { path = "poem-grpc-build", version = "0.3.0" }
23+
poem = { path = "poem", version = "3.0.0", default-features = false }
24+
poem-derive = { path = "poem-derive", version = "3.0.0" }
25+
poem-openapi-derive = { path = "poem-openapi-derive", version = "5.0.0" }
26+
poem-grpc-build = { path = "poem-grpc-build", version = "0.4.0" }
2727

2828
proc-macro-crate = "3.0.0"
2929
proc-macro2 = "1.0.29"
@@ -42,10 +42,12 @@ futures-util = "0.3.17"
4242
tokio-stream = "0.1.8"
4343
serde_yaml = "0.9"
4444
quick-xml = { version = "0.31.0", features = ["serialize"] }
45-
base64 = "0.21.0"
45+
base64 = "0.22.0"
4646
serde_urlencoded = "0.7.1"
4747
indexmap = "2.0.0"
48-
reqwest = { version = "0.11.23", default-features = false }
48+
reqwest = { version = "0.12.2", default-features = false }
49+
darling = "0.20.8"
50+
static_assertions = "1.1.0"
4951

5052
# rustls, update together
5153
rustls = "0.22.0"

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
<img src="https://img.shields.io/badge/unsafe-forbidden-success.svg?style=flat-square"
1010
alt="Unsafe Rust forbidden" />
1111
</a>
12-
<a href="https://blog.rust-lang.org/2022/09/22/Rust-1.74.0.html">
13-
<img src="https://img.shields.io/badge/rustc-1.74.0+-ab6000.svg"
14-
alt="rustc 1.74.0+" />
12+
<a href="https://blog.rust-lang.org/2023/11/16/Rust-1.75.0.html">
13+
<img src="https://img.shields.io/badge/rustc-1.75.0+-ab6000.svg"
14+
alt="rustc 1.75.0+" />
1515
</a>
1616
<a href="https://discord.gg/qWWNxwasb7">
1717
<img src="https://img.shields.io/discord/932986985604333638.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2" />

examples/disabled/tonic/src/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ pub mod hello_world {
1212

1313
pub struct MyGreeter;
1414

15-
#[tonic::async_trait]
1615
impl Greeter for MyGreeter {
1716
async fn say_hello(
1817
&self,

examples/grpc/helloworld/src/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ poem_grpc::include_proto!("helloworld");
55

66
struct GreeterService;
77

8-
#[poem::async_trait]
98
impl Greeter for GreeterService {
109
async fn say_hello(
1110
&self,

examples/grpc/jsoncodec/src/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ poem_grpc::include_proto!("helloworld");
55

66
struct GreeterService;
77

8-
#[poem::async_trait]
98
impl Greeter for GreeterService {
109
async fn say_hello(
1110
&self,

examples/grpc/middleware/src/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ poem_grpc::include_proto!("helloworld");
77

88
struct GreeterService;
99

10-
#[poem::async_trait]
1110
impl Greeter for GreeterService {
1211
async fn say_hello(
1312
&self,

examples/grpc/reflection/src/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ const FILE_DESCRIPTOR_SET: &[u8] = poem_grpc::include_file_descriptor_set!("hell
66

77
struct GreeterService;
88

9-
#[poem::async_trait]
109
impl Greeter for GreeterService {
1110
async fn say_hello(
1211
&self,

examples/grpc/routeguide/src/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ struct RouteGuideService {
1212
features: Arc<Vec<Feature>>,
1313
}
1414

15-
#[poem::async_trait]
1615
impl RouteGuide for RouteGuideService {
1716
async fn get_feature(&self, request: Request<Point>) -> Result<Response<Feature>, Status> {
1817
for feature in &self.features[..] {

examples/disabled/auth-github/Cargo.toml examples/openapi/auth-github/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ publish.workspace = true
88
poem.workspace = true
99
poem-openapi.workspace = true
1010
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11-
reqwest = { version = "0.11.4", default-features = false, features = [
11+
reqwest = { version = "0.12.2", default-features = false, features = [
1212
"rustls-tls",
1313
] }
1414
tracing-subscriber.workspace = true

examples/openapi/auth-multiple/src/main.rs

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ impl Api {
7676
auth1: MyApiKeyAuthorization,
7777
auth2: MyBasicAuthorization,
7878
) -> Result<PlainText<String>> {
79+
if auth1.0.username != "test" {
80+
return Err(Error::from_status(StatusCode::UNAUTHORIZED));
81+
}
7982
if auth2.0.username != "test" || auth2.0.password != "123456" {
8083
return Err(Error::from_status(StatusCode::UNAUTHORIZED));
8184
}

examples/openapi/content-type-accept/src/bcs_payload.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,11 @@ impl<T: Type> Payload for Bcs<T> {
5050
}
5151
}
5252

53-
#[poem::async_trait]
5453
impl<T: Type + for<'b> Deserialize<'b>> ParsePayload for Bcs<T> {
5554
const IS_REQUIRED: bool = true;
5655

5756
async fn from_request(request: &Request, body: &mut RequestBody) -> Result<Self> {
58-
let data: Vec<u8> = FromRequest::from_request(request, body).await?;
57+
let data = Vec::<u8>::from_request(request, body).await?;
5958
let value: T = from_bytes(&data).map_err(|err| ParseRequestPayloadError {
6059
reason: err.to_string(),
6160
})?;

examples/openapi/custom-payload/src/bcs_payload.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,11 @@ impl<T: Type> Payload for Bcs<T> {
5050
}
5151
}
5252

53-
#[poem::async_trait]
5453
impl<T: Type + for<'b> Deserialize<'b>> ParsePayload for Bcs<T> {
5554
const IS_REQUIRED: bool = true;
5655

5756
async fn from_request(request: &Request, body: &mut RequestBody) -> Result<Self> {
58-
let data: Vec<u8> = FromRequest::from_request(request, body).await?;
57+
let data = Vec::<u8>::from_request(request, body).await?;
5958
let value: T = from_bytes(&data).map_err(|err| ParseRequestPayloadError {
6059
reason: err.to_string(),
6160
})?;

examples/poem/basic-auth/src/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ struct BasicAuthEndpoint<E> {
3232
password: String,
3333
}
3434

35-
#[poem::async_trait]
3635
impl<E: Endpoint> Endpoint for BasicAuthEndpoint<E> {
3736
type Output = E::Output;
3837

examples/poem/custom-extractor/src/main.rs

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use poem::{
66
struct Token(String);
77

88
// Implements a token extractor
9-
#[poem::async_trait]
109
impl<'a> FromRequest<'a> for Token {
1110
async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result<Self> {
1211
let token = req

examples/poem/local-server-with-browser/src/main.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ async fn main() -> Result<(), std::io::Error> {
1919

2020
// To test port assignment, run two instances of this example at once.
2121
//
22-
// For ports <1024, running with administrator priveleges would be needed on
23-
// Unix. For port 0, the OS would assign a port and we'd need to find out
22+
// For ports <1024, running with administrator priveledges would be needed
23+
// on Unix. For port 0, the OS would assign a port and we'd need to find out
2424
// what that port's number is.
2525
let (min_port, max_port) = (8080, 8085);
2626
// Using 127.0.0.1 instead of 0.0.0.0 for security; a local server should
@@ -32,25 +32,30 @@ async fn main() -> Result<(), std::io::Error> {
3232
if port > max_port {
3333
return Err(error.unwrap());
3434
}
35-
let listener = TcpListener::bind(format!("{hostname}:{}", port));
35+
let listener = TcpListener::bind(format!("{hostname}:{port}"));
3636
match listener.into_acceptor().await {
3737
Ok(a) => break a,
38-
Err(err) => {
39-
// Most likely, another application is bound to this port.
40-
eprintln!("Couldn't bind to port {port}.");
41-
error = Some(err)
42-
}
38+
Err(err) => error = Some(err),
4339
};
40+
// Most likely, another application is bound to this port.
41+
eprintln!("Couldn't bind to port {port}.");
4442
port += 1;
4543
};
4644

4745
// Now that the acceptor exists, the browser should be able to connect
46+
eprintln!("Listening at {hostname}:{port}.");
4847
let http_address = format!("http://{hostname}:{port}/");
49-
eprintln!("Listening at {http_address}.");
50-
eprint!("Trying to launch a browser at {http_address}...");
51-
match open::that(&http_address) {
52-
Ok(_) => eprintln!(" Success!"),
53-
Err(err) => eprintln!("\nFailed to launch a browser: {err}"),
48+
eprintln!("Trying to launch a browser at {http_address}...");
49+
// We use `open::that_detached` so that launching, for example, a new
50+
// instance of firefox on Linux does not block. This will report success
51+
// even if the browser exits with a non-zero error code.
52+
//
53+
// You can alternatively consider using `tokio::spawn_blocking` and
54+
// `open::that`. Note that in cases when `open::that` blocks, exiting the
55+
// server process may also kill the browser process.
56+
match open::that_detached(&http_address) {
57+
Ok(()) => { /* Ok() doesn't mean much with `that_detached`. */ }
58+
Err(err) => eprintln!("Failed to launch a browser: {err}"),
5459
}
5560

5661
Server::new_with_acceptor(acceptor).run(app).await?;

examples/poem/middleware/src/main.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use poem::{
2-
async_trait, get, handler, listener::TcpListener, Endpoint, EndpointExt, IntoResponse,
3-
Middleware, Request, Response, Result, Route, Server,
2+
get, handler, listener::TcpListener, Endpoint, EndpointExt, IntoResponse, Middleware, Request,
3+
Response, Result, Route, Server,
44
};
55

66
struct Log;
@@ -15,7 +15,6 @@ impl<E: Endpoint> Middleware<E> for Log {
1515

1616
struct LogImpl<E>(E);
1717

18-
#[async_trait]
1918
impl<E: Endpoint> Endpoint for LogImpl<E> {
2019
type Output = Response;
2120

examples/poem/opentelemetry-jaeger/Cargo.toml

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ publish.workspace = true
88
poem = { workspace = true, features = ["opentelemetry"] }
99
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
1010
tracing-subscriber.workspace = true
11-
opentelemetry = { version = "0.21.0", features = ["metrics"] }
12-
opentelemetry_sdk = { version = "0.21.0", features = ["rt-tokio"] }
13-
opentelemetry-http = { version = "0.10.0" }
14-
opentelemetry-otlp = { version = "0.14.0", features = [
11+
opentelemetry = { version = "0.22.0", features = ["metrics"] }
12+
opentelemetry_sdk = { version = "0.22.0", features = ["rt-tokio"] }
13+
opentelemetry-http = { version = "0.11.0" }
14+
opentelemetry-otlp = { version = "0.15.0", features = [
1515
"trace",
1616
] }
17-
reqwest = "0.11.6"
17+
reqwest = "0.11"
1818

1919
[[bin]]
2020
name = "example-opentelemetry-client"

examples/poem/redis-session/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ publish.workspace = true
88
poem = { workspace = true, features = ["redis-session"] }
99
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
1010
tracing-subscriber.workspace = true
11-
redis = { version = "0.24.0", features = ["aio", "tokio-comp", "connection-manager"] }
11+
redis = { version = "0.25.2", features = ["aio", "tokio-comp", "connection-manager"] }

poem-derive/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "poem-derive"
3-
version = "2.0.1"
3+
version = "3.0.0"
44
authors.workspace = true
55
edition.workspace = true
66
license.workspace = true

poem-derive/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ fn generate_handler(internal: bool, input: TokenStream) -> Result<TokenStream> {
100100
#[allow(non_camel_case_types)]
101101
#def_struct
102102

103-
#[#crate_name::async_trait]
104103
impl #impl_generics #crate_name::Endpoint for #ident #type_generics #where_clause {
105104
type Output = #crate_name::Response;
106105

poem-grpc-build/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "poem-grpc-build"
3-
version = "0.3.0"
3+
version = "0.4.0"
44
authors.workspace = true
55
edition.workspace = true
66
license.workspace = true

poem-grpc-build/src/client.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub(crate) fn generate(config: &GrpcConfig, service: &Service, buf: &mut String)
110110

111111
pub fn with<M>(mut self, middleware: M) -> Self
112112
where
113-
M: ::poem::Middleware<::std::sync::Arc<dyn ::poem::Endpoint<Output = ::poem::Response> + 'static>>,
113+
M: ::poem::Middleware<::std::sync::Arc<dyn ::poem::endpoint::DynEndpoint<Output = ::poem::Response> + 'static>>,
114114
M::Output: 'static,
115115
{
116116
self.cli = self.cli.with(middleware);

poem-grpc-build/src/server.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -61,25 +61,25 @@ pub(crate) fn generate(config: &GrpcConfig, service: &Service, buf: &mut String)
6161
match (method.client_streaming, method.server_streaming) {
6262
(false, false) => {
6363
trait_methods.push(quote! {
64-
async fn #method_ident(&self, request: #crate_name::Request<#input_type>) -> ::std::result::Result<#crate_name::Response<#output_type>, #crate_name::Status>;
64+
fn #method_ident(&self, request: #crate_name::Request<#input_type>) -> impl ::std::future::Future<Output = ::std::result::Result<#crate_name::Response<#output_type>, #crate_name::Status>> + Send;
6565
});
6666
endpoints.push(generate_unary(&codec_list, method_info));
6767
}
6868
(true, false) => {
6969
trait_methods.push(quote! {
70-
async fn #method_ident(&self, request: #crate_name::Request<#crate_name::Streaming<#input_type>>) -> ::std::result::Result<#crate_name::Response<#output_type>, #crate_name::Status>;
70+
fn #method_ident(&self, request: #crate_name::Request<#crate_name::Streaming<#input_type>>) -> impl ::std::future::Future<Output = ::std::result::Result<#crate_name::Response<#output_type>, #crate_name::Status>> + Send;
7171
});
7272
endpoints.push(generate_client_streaming(&codec_list, method_info));
7373
}
7474
(false, true) => {
7575
trait_methods.push(quote! {
76-
async fn #method_ident(&self, request: #crate_name::Request<#input_type>) -> ::std::result::Result<#crate_name::Response<#crate_name::Streaming<#output_type>>, #crate_name::Status>;
76+
fn #method_ident(&self, request: #crate_name::Request<#input_type>) -> impl ::std::future::Future<Output = ::std::result::Result<#crate_name::Response<#crate_name::Streaming<#output_type>>, #crate_name::Status>> + Send;
7777
});
7878
endpoints.push(generate_server_streaming(&codec_list, method_info));
7979
}
8080
(true, true) => {
8181
trait_methods.push(quote! {
82-
async fn #method_ident(&self, request: #crate_name::Request<#crate_name::Streaming<#input_type>>) -> ::std::result::Result<#crate_name::Response<#crate_name::Streaming<#output_type>>, #crate_name::Status>;
82+
fn #method_ident(&self, request: #crate_name::Request<#crate_name::Streaming<#input_type>>) -> impl ::std::future::Future<Output = ::std::result::Result<#crate_name::Response<#crate_name::Streaming<#output_type>>, #crate_name::Status>> + Send;
8383
});
8484
endpoints.push(generate_bidirectional_streaming(&codec_list, method_info));
8585
}
@@ -94,7 +94,6 @@ pub(crate) fn generate(config: &GrpcConfig, service: &Service, buf: &mut String)
9494

9595
let token_stream = quote! {
9696
#[allow(unused_imports)]
97-
#[::poem::async_trait]
9897
pub trait #service_ident: Send + Sync + 'static {
9998
#(#trait_methods)*
10099
}
@@ -200,7 +199,6 @@ fn generate_unary(codec_list: &[Path], method_info: MethodInfo) -> TokenStream {
200199
#[allow(non_camel_case_types)]
201200
struct #proxy_service_ident<T>(::std::sync::Arc<T>);
202201

203-
#[::poem::async_trait]
204202
impl<T: #service_ident> #crate_name::service::UnaryService<#input_type> for #proxy_service_ident<T> {
205203
type Response = #output_type;
206204

@@ -245,7 +243,6 @@ fn generate_client_streaming(codec_list: &[Path], method_info: MethodInfo) -> To
245243
#[allow(non_camel_case_types)]
246244
struct #proxy_service_ident<T>(::std::sync::Arc<T>);
247245

248-
#[::poem::async_trait]
249246
impl<T: #service_ident> #crate_name::service::ClientStreamingService<#input_type> for #proxy_service_ident<T> {
250247
type Response = #output_type;
251248

@@ -290,7 +287,6 @@ fn generate_server_streaming(codec_list: &[Path], method_info: MethodInfo) -> To
290287
#[allow(non_camel_case_types)]
291288
struct #proxy_service_ident<T>(::std::sync::Arc<T>);
292289

293-
#[::poem::async_trait]
294290
impl<T: #service_ident> #crate_name::service::ServerStreamingService<#input_type> for #proxy_service_ident<T> {
295291
type Response = #output_type;
296292

@@ -335,7 +331,6 @@ fn generate_bidirectional_streaming(codec_list: &[Path], method_info: MethodInfo
335331
#[allow(non_camel_case_types)]
336332
struct #proxy_service_ident<T>(::std::sync::Arc<T>);
337333

338-
#[::poem::async_trait]
339334
impl<T: #service_ident> #crate_name::service::BidirectionalStreamingService<#input_type> for #proxy_service_ident<T> {
340335
type Response = #output_type;
341336

poem-grpc/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "poem-grpc"
3-
version = "0.3.0"
3+
version = "0.4.0"
44
authors.workspace = true
55
edition.workspace = true
66
license.workspace = true
@@ -28,7 +28,7 @@ itoa = "1.0.2"
2828
percent-encoding = "2.1.0"
2929
bytes.workspace = true
3030
prost = "0.12.0"
31-
base64 = "0.21.0"
31+
base64.workspace = true
3232
prost-types = "0.12.0"
3333
tokio-stream = { workspace = true, features = ["sync"] }
3434
serde = { workspace = true, optional = true }

0 commit comments

Comments
 (0)