├── poem
├── .gitignore
├── src
│ ├── route
│ │ ├── internal
│ │ │ └── mod.rs
│ │ └── mod.rs
│ ├── listener
│ │ ├── certs
│ │ │ ├── identity.p12
│ │ │ ├── openssl.cnf
│ │ │ └── cert1.pem
│ │ ├── tls.rs
│ │ └── acme
│ │ │ ├── mod.rs
│ │ │ └── keypair.rs
│ ├── endpoint
│ │ ├── to_response.rs
│ │ ├── map_to_response.rs
│ │ ├── before.rs
│ │ ├── after.rs
│ │ ├── map.rs
│ │ ├── and_then.rs
│ │ ├── around.rs
│ │ ├── inspect_all_err.rs
│ │ ├── catch_all_error.rs
│ │ ├── inspect_err.rs
│ │ ├── catch_error.rs
│ │ └── mod.rs
│ ├── session
│ │ ├── mod.rs
│ │ └── session_storage.rs
│ └── web
│ │ └── addr.rs
└── LICENSE-MIT
├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── question.md
│ ├── feature_request.md
│ └── bug_report.md
├── dependabot.yml
└── workflows
│ └── code-coverage.yml
├── examples
├── poem
│ ├── static-files
│ │ ├── files
│ │ │ ├── #a.txt
│ │ │ ├── 你好.txt
│ │ │ ├── 文件
│ │ │ │ ├── a
│ │ │ │ │ └── a.txt
│ │ │ │ ├── 你好.txt
│ │ │ │ └── poem-logo.jpg
│ │ │ ├── images
│ │ │ │ └── poem-logo.jpg
│ │ │ ├── subpage
│ │ │ │ ├── res
│ │ │ │ │ └── poem-logo.jpg
│ │ │ │ └── index.html
│ │ │ └── index.html
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── tera-templating
│ │ ├── templates
│ │ │ └── index.html.tera
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── worker-hello-world
│ │ ├── .gitignore
│ │ ├── wrangler.toml
│ │ ├── README.md
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── lib.rs
│ ├── i18n
│ │ ├── resources
│ │ │ ├── zh-CN
│ │ │ │ └── simple.ftl
│ │ │ ├── en-US
│ │ │ │ └── simple.ftl
│ │ │ └── fr
│ │ │ │ └── simple.ftl
│ │ └── Cargo.toml
│ ├── opentelemetry-jaeger
│ │ ├── jaeger.png
│ │ ├── README.md
│ │ └── Cargo.toml
│ ├── embed-files
│ │ ├── files
│ │ │ ├── images
│ │ │ │ └── poem-logo.jpg
│ │ │ └── index.html
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── add-data
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── basic-auth
│ │ └── Cargo.toml
│ ├── catch-panic
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── handling-404
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── hello-world
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── middleware
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── unix-socket
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── middleware_fn
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── nested-routing
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── tls
│ │ └── Cargo.toml
│ ├── combined-listeners
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── upload
│ │ └── Cargo.toml
│ ├── custom-error
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── acme-alpn-01
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── acme-http-01
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── requestid
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── cookie-session
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── csrf
│ │ └── Cargo.toml
│ ├── custom-extractor
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── auth
│ │ └── Cargo.toml
│ ├── json
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── local-server-with-browser
│ │ └── Cargo.toml
│ ├── tokio-metrics
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── async-graphql
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── tls-reload
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ ├── main.rs
│ │ │ └── cert.pem
│ ├── acme-expanded-http-01
│ │ └── Cargo.toml
│ ├── websocket-chat
│ │ └── Cargo.toml
│ ├── lambda-hello-world
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── sse
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── mongodb
│ │ ├── Cargo.toml
│ │ └── README.md
│ ├── graceful-shutdown
│ │ └── Cargo.toml
│ ├── tower-layer
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ └── redis-session
│ │ ├── Cargo.toml
│ │ └── src
│ │ └── main.rs
├── openapi
│ ├── custom-payload
│ │ ├── data.bcs
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ └── src
│ │ │ └── main.rs
│ ├── todos
│ │ ├── .gitignore
│ │ ├── migrations
│ │ │ └── 20211218110925_todos.sql
│ │ ├── Cargo.toml
│ │ └── README.md
│ ├── log-with-operation-id
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── union
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── generics
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── auth-basic
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── hello-world
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── combined-apis
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── poem-extractor
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── poem-middleware
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── uniform-response
│ │ └── Cargo.toml
│ ├── upload
│ │ └── Cargo.toml
│ ├── sse
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ ├── content-type-accept
│ │ ├── Cargo.toml
│ │ └── README.md
│ ├── users-crud
│ │ └── Cargo.toml
│ ├── auth-apikey
│ │ └── Cargo.toml
│ ├── auth-multiple
│ │ └── Cargo.toml
│ └── auth-github
│ │ └── Cargo.toml
├── .gitignore
├── disabled
│ └── tonic
│ │ ├── build.rs
│ │ ├── proto
│ │ └── helloworld.proto
│ │ ├── Cargo.toml
│ │ └── src
│ │ ├── client.rs
│ │ └── main.rs
├── grpc
│ ├── helloworld
│ │ ├── build.rs
│ │ ├── Cargo.toml
│ │ ├── src
│ │ │ ├── client.rs
│ │ │ └── main.rs
│ │ └── proto
│ │ │ └── helloworld.proto
│ ├── routeguide
│ │ ├── build.rs
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── data.rs
│ ├── helloworld_compressed
│ │ ├── build.rs
│ │ ├── Cargo.toml
│ │ ├── src
│ │ │ ├── client.rs
│ │ │ └── main.rs
│ │ └── proto
│ │ │ └── helloworld.proto
│ ├── helloworld_typename
│ │ ├── build.rs
│ │ ├── Cargo.toml
│ │ ├── src
│ │ │ └── main.rs
│ │ └── proto
│ │ │ └── helloworld.proto
│ ├── reflection
│ │ ├── build.rs
│ │ ├── Cargo.toml
│ │ ├── proto
│ │ │ └── helloworld.proto
│ │ └── src
│ │ │ └── main.rs
│ ├── jsoncodec
│ │ ├── build.rs
│ │ ├── Cargo.toml
│ │ ├── src
│ │ │ └── main.rs
│ │ └── proto
│ │ │ └── helloworld.proto
│ └── middleware
│ │ ├── build.rs
│ │ ├── Cargo.toml
│ │ ├── src
│ │ ├── client.rs
│ │ ├── main.rs
│ │ └── middleware.rs
│ │ └── proto
│ │ └── helloworld.proto
├── mcpserver
│ ├── counter
│ │ ├── Cargo.toml
│ │ └── src
│ │ │ └── main.rs
│ └── counter-streamable-http
│ │ ├── Cargo.toml
│ │ └── src
│ │ └── main.rs
└── Cargo.toml
├── logo.png
├── favicon.ico
├── .gitignore
├── poem-openapi
├── assets
│ └── swagger-ui.jpg
├── src
│ ├── types
│ │ ├── external
│ │ │ ├── prost_wkt_types
│ │ │ │ └── mod.rs
│ │ │ ├── mod.rs
│ │ │ └── sqlx.rs
│ │ └── multipart
│ │ │ └── mod.rs
│ ├── response
│ │ └── mod.rs
│ ├── ui
│ │ ├── rapidoc
│ │ │ └── oauth-receiver.html
│ │ ├── mod.rs
│ │ ├── stoplight_elements
│ │ │ ├── mod.rs
│ │ │ └── stoplight-elements.html
│ │ ├── scalar
│ │ │ └── mod.rs
│ │ ├── openapi_explorer
│ │ │ └── mod.rs
│ │ └── redoc
│ │ │ └── mod.rs
│ ├── param
│ │ └── mod.rs
│ ├── validation
│ │ ├── max_length.rs
│ │ ├── multiple_of.rs
│ │ ├── min_length.rs
│ │ ├── max_items.rs
│ │ ├── min_items.rs
│ │ ├── pattern.rs
│ │ ├── unique_items.rs
│ │ ├── mod.rs
│ │ ├── maximum.rs
│ │ ├── minimum.rs
│ │ ├── max_properties.rs
│ │ └── min_properties.rs
│ ├── docs
│ │ ├── request.md
│ │ ├── response_content.md
│ │ ├── newtype.md
│ │ ├── oauth_scopes.md
│ │ └── tags.md
│ ├── auth
│ │ ├── bearer.rs
│ │ ├── basic.rs
│ │ └── api_key.rs
│ └── path_util.rs
└── LICENSE-MIT
├── poem-grpc
├── src
│ ├── example_generated
│ │ └── mod.rs
│ ├── macros.rs
│ ├── streaming.rs
│ ├── route.rs
│ ├── service.rs
│ └── lib.rs
├── proto
│ ├── health.proto
│ └── test_harness.proto
├── build.rs
├── LICENSE-MIT
└── CHANGELOG.md
├── poem-worker
├── src
│ ├── lib.rs
│ ├── context.rs
│ └── body.rs
└── Cargo.toml
├── .tarpaulin.toml
├── .rustfmt.toml
├── poem-mcpserver
├── src
│ ├── protocol
│ │ ├── mod.rs
│ │ ├── resources.rs
│ │ └── content.rs
│ └── lib.rs
├── CHANGELOG.md
└── Cargo.toml
├── poem-mcpserver-macros
├── Cargo.toml
└── src
│ └── lib.rs
├── poem-derive
├── src
│ └── utils.rs
├── Cargo.toml
└── LICENSE-MIT
├── poem-grpc-build
├── src
│ ├── utils.rs
│ ├── service_generator.rs
│ └── lib.rs
├── Cargo.toml
└── LICENSE-MIT
├── poem-openapi-derive
├── src
│ ├── error.rs
│ └── parameter_style.rs
├── Cargo.toml
└── LICENSE-MIT
├── poem-lambda
├── Cargo.toml
├── LICENSE-MIT
└── CHANGELOG.md
├── SECURITY.md
└── LICENSE-MIT
/poem/.gitignore:
--------------------------------------------------------------------------------
1 | test-socket
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: sunli829
2 |
--------------------------------------------------------------------------------
/examples/poem/static-files/files/#a.txt:
--------------------------------------------------------------------------------
1 | #a
--------------------------------------------------------------------------------
/examples/poem/static-files/files/你好.txt:
--------------------------------------------------------------------------------
1 | 你好!
--------------------------------------------------------------------------------
/examples/poem/static-files/files/文件/a/a.txt:
--------------------------------------------------------------------------------
1 | abc
--------------------------------------------------------------------------------
/examples/poem/static-files/files/文件/你好.txt:
--------------------------------------------------------------------------------
1 | 你好!
--------------------------------------------------------------------------------
/examples/openapi/custom-payload/data.bcs:
--------------------------------------------------------------------------------
1 | JohnDoe
--------------------------------------------------------------------------------
/examples/openapi/todos/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | todos.db*
3 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poem-web/poem/HEAD/logo.png
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poem-web/poem/HEAD/favicon.ico
--------------------------------------------------------------------------------
/examples/poem/tera-templating/templates/index.html.tera:
--------------------------------------------------------------------------------
1 |
Hello {{ name }}
--------------------------------------------------------------------------------
/poem/src/route/internal/mod.rs:
--------------------------------------------------------------------------------
1 | pub(crate) mod radix_tree;
2 | pub(crate) mod trie;
3 |
--------------------------------------------------------------------------------
/examples/poem/worker-hello-world/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | node_modules
3 | .wrangler
4 | build
--------------------------------------------------------------------------------
/examples/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | Cargo.lock
3 | .idea
4 | .DS_Store
5 | docs/gh-pages
6 | docs/book
--------------------------------------------------------------------------------
/examples/poem/i18n/resources/zh-CN/simple.ftl:
--------------------------------------------------------------------------------
1 | hello-world = 你好世界!
2 | welcome = 欢迎 { $name }!
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | Cargo.lock
3 | .idea
4 | .vscode
5 | .DS_Store
6 | docs/gh-pages
7 | docs/book
--------------------------------------------------------------------------------
/examples/poem/i18n/resources/en-US/simple.ftl:
--------------------------------------------------------------------------------
1 | hello-world = Hello world!
2 | welcome = welcome { $name }!
3 |
--------------------------------------------------------------------------------
/examples/poem/i18n/resources/fr/simple.ftl:
--------------------------------------------------------------------------------
1 | hello-world = Bonjour le monde!
2 | welcome = Bienvenue { $name }!
3 |
--------------------------------------------------------------------------------
/poem-openapi/assets/swagger-ui.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poem-web/poem/HEAD/poem-openapi/assets/swagger-ui.jpg
--------------------------------------------------------------------------------
/poem/src/listener/certs/identity.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poem-web/poem/HEAD/poem/src/listener/certs/identity.p12
--------------------------------------------------------------------------------
/poem-openapi/src/types/external/prost_wkt_types/mod.rs:
--------------------------------------------------------------------------------
1 | mod duration;
2 | mod r#struct;
3 | mod timestamp;
4 | mod value;
5 |
--------------------------------------------------------------------------------
/poem-openapi/src/response/mod.rs:
--------------------------------------------------------------------------------
1 | //! Commonly used response types.
2 |
3 | #[cfg(feature = "static-files")]
4 | mod static_file;
5 |
--------------------------------------------------------------------------------
/examples/poem/opentelemetry-jaeger/jaeger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poem-web/poem/HEAD/examples/poem/opentelemetry-jaeger/jaeger.png
--------------------------------------------------------------------------------
/examples/poem/static-files/files/文件/poem-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poem-web/poem/HEAD/examples/poem/static-files/files/文件/poem-logo.jpg
--------------------------------------------------------------------------------
/examples/poem/embed-files/files/images/poem-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poem-web/poem/HEAD/examples/poem/embed-files/files/images/poem-logo.jpg
--------------------------------------------------------------------------------
/examples/poem/static-files/files/images/poem-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poem-web/poem/HEAD/examples/poem/static-files/files/images/poem-logo.jpg
--------------------------------------------------------------------------------
/examples/poem/static-files/files/subpage/res/poem-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poem-web/poem/HEAD/examples/poem/static-files/files/subpage/res/poem-logo.jpg
--------------------------------------------------------------------------------
/poem-openapi/src/types/multipart/mod.rs:
--------------------------------------------------------------------------------
1 | //! Multipart related types.
2 |
3 | mod json;
4 | mod upload;
5 |
6 | pub use json::JsonField;
7 | pub use upload::Upload;
8 |
--------------------------------------------------------------------------------
/examples/disabled/tonic/build.rs:
--------------------------------------------------------------------------------
1 | fn main() -> Result<(), Box> {
2 | tonic_build::compile_protos("proto/helloworld.proto")?;
3 | Ok(())
4 | }
5 |
--------------------------------------------------------------------------------
/examples/poem/worker-hello-world/wrangler.toml:
--------------------------------------------------------------------------------
1 | name = "worker-hello-world"
2 | main = "build/worker/shim.mjs"
3 | compatibility_date = "2025-07-20"
4 |
5 | [build]
6 | command = "worker-build --release"
7 |
--------------------------------------------------------------------------------
/examples/grpc/helloworld/build.rs:
--------------------------------------------------------------------------------
1 | use std::io::Result;
2 |
3 | use poem_grpc_build::compile_protos;
4 |
5 | fn main() -> Result<()> {
6 | compile_protos(&["./proto/helloworld.proto"], &["./proto"])
7 | }
8 |
--------------------------------------------------------------------------------
/examples/grpc/routeguide/build.rs:
--------------------------------------------------------------------------------
1 | use std::io::Result;
2 |
3 | use poem_grpc_build::Config;
4 |
5 | fn main() -> Result<()> {
6 | Config::new().compile(&["./proto/routeguide.proto"], &["./proto"])
7 | }
8 |
--------------------------------------------------------------------------------
/examples/grpc/helloworld_compressed/build.rs:
--------------------------------------------------------------------------------
1 | use std::io::Result;
2 |
3 | use poem_grpc_build::compile_protos;
4 |
5 | fn main() -> Result<()> {
6 | compile_protos(&["./proto/helloworld.proto"], &["./proto"])
7 | }
8 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 'Question'
3 | about: 'If something needs clarification'
4 | title: ''
5 | labels: question
6 | ---
7 |
8 |
--------------------------------------------------------------------------------
/poem-openapi/src/ui/rapidoc/oauth-receiver.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/poem-grpc/src/example_generated/mod.rs:
--------------------------------------------------------------------------------
1 | //! This module shows an example of code generated by the macro. **IT MUST NOT
2 | //! BE USED OUTSIDE THIS CRATE**.
3 |
4 | #![allow(missing_docs)]
5 |
6 | include!(concat!(env!("OUT_DIR"), "/routeguide.rs"));
7 |
--------------------------------------------------------------------------------
/examples/openapi/todos/migrations/20211218110925_todos.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS todos
2 | (
3 | id INTEGER PRIMARY KEY NOT NULL,
4 | description TEXT NOT NULL,
5 | done BOOLEAN NOT NULL DEFAULT 0
6 | );
--------------------------------------------------------------------------------
/poem-worker/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub(crate) mod body;
2 | pub(crate) mod req;
3 |
4 | mod cloudflare;
5 | pub use cloudflare::*;
6 |
7 | mod env;
8 | pub use env::*;
9 |
10 | mod context;
11 | pub use context::*;
12 |
13 | mod server;
14 | pub use server::*;
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 'Feature Request'
3 | about: 'Report a new feature to be implemented'
4 | title: ''
5 | labels: enhancement
6 | ---
7 |
8 | ## Description of the feature
9 |
10 |
11 | ## Code example (if possible)
--------------------------------------------------------------------------------
/.tarpaulin.toml:
--------------------------------------------------------------------------------
1 | [all]
2 | workspace = true
3 | avoid_cfg_tarpaulin = true
4 | all-features = true
5 | exclude = []
6 | exclude-files = [
7 | "examples/**/*",
8 | "poem-derive/**/*",
9 | "poem-openapi-derive/**/*",
10 | "poem-grpc-build/**/*",
11 | ]
12 |
--------------------------------------------------------------------------------
/examples/grpc/helloworld_typename/build.rs:
--------------------------------------------------------------------------------
1 | use std::io::Result;
2 |
3 | use poem_grpc_build::Config;
4 |
5 | fn main() -> Result<()> {
6 | Config::new()
7 | .enable_type_names()
8 | .compile(&["./proto/helloworld.proto"], &["./proto"])
9 | }
10 |
--------------------------------------------------------------------------------
/examples/poem/worker-hello-world/README.md:
--------------------------------------------------------------------------------
1 | # Poem with Cloudflare worker
2 |
3 | ## Prequirement
4 |
5 | - [worker-build](https://github.com/cloudflare/workers-rs/tree/main/worker-build)
6 | - [wranger](https://developers.cloudflare.com/workers/wrangler/install-and-update/)
7 |
--------------------------------------------------------------------------------
/examples/grpc/reflection/build.rs:
--------------------------------------------------------------------------------
1 | use std::io::Result;
2 |
3 | use poem_grpc_build::Config;
4 |
5 | fn main() -> Result<()> {
6 | Config::new()
7 | .file_descriptor_set_path("helloworld.bin")
8 | .compile(&["./proto/helloworld.proto"], &["./proto"])
9 | }
10 |
--------------------------------------------------------------------------------
/examples/disabled/tonic/proto/helloworld.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package helloworld;
4 |
5 | message HelloRequest {
6 | string name = 1;
7 | }
8 |
9 | message HelloReply {
10 | string message = 1;
11 | }
12 |
13 | service Greeter {
14 | rpc SayHello (HelloRequest) returns (HelloReply) {}
15 | }
16 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Please see the documentation for all configuration options:
2 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
3 |
4 | version: 2
5 | updates:
6 | - package-ecosystem: "cargo"
7 | directory: "/"
8 | schedule:
9 | interval: "weekly"
--------------------------------------------------------------------------------
/examples/poem/add-data/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-add-data"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
--------------------------------------------------------------------------------
/examples/poem/static-files/files/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello world
6 |
7 |
8 | Poem Web Framework
9 |
10 |
11 |
--------------------------------------------------------------------------------
/examples/poem/tera-templating/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-tera-templating"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["full"] }
10 | tera = "1.17.1"
11 | once_cell = "1.17.0"
12 |
--------------------------------------------------------------------------------
/.rustfmt.toml:
--------------------------------------------------------------------------------
1 | edition = "2021"
2 | newline_style = "unix"
3 | # comments
4 | normalize_comments = true
5 | wrap_comments = true
6 | format_code_in_doc_comments = true
7 | # imports
8 | imports_granularity = "Crate"
9 | group_imports = "StdExternalCrate"
10 | # report
11 | #report_fixme="Unnumbered"
12 | #report_todo="Unnumbered"
13 |
--------------------------------------------------------------------------------
/examples/poem/basic-auth/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-basic-auth"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/catch-panic/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-catch-unwind"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/handling-404/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-handling-404"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/hello-world/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-hello-world"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/middleware/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-middleware"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/unix-socket/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-unix-socket"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/mcpserver/counter/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "counter"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | poem-mcpserver.workspace = true
8 | serde = { version = "1.0.219", features = ["derive"] }
9 | schemars = "1.0"
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] }
11 |
--------------------------------------------------------------------------------
/examples/poem/embed-files/files/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello world
6 |
7 |
8 | Poem Web Framework
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/poem/middleware_fn/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-middleware-fn"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/nested-routing/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-nested-routing"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/static-files/files/subpage/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello world
6 |
7 |
8 | Poem Web Framework
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/poem/tls/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-tls"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["rustls"]}
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/poem-openapi/src/param/mod.rs:
--------------------------------------------------------------------------------
1 | //! Parameter types for the API operation.
2 | #[cfg(feature = "cookie")]
3 | mod cookie;
4 | mod header;
5 | mod path;
6 | mod query;
7 |
8 | #[cfg(feature = "cookie")]
9 | pub use cookie::{Cookie, CookiePrivate, CookieSigned};
10 | pub use header::Header;
11 | pub use path::Path;
12 | pub use query::Query;
13 |
--------------------------------------------------------------------------------
/examples/poem/combined-listeners/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-combined-listeners"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/i18n/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-i18n"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["i18n"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/upload/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-upload"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["multipart"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/grpc/jsoncodec/build.rs:
--------------------------------------------------------------------------------
1 | use std::io::Result;
2 |
3 | use poem_grpc_build::Config;
4 |
5 | fn main() -> Result<()> {
6 | Config::new()
7 | .codec("::poem_grpc::codec::JsonCodec")
8 | .type_attribute(".", "#[derive(serde::Deserialize, serde::Serialize)]")
9 | .compile(&["./proto/helloworld.proto"], &["./proto"])
10 | }
11 |
--------------------------------------------------------------------------------
/examples/openapi/log-with-operation-id/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-log-with-operation-id"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 |
--------------------------------------------------------------------------------
/examples/poem/custom-error/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-custom-error"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 | thiserror = "2.0"
12 |
--------------------------------------------------------------------------------
/examples/grpc/middleware/build.rs:
--------------------------------------------------------------------------------
1 | use std::io::Result;
2 |
3 | use poem_grpc_build::Config;
4 |
5 | fn main() -> Result<()> {
6 | Config::new()
7 | .client_middleware("crate::middleware::ClientMiddleware")
8 | .server_middleware("crate::middleware::ServerMiddleware")
9 | .compile(&["./proto/helloworld.proto"], &["./proto"])
10 | }
11 |
--------------------------------------------------------------------------------
/examples/poem/acme-alpn-01/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-acme-alpn-01"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["acme"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/acme-http-01/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-acme-http-01"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["acme"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/requestid/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-requestid"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["requestid"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 'Bug Report'
3 | about: 'Report a new bug'
4 | title: ''
5 | labels: bug
6 | ---
7 |
8 | ## Expected Behavior
9 |
10 |
11 | ## Actual Behavior
12 |
13 |
14 | ## Steps to Reproduce the Problem
15 |
16 | 1.
17 | 2.
18 | 3.
19 |
20 | ## Specifications
21 |
22 | - Version:
23 | - Platform:
24 | - Subsystem:
--------------------------------------------------------------------------------
/examples/openapi/union/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-union"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/poem/cookie-session/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-cookie-session"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["session"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/poem/static-files/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-static-files"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["static-files"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/openapi/generics/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-generics"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/poem/csrf/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-csrf"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["csrf"] }
9 | serde.workspace = true
10 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/poem/custom-extractor/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-custom-extractor"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | serde.workspace = true
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/openapi/auth-basic/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-auth-basic"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/openapi/hello-world/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-hello-world"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/poem/auth/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-auth"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["session"] }
9 | serde.workspace = true
10 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/poem/json/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-json"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | serde.workspace = true
11 | serde_json.workspace = true
12 | tracing-subscriber.workspace = true
13 |
--------------------------------------------------------------------------------
/examples/poem/local-server-with-browser/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "local-server-with-browser"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | open.workspace = true
9 | poem.workspace = true
10 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/openapi/combined-apis/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-combined-apis"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/openapi/poem-extractor/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-poem-extractor"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/poem/embed-files/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-embed-files"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["embed"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 | rust-embed = "8.0"
12 |
--------------------------------------------------------------------------------
/examples/poem/tokio-metrics/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-tokio-metrics"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["tokio-metrics"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros", "time"] }
10 | tracing-subscriber.workspace = true
11 |
--------------------------------------------------------------------------------
/examples/openapi/poem-middleware/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-poem-middleware"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/poem/async-graphql/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-async-graphql"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | async-graphql = "7.0.7"
11 | slab = "0.4.4"
12 | tracing-subscriber.workspace = true
13 |
--------------------------------------------------------------------------------
/examples/poem/tls-reload/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-tls-reload"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | async-stream = "0.3.2"
9 | poem = { workspace = true, features = ["rustls"]}
10 | tokio = { workspace = true, features = ["rt-multi-thread", "macros", "time"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/openapi/uniform-response/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-uniform-response"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/poem/acme-expanded-http-01/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-acme-expanded-http-01"
3 | version = "0.1.0"
4 | edition = "2021"
5 | publish = false
6 |
7 | [dependencies]
8 | poem = { path = "../../../poem", features = ["acme"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber = { version = "0.3.9", features = ["env-filter"] }
11 |
--------------------------------------------------------------------------------
/examples/poem/websocket-chat/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-websocket-chat"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["websocket"]}
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | futures-util.workspace = true
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/openapi/upload/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-upload"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["multipart", "tempfile"] }
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 | tracing-subscriber.workspace = true
--------------------------------------------------------------------------------
/examples/poem/lambda-hello-world/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-lambda-hello-world"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { path = "../../../poem", default-features = false }
9 | poem-lambda.workspace = true
10 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
11 | tracing-subscriber.workspace = true
--------------------------------------------------------------------------------
/examples/poem/sse/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-sse"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["sse"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | futures-util.workspace = true
11 | tokio-stream.workspace = true
12 | tracing-subscriber.workspace = true
13 |
--------------------------------------------------------------------------------
/examples/poem/mongodb/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-mongodb"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | serde.workspace = true
11 | serde_json.workspace = true
12 | mongodb = "2"
13 | futures = "0.3"
14 | tracing-subscriber.workspace = true
15 |
--------------------------------------------------------------------------------
/poem-openapi/src/ui/mod.rs:
--------------------------------------------------------------------------------
1 | #[cfg(feature = "openapi-explorer")]
2 | pub(crate) mod openapi_explorer;
3 | #[cfg(feature = "rapidoc")]
4 | pub(crate) mod rapidoc;
5 | #[cfg(feature = "redoc")]
6 | pub(crate) mod redoc;
7 | #[cfg(feature = "scalar")]
8 | pub(crate) mod scalar;
9 | #[cfg(feature = "stoplight-elements")]
10 | pub(crate) mod stoplight_elements;
11 | #[cfg(feature = "swagger-ui")]
12 | pub(crate) mod swagger_ui;
13 |
--------------------------------------------------------------------------------
/examples/openapi/custom-payload/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-custom-payload"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | bcs = "0.1.3"
9 | mime.workspace = true
10 | poem.workspace = true
11 | poem-openapi.workspace = true
12 | serde.workspace = true
13 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] }
14 |
15 |
--------------------------------------------------------------------------------
/examples/openapi/sse/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-sse"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | async-stream = "0.3.2"
9 | futures-util.workspace = true
10 | poem.workspace = true
11 | poem-openapi.workspace = true
12 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] }
13 | tracing-subscriber.workspace = true
14 |
--------------------------------------------------------------------------------
/examples/openapi/todos/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "poem-todos"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | sqlx = { version = "0.8.3", features = ["runtime-tokio-rustls", "sqlite"] }
11 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
12 | tokio-stream.workspace = true
13 |
--------------------------------------------------------------------------------
/examples/openapi/content-type-accept/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-content-type-accept"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | bcs = "0.1.3"
9 | mime.workspace = true
10 | poem.workspace = true
11 | poem-openapi.workspace = true
12 | serde.workspace = true
13 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] }
14 |
--------------------------------------------------------------------------------
/examples/grpc/helloworld_typename/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-grpc-helloworld-typename"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-grpc.workspace = true
10 | prost.workspace = true
11 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
12 |
13 | [build-dependencies]
14 | poem-grpc-build.workspace = true
15 |
--------------------------------------------------------------------------------
/examples/poem/worker-hello-world/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "examples-worker-hello-world"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [workspace]
7 |
8 | [package.metadata.release]
9 | release = false
10 |
11 | [lib]
12 | crate-type = ["cdylib"]
13 |
14 | [dependencies]
15 | worker = { version = "0.6.0" }
16 | poem = { path = "../../../poem", default-features = false }
17 | poem-worker = { path = "../../../poem-worker" }
18 |
--------------------------------------------------------------------------------
/examples/openapi/users-crud/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-users-crud"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi = { workspace = true, features = ["swagger-ui", "email"] }
10 | slab = "0.4.4"
11 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] }
12 | tracing-subscriber.workspace = true
13 |
--------------------------------------------------------------------------------
/examples/poem/graceful-shutdown/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-graceful-shutdown"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["sse"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal"] }
10 | futures-util.workspace = true
11 | tokio-stream.workspace = true
12 | tracing-subscriber.workspace = true
13 |
--------------------------------------------------------------------------------
/examples/poem/tower-layer/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-tower-layer"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["tower-compat"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tower = { version = "0.4.8", default-features = false, features = ["limit"] }
11 | tracing-subscriber.workspace = true
12 |
--------------------------------------------------------------------------------
/examples/poem/worker-hello-world/src/lib.rs:
--------------------------------------------------------------------------------
1 | use poem::{get, handler, web::Path, Route};
2 | use poem_worker::{CloudflareProperties, Server};
3 | use worker::event;
4 |
5 | #[handler]
6 | fn hello(Path(name): Path, _cf: CloudflareProperties) -> String {
7 | format!("hello: {}", name)
8 | }
9 |
10 | #[event(start)]
11 | fn start() {
12 | let app = Route::new().at("/hello/:name", get(hello));
13 |
14 | Server::new().run(app);
15 | }
16 |
--------------------------------------------------------------------------------
/examples/openapi/auth-apikey/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-auth-apikey"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | jwt = "0.15.0"
9 | poem.workspace = true
10 | poem-openapi.workspace = true
11 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
12 | tracing-subscriber.workspace = true
13 | hmac = "0.11"
14 | sha2 = "0.9"
15 | serde.workspace = true
16 |
--------------------------------------------------------------------------------
/examples/grpc/reflection/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-grpc-reflection"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-grpc.workspace = true
10 | prost.workspace = true
11 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
12 | tracing-subscriber.workspace = true
13 |
14 | [build-dependencies]
15 | poem-grpc-build.workspace = true
16 |
--------------------------------------------------------------------------------
/examples/openapi/auth-multiple/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-auth-multiple"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | jwt = "0.15.0"
9 | poem.workspace = true
10 | poem-openapi.workspace = true
11 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
12 | tracing-subscriber.workspace = true
13 | hmac = "0.11"
14 | sha2 = "0.9"
15 | serde.workspace = true
16 |
--------------------------------------------------------------------------------
/poem-mcpserver/src/protocol/mod.rs:
--------------------------------------------------------------------------------
1 | //! The protocol module contains all the necessary components to implement the
2 | //! MCP protocol.
3 |
4 | pub mod content;
5 | pub mod initialize;
6 | pub mod prompts;
7 | pub mod resources;
8 | pub mod rpc;
9 | pub mod tool;
10 |
11 | /// The JSON-RPC version.
12 | pub const JSON_RPC_VERSION: &str = "2.0";
13 |
14 | /// The MCP protocol version.
15 | pub const MCP_PROTOCOL_VERSION: time::Date = time::macros::date!(2025 - 06 - 18);
16 |
--------------------------------------------------------------------------------
/examples/openapi/auth-github/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-openapi-auth-github"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-openapi.workspace = true
10 | tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
11 | reqwest = { version = "0.12.2", default-features = false, features = [
12 | "rustls-tls",
13 | ] }
14 | tracing-subscriber.workspace = true
15 |
--------------------------------------------------------------------------------
/examples/mcpserver/counter-streamable-http/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "counter-streamable-http"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | poem-mcpserver = { workspace = true, features = ["streamable-http"] }
8 | serde = { version = "1.0.219", features = ["derive"] }
9 | schemars = "1.0"
10 | poem = { workspace = true, features = ["sse"] }
11 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync"] }
12 | tracing-subscriber.workspace = true
13 |
--------------------------------------------------------------------------------
/examples/poem/redis-session/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-redis-session"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["redis-session"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | tracing-subscriber.workspace = true
11 | redis = { version = "0.32", features = [
12 | "aio",
13 | "tokio-comp",
14 | "connection-manager",
15 | ] }
16 |
--------------------------------------------------------------------------------
/poem-openapi/src/ui/stoplight_elements/mod.rs:
--------------------------------------------------------------------------------
1 | use poem::{Endpoint, endpoint::make_sync, web::Html};
2 |
3 | const TEMPLATE: &str = include_str!("stoplight-elements.html");
4 |
5 | pub(crate) fn create_html(document: &str) -> String {
6 | TEMPLATE.replace("'{:spec}'", document)
7 | }
8 |
9 | pub(crate) fn create_endpoint(document: String) -> impl Endpoint {
10 | let ui_html = create_html(&document);
11 | poem::Route::new().at("/", make_sync(move |_| Html(ui_html.clone())))
12 | }
13 |
--------------------------------------------------------------------------------
/examples/grpc/helloworld/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-grpc-helloworld"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-grpc.workspace = true
10 | prost.workspace = true
11 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
12 |
13 | [build-dependencies]
14 | poem-grpc-build.workspace = true
15 |
16 | [[bin]]
17 | name = "grpc-helloworld-client"
18 | path = "src/client.rs"
19 |
--------------------------------------------------------------------------------
/examples/grpc/middleware/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-grpc-middleware"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-grpc.workspace = true
10 | prost.workspace = true
11 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
12 |
13 | [build-dependencies]
14 | poem-grpc-build.workspace = true
15 |
16 | [[bin]]
17 | name = "grpc-middleware-client"
18 | path = "src/client.rs"
19 |
--------------------------------------------------------------------------------
/examples/grpc/helloworld_typename/src/main.rs:
--------------------------------------------------------------------------------
1 | use prost::Name;
2 |
3 | poem_grpc::include_proto!("helloworld");
4 |
5 | fn main() -> Result<(), std::io::Error> {
6 | println!(
7 | "HelloRequest has {} full name and {} type url",
8 | HelloRequest::full_name(),
9 | HelloRequest::type_url()
10 | );
11 | println!(
12 | "HelloReply has {} full name and {} type url",
13 | HelloReply::full_name(),
14 | HelloReply::type_url()
15 | );
16 |
17 | Ok(())
18 | }
19 |
--------------------------------------------------------------------------------
/examples/grpc/jsoncodec/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-grpc-jsoncodec"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-grpc = { workspace = true, features = ["json-codec"] }
10 | prost.workspace = true
11 | serde.workspace = true
12 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
13 | tracing-subscriber.workspace = true
14 |
15 | [build-dependencies]
16 | poem-grpc-build.workspace = true
17 |
--------------------------------------------------------------------------------
/poem-grpc/src/macros.rs:
--------------------------------------------------------------------------------
1 | /// Include generated server and client types.
2 | #[macro_export]
3 | macro_rules! include_proto {
4 | ($package: tt) => {
5 | include!(concat!(env!("OUT_DIR"), concat!("/", $package, ".rs")));
6 | };
7 | }
8 |
9 | /// Include an encoded `prost_types::FileDescriptorSet` as a `&'static [u8]`.
10 | #[macro_export]
11 | macro_rules! include_file_descriptor_set {
12 | ($package: tt) => {
13 | include_bytes!(concat!(env!("OUT_DIR"), concat!("/", $package)))
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/poem/src/listener/tls.rs:
--------------------------------------------------------------------------------
1 | use std::io::Result as IoResult;
2 |
3 | use futures_util::Stream;
4 |
5 | /// Represents a type that can convert into tls config stream.
6 | #[cfg(any(feature = "rustls", feature = "native-tls", feature = "openssl-tls"))]
7 | pub trait IntoTlsConfigStream: Send + 'static {
8 | /// Represents a tls config stream.
9 | type Stream: Stream- + Send + 'static;
10 |
11 | /// Consume itself and return tls config stream.
12 | fn into_stream(self) -> IoResult;
13 | }
14 |
--------------------------------------------------------------------------------
/examples/openapi/todos/README.md:
--------------------------------------------------------------------------------
1 | # TODOs Example
2 |
3 | ## Setup
4 |
5 | 1. Install sqlx-cli
6 |
7 | ```bash
8 | cargo install sqlx-cli --no-default-features --features sqlite
9 | ```
10 |
11 | 2. Declare the database URL
12 |
13 | ```bash
14 | export DATABASE_URL="sqlite:todos.db"
15 | ```
16 |
17 | 3. Create the database
18 |
19 | ```bash
20 | sqlx db create
21 | ```
22 |
23 | 4. Run sql migrations
24 |
25 | ```bash
26 | sqlx migrate run
27 | ```
28 |
29 | 5. Start the server
30 |
31 | ```bash
32 | cargo run
33 | ```
34 |
--------------------------------------------------------------------------------
/poem-grpc/proto/health.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grpc.health.v1;
4 |
5 | message HealthCheckRequest { string service = 1; }
6 |
7 | message HealthCheckResponse {
8 | enum ServingStatus {
9 | UNKNOWN = 0;
10 | SERVING = 1;
11 | NOT_SERVING = 2;
12 | SERVICE_UNKNOWN = 3; // Used only by the Watch method.
13 | }
14 | ServingStatus status = 1;
15 | }
16 |
17 | service Health {
18 | rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
19 |
20 | rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
21 | }
--------------------------------------------------------------------------------
/examples/grpc/routeguide/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-grpc-routeguide"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | async-stream = "0.3.3"
9 | futures-util.workspace = true
10 | poem.workspace = true
11 | poem-grpc.workspace = true
12 | prost.workspace = true
13 | serde.workspace = true
14 | serde_json.workspace = true
15 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
16 | tracing-subscriber.workspace = true
17 |
18 | [build-dependencies]
19 | poem-grpc-build.workspace = true
20 |
--------------------------------------------------------------------------------
/poem-mcpserver-macros/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "poem-mcpserver-macros"
3 | version = "0.3.1"
4 | authors.workspace = true
5 | edition.workspace = true
6 | license.workspace = true
7 | documentation.workspace = true
8 | homepage.workspace = true
9 | repository.workspace = true
10 | rust-version.workspace = true
11 | description = "Macros for poem-mcpserver"
12 |
13 | [lib]
14 | proc-macro = true
15 |
16 | [dependencies]
17 | darling.workspace = true
18 | proc-macro-crate.workspace = true
19 | proc-macro2.workspace = true
20 | quote.workspace = true
21 | syn.workspace = true
22 |
--------------------------------------------------------------------------------
/examples/poem/lambda-hello-world/src/main.rs:
--------------------------------------------------------------------------------
1 | use poem::{get, handler, web::Path, Route};
2 | use poem_lambda::{run, Error};
3 |
4 | #[handler]
5 | fn hello(Path(name): Path) -> String {
6 | format!("hello: {name}")
7 | }
8 |
9 | #[tokio::main]
10 | async fn main() -> Result<(), Error> {
11 | if std::env::var_os("RUST_LOG").is_none() {
12 | std::env::set_var("RUST_LOG", "poem=debug");
13 | }
14 | tracing_subscriber::fmt::init();
15 |
16 | let app = Route::new().at("/hello/:name", get(hello));
17 | run(Route::new().nest("/prod", app)).await
18 | }
19 |
--------------------------------------------------------------------------------
/poem-derive/src/utils.rs:
--------------------------------------------------------------------------------
1 | use proc_macro_crate::{FoundCrate, crate_name};
2 | use proc_macro2::{Span, TokenStream};
3 | use quote::quote;
4 | use syn::Ident;
5 |
6 | pub(crate) fn get_crate_name(internal: bool) -> TokenStream {
7 | if internal {
8 | quote! { crate }
9 | } else {
10 | let name = match crate_name("poem") {
11 | Ok(FoundCrate::Name(name)) => name,
12 | Ok(FoundCrate::Itself) | Err(_) => "poem".to_string(),
13 | };
14 | let name = Ident::new(&name, Span::call_site());
15 | quote!(#name)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/disabled/tonic/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-tonic"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem = { workspace = true, features = ["tower-compat"] }
9 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
10 | prost = "0.14"
11 | tonic = "0.14"
12 | tracing-subscriber.workspace = true
13 | tower = { version = "0.4.8", features = ["buffer"] }
14 |
15 | [build-dependencies]
16 | tonic-build = "0.14"
17 |
18 | [[bin]]
19 | name = "example-tonic-client"
20 | path = "src/client.rs"
21 |
--------------------------------------------------------------------------------
/poem-grpc-build/src/utils.rs:
--------------------------------------------------------------------------------
1 | use proc_macro_crate::{FoundCrate, crate_name};
2 | use proc_macro2::{Span, TokenStream};
3 | use quote::quote;
4 | use syn::Ident;
5 |
6 | pub(crate) fn get_crate_name(internal: bool) -> TokenStream {
7 | if internal {
8 | quote! { crate }
9 | } else {
10 | let name = match crate_name("poem-grpc") {
11 | Ok(FoundCrate::Name(name)) => name,
12 | Ok(FoundCrate::Itself) | Err(_) => "poem_grpc".to_string(),
13 | };
14 | let name = Ident::new(&name, Span::call_site());
15 | quote!(#name)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/poem/static-files/src/main.rs:
--------------------------------------------------------------------------------
1 | use poem::{endpoint::StaticFilesEndpoint, listener::TcpListener, Route, Server};
2 |
3 | #[tokio::main]
4 | async fn main() -> Result<(), std::io::Error> {
5 | if std::env::var_os("RUST_LOG").is_none() {
6 | std::env::set_var("RUST_LOG", "poem=debug");
7 | }
8 | tracing_subscriber::fmt::init();
9 |
10 | let app = Route::new().nest(
11 | "/",
12 | StaticFilesEndpoint::new("./poem/static-files/files").show_files_listing(),
13 | );
14 | Server::new(TcpListener::bind("0.0.0.0:3000"))
15 | .run(app)
16 | .await
17 | }
18 |
--------------------------------------------------------------------------------
/poem/src/endpoint/to_response.rs:
--------------------------------------------------------------------------------
1 | use crate::{Endpoint, Request, Response, Result};
2 |
3 | /// Endpoint for the [`to_response`](super::EndpointExt::to_response)
4 | /// method.
5 | pub struct ToResponse {
6 | inner: E,
7 | }
8 |
9 | impl ToResponse {
10 | #[inline]
11 | pub(crate) fn new(inner: E) -> ToResponse {
12 | Self { inner }
13 | }
14 | }
15 |
16 | impl Endpoint for ToResponse {
17 | type Output = Response;
18 |
19 | async fn call(&self, req: Request) -> Result {
20 | Ok(self.inner.get_response(req).await)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/poem-grpc-build/src/service_generator.rs:
--------------------------------------------------------------------------------
1 | use prost_build::{Service, ServiceGenerator};
2 |
3 | use crate::config::GrpcConfig;
4 |
5 | pub(crate) struct PoemServiceGenerator {
6 | pub(crate) config: GrpcConfig,
7 | }
8 |
9 | impl ServiceGenerator for PoemServiceGenerator {
10 | fn generate(&mut self, service: Service, buf: &mut String) {
11 | if self.config.build_client {
12 | crate::client::generate(&self.config, &service, buf);
13 | }
14 | if self.config.build_server {
15 | crate::server::generate(&self.config, &service, buf);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/disabled/tonic/src/client.rs:
--------------------------------------------------------------------------------
1 | use hello_world::{greeter_client::GreeterClient, HelloRequest};
2 |
3 | pub mod hello_world {
4 | tonic::include_proto!("helloworld");
5 | }
6 |
7 | #[tokio::main]
8 | async fn main() -> Result<(), Box> {
9 | let mut client = GreeterClient::connect("http://localhost:3000")
10 | .await
11 | .unwrap();
12 | let request = tonic::Request::new(HelloRequest {
13 | name: "Tonic".into(),
14 | });
15 | let response = client.say_hello(request).await?;
16 | println!("RESPONSE={response:?}");
17 | Ok(())
18 | }
19 |
--------------------------------------------------------------------------------
/examples/grpc/helloworld_compressed/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "example-grpc-helloworld-compressed"
3 | version.workspace = true
4 | edition.workspace = true
5 | publish.workspace = true
6 |
7 | [dependencies]
8 | poem.workspace = true
9 | poem-grpc = { workspace = true, features = [
10 | "gzip",
11 | "deflate",
12 | "brotli",
13 | "zstd",
14 | ] }
15 | prost.workspace = true
16 | tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
17 |
18 | [build-dependencies]
19 | poem-grpc-build.workspace = true
20 |
21 | [[bin]]
22 | name = "grpc-helloworld-compressed-client"
23 | path = "src/client.rs"
24 |
--------------------------------------------------------------------------------
/examples/grpc/helloworld/src/client.rs:
--------------------------------------------------------------------------------
1 | use poem_grpc::{ClientConfig, Request};
2 |
3 | poem_grpc::include_proto!("helloworld");
4 |
5 | #[tokio::main]
6 | async fn main() -> Result<(), Box> {
7 | let client = GreeterClient::new(
8 | ClientConfig::builder()
9 | .uri("http://localhost:3000")
10 | .build()
11 | .unwrap(),
12 | );
13 | let request = Request::new(HelloRequest {
14 | name: "Poem".into(),
15 | });
16 | let response = client.say_hello(request).await?;
17 | println!("RESPONSE={response:?}");
18 | Ok(())
19 | }
20 |
--------------------------------------------------------------------------------
/examples/poem/nested-routing/src/main.rs:
--------------------------------------------------------------------------------
1 | use poem::{get, handler, listener::TcpListener, Route, Server};
2 |
3 | #[handler]
4 | fn hello() -> String {
5 | "hello".to_string()
6 | }
7 |
8 | fn api() -> Route {
9 | Route::new().at("/hello", get(hello))
10 | }
11 |
12 | #[tokio::main]
13 | async fn main() -> Result<(), std::io::Error> {
14 | if std::env::var_os("RUST_LOG").is_none() {
15 | std::env::set_var("RUST_LOG", "poem=debug")
16 | }
17 | tracing_subscriber::fmt::init();
18 |
19 | let app = Route::new().nest("/api", api());
20 | Server::new(TcpListener::bind("0.0.0.0:3000"))
21 | .run(app)
22 | .await
23 | }
24 |
--------------------------------------------------------------------------------
/poem-openapi-derive/src/error.rs:
--------------------------------------------------------------------------------
1 | use proc_macro2::TokenStream;
2 | use thiserror::Error;
3 |
4 | #[derive(Error, Debug)]
5 | pub(crate) enum GeneratorError {
6 | #[error("{0}")]
7 | Syn(#[from] syn::Error),
8 |
9 | #[error("{0}")]
10 | Darling(#[from] darling::Error),
11 | }
12 |
13 | impl GeneratorError {
14 | pub(crate) fn write_errors(self) -> TokenStream {
15 | match self {
16 | GeneratorError::Syn(err) => err.to_compile_error(),
17 | GeneratorError::Darling(err) => err.write_errors(),
18 | }
19 | }
20 | }
21 |
22 | pub(crate) type GeneratorResult = std::result::Result;
23 |
--------------------------------------------------------------------------------
/examples/grpc/middleware/src/client.rs:
--------------------------------------------------------------------------------
1 | mod middleware;
2 |
3 | use poem_grpc::{ClientConfig, Request};
4 |
5 | poem_grpc::include_proto!("helloworld");
6 |
7 | #[tokio::main]
8 | async fn main() -> Result<(), Box> {
9 | let client = GreeterClient::new(
10 | ClientConfig::builder()
11 | .uri("http://localhost:3000")
12 | .build()
13 | .unwrap(),
14 | );
15 | let request = Request::new(HelloRequest {
16 | name: "Poem".into(),
17 | });
18 | let response = client.say_hello(request).await?;
19 | println!("RESPONSE={response:?}");
20 | Ok(())
21 | }
22 |
--------------------------------------------------------------------------------
/poem/src/endpoint/map_to_response.rs:
--------------------------------------------------------------------------------
1 | use crate::{Endpoint, IntoResponse, Request, Response, Result};
2 |
3 | /// Endpoint for the [`map_to_response`](super::EndpointExt::map_to_response)
4 | /// method.
5 | pub struct MapToResponse {
6 | inner: E,
7 | }
8 |
9 | impl MapToResponse {
10 | #[inline]
11 | pub(crate) fn new(inner: E) -> MapToResponse {
12 | Self { inner }
13 | }
14 | }
15 |
16 | impl Endpoint for MapToResponse {
17 | type Output = Response;
18 |
19 | async fn call(&self, req: Request) -> Result {
20 | self.inner.call(req).await.map(IntoResponse::into_response)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/poem-grpc/proto/test_harness.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package test_harness;
4 |
5 | message UnaryRequest {
6 | int32 a = 1;
7 | int32 b = 2;
8 | }
9 |
10 | message ValueResponse { int32 value = 1; }
11 |
12 | message ValueRequest { int32 value = 1; }
13 |
14 | service TestHarness {
15 | rpc Unary(UnaryRequest) returns (ValueResponse);
16 |
17 | rpc ClientStreaming(stream ValueRequest) returns (ValueResponse);
18 |
19 | rpc ServerStreaming(ValueRequest) returns (stream ValueResponse);
20 |
21 | rpc BidirectionalStreaming(stream ValueRequest)
22 | returns (stream ValueResponse);
23 |
24 | rpc UnaryMetadata(UnaryRequest) returns (ValueResponse);
25 | }
26 |
--------------------------------------------------------------------------------
/examples/openapi/content-type-accept/README.md:
--------------------------------------------------------------------------------
1 | # Example: Content Type + Accept
2 |
3 | The purpose of this example is to demonstrate how to use the following two features of HTTP:
4 |
5 | - `Content-Type`: When a client sends the server a request, it can use this to tell it what type the data is.
6 | - `Accept`: When a client sends the server a request, it can use this to tell it what type of data it would like to receive as the response.
7 |
8 | This allows a client to, for example, submit a request as JSON, but expect the response as XML, assuming the server supports both types.
9 |
10 | To see what kind of spec this code produces, `cargo run` and then visit http://localhost:3000/spec.
11 |
--------------------------------------------------------------------------------
/poem-grpc/build.rs:
--------------------------------------------------------------------------------
1 | use std::io::Result;
2 |
3 | fn main() -> Result<()> {
4 | poem_grpc_build::Config::new()
5 | .build_client(false)
6 | .internal()
7 | .file_descriptor_set_path("grpc-reflection.bin")
8 | .compile(
9 | &["proto/reflection.proto", "proto/health.proto"],
10 | &["proto/"],
11 | )?;
12 |
13 | // for test
14 | poem_grpc_build::Config::new()
15 | .internal()
16 | .compile(&["proto/test_harness.proto"], &["proto/"])?;
17 |
18 | // example
19 | poem_grpc_build::Config::new()
20 | .internal()
21 | .compile(&["src/example_generated/routeguide.proto"], &[] as &[&str])?;
22 |
23 | Ok(())
24 | }
25 |
--------------------------------------------------------------------------------
/poem-mcpserver/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! MCP Server implementation for Poem
2 |
3 | #![forbid(unsafe_code)]
4 | #![deny(unreachable_pub)]
5 | #![cfg_attr(docsrs, feature(doc_cfg))]
6 | #![warn(rustdoc::broken_intra_doc_links)]
7 | #![warn(missing_docs)]
8 |
9 | pub mod content;
10 | pub mod protocol;
11 | mod server;
12 | pub mod stdio;
13 | #[cfg(feature = "streamable-http")]
14 | #[cfg_attr(docsrs, doc(cfg(feature = "streamable-http")))]
15 | pub mod streamable_http;
16 | pub mod tool;
17 | pub use poem_mcpserver_macros::Tools;
18 | pub use schemars::JsonSchema;
19 | pub use server::McpServer;
20 |
21 | #[doc(hidden)]
22 | pub mod private {
23 | pub use serde_json;
24 |
25 | pub use crate::tool::IntoToolResponse;
26 | }
27 |
--------------------------------------------------------------------------------
/examples/poem/hello-world/src/main.rs:
--------------------------------------------------------------------------------
1 | use poem::{
2 | get, handler, listener::TcpListener, middleware::Tracing, web::Path, EndpointExt, Route, Server,
3 | };
4 |
5 | #[handler]
6 | fn hello(Path(name): Path) -> String {
7 | format!("hello: {name}")
8 | }
9 |
10 | #[tokio::main]
11 | async fn main() -> Result<(), std::io::Error> {
12 | if std::env::var_os("RUST_LOG").is_none() {
13 | std::env::set_var("RUST_LOG", "poem=debug");
14 | }
15 | tracing_subscriber::fmt::init();
16 |
17 | let app = Route::new().at("/hello/:name", get(hello)).with(Tracing);
18 | Server::new(TcpListener::bind("0.0.0.0:3000"))
19 | .name("hello-world")
20 | .run(app)
21 | .await
22 | }
23 |
--------------------------------------------------------------------------------
/poem-worker/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "poem-worker"
3 | version = "0.1.0"
4 | authors.workspace = true
5 | edition.workspace = true
6 | license.workspace = true
7 | documentation.workspace = true
8 | homepage.workspace = true
9 | repository.workspace = true
10 | rust-version.workspace = true
11 |
12 | [dependencies]
13 | serde = { workspace = true }
14 | worker = { version = "0.6.0", features = ["http"] }
15 | bytes = { workspace = true }
16 | http = { workspace = true }
17 | http-body = "1.0.1"
18 | http-body-util = "0.1.0"
19 | async-trait = "0.1.88"
20 |
21 | poem = { workspace = true, default-features = false }
22 |
23 | tokio = { workspace = true }
24 |
25 | [features]
26 | queue = ["worker/queue"]
27 | d1 = ["worker/d1"]
28 |
--------------------------------------------------------------------------------
/examples/poem/opentelemetry-jaeger/README.md:
--------------------------------------------------------------------------------
1 | # Quickstart
2 |
3 | First make sure you have a running version of the Jaeger instance you want to send data to:
4 |
5 | ```shell
6 | docker run -e COLLECTOR_OTLP_ENABLED=true -p 4317:4317 -p 4318:4318 -p16686:16686 -p14268:14268 jaegertracing/all-in-one:latest
7 | ```
8 |
9 | Launch the servers:
10 |
11 | ```shell
12 | cargo run --bin example-opentelemetry-server1
13 | ```
14 |
15 | ```shell
16 | cargo run --bin example-opentelemetry-server2
17 | ```
18 |
19 | Send a request from the client:
20 |
21 | ```shell
22 | cargo run --bin example-opentelemetry-client
23 | ```
24 |
25 | Open `http://localhost:16686/` in the browser, you will see the following picture.
26 |
27 | 
28 |
--------------------------------------------------------------------------------
/poem-openapi/src/ui/stoplight_elements/stoplight-elements.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | OpenAPI
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/poem/src/session/mod.rs:
--------------------------------------------------------------------------------
1 | //! Session management.
2 |
3 | mod cookie_config;
4 | mod cookie_session;
5 | mod memory_storage;
6 | #[cfg(feature = "redis-session")]
7 | mod redis_storage;
8 | mod server_session;
9 | #[allow(clippy::module_inception)]
10 | mod session;
11 | mod session_storage;
12 | #[cfg(test)]
13 | pub(crate) mod test_harness;
14 |
15 | pub use cookie_config::{CookieConfig, CookieSecurity};
16 | pub use cookie_session::{CookieSession, CookieSessionEndpoint};
17 | pub use memory_storage::MemoryStorage;
18 | #[cfg(feature = "redis-session")]
19 | pub use redis_storage::RedisStorage;
20 | pub use server_session::{ServerSession, ServerSessionEndpoint};
21 | pub use session::{Session, SessionStatus};
22 | pub use session_storage::SessionStorage;
23 |
--------------------------------------------------------------------------------
/examples/poem/catch-panic/src/main.rs:
--------------------------------------------------------------------------------
1 | use poem::{
2 | handler,
3 | listener::TcpListener,
4 | middleware::{CatchPanic, Tracing},
5 | EndpointExt, Route, Server,
6 | };
7 |
8 | #[handler]
9 | fn index() {
10 | panic!("error!")
11 | }
12 |
13 | #[tokio::main]
14 | async fn main() -> Result<(), std::io::Error> {
15 | if std::env::var_os("RUST_LOG").is_none() {
16 | std::env::set_var("RUST_LOG", "poem=debug");
17 | }
18 | tracing_subscriber::fmt::init();
19 |
20 | let app = Route::new()
21 | .at("/", index)
22 | .with(Tracing)
23 | .with(CatchPanic::new());
24 | Server::new(TcpListener::bind("0.0.0.0:3000"))
25 | .name("hello-world")
26 | .run(app)
27 | .await
28 | }
29 |
--------------------------------------------------------------------------------
/examples/poem/combined-listeners/src/main.rs:
--------------------------------------------------------------------------------
1 | use poem::{
2 | get, handler,
3 | listener::{Listener, TcpListener},
4 | IntoResponse, Route, Server,
5 | };
6 |
7 | #[handler]
8 | fn hello() -> impl IntoResponse {
9 | "hello"
10 | }
11 |
12 | #[tokio::main]
13 | async fn main() -> Result<(), std::io::Error> {
14 | if std::env::var_os("RUST_LOG").is_none() {
15 | std::env::set_var("RUST_LOG", "poem=debug");
16 | }
17 | tracing_subscriber::fmt::init();
18 |
19 | let app = Route::new().at("/", get(hello));
20 | let listener = TcpListener::bind("0.0.0.0:3000")
21 | .combine(TcpListener::bind("0.0.0.0:3001"))
22 | .combine(TcpListener::bind("0.0.0.0:3002"));
23 | Server::new(listener).run(app).await
24 | }
25 |
--------------------------------------------------------------------------------
/poem-derive/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "poem-derive"
3 | version = "3.1.12"
4 | authors.workspace = true
5 | edition.workspace = true
6 | license.workspace = true
7 | documentation.workspace = true
8 | homepage.workspace = true
9 | repository.workspace = true
10 | rust-version.workspace = true
11 | description = "Macros for poem"
12 | keywords = ["http", "web", "framework", "async"]
13 | categories = [
14 | "network-programming",
15 | "asynchronous",
16 | "web-programming::http-server",
17 | "web-programming::websocket",
18 | ]
19 |
20 | [lib]
21 | proc-macro = true
22 |
23 | [dependencies]
24 | proc-macro-crate.workspace = true
25 | proc-macro2.workspace = true
26 | quote.workspace = true
27 | syn = { workspace = true, features = ["full"] }
28 |
--------------------------------------------------------------------------------
/poem/src/endpoint/before.rs:
--------------------------------------------------------------------------------
1 | use std::future::Future;
2 |
3 | use crate::{Endpoint, Request, Result};
4 |
5 | /// Endpoint for the [`before`](super::EndpointExt::before) method.
6 | pub struct Before {
7 | inner: E,
8 | f: F,
9 | }
10 |
11 | impl Before {
12 | #[inline]
13 | pub(crate) fn new(inner: E, f: F) -> Before {
14 | Self { inner, f }
15 | }
16 | }
17 |
18 | impl Endpoint for Before
19 | where
20 | E: Endpoint,
21 | F: Fn(Request) -> Fut + Send + Sync,
22 | Fut: Future