Skip to content

Commit ea86f97

Browse files
authored
Merge pull request #118 from Tuntii/grpc-and-so-many
Add optional rustapi-grpc crate (tonic/prost)
2 parents 376b1b5 + 3074e46 commit ea86f97

File tree

13 files changed

+536
-9
lines changed

13 files changed

+536
-9
lines changed

Cargo.lock

Lines changed: 101 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ members = [
1212
"crates/rustapi-view",
1313
"crates/rustapi-testing",
1414
"crates/rustapi-jobs",
15+
"crates/rustapi-grpc",
1516
"crates/cargo-rustapi",
1617
]
1718

@@ -79,6 +80,10 @@ criterion = { version = "0.5", features = ["html_reports"] }
7980
tokio-tungstenite = "0.24"
8081
tungstenite = "0.24"
8182

83+
# gRPC
84+
tonic = "0.14"
85+
prost = "0.14"
86+
8287
# Template engine
8388
tera = "1.19"
8489

@@ -100,6 +105,7 @@ rustapi-ws = { path = "crates/rustapi-ws", version = "0.1.335" }
100105
rustapi-view = { path = "crates/rustapi-view", version = "0.1.335" }
101106
rustapi-testing = { path = "crates/rustapi-testing", version = "0.1.335" }
102107
rustapi-jobs = { path = "crates/rustapi-jobs", version = "0.1.335" }
108+
rustapi-grpc = { path = "crates/rustapi-grpc", version = "0.1.335" }
103109

104110
# HTTP/3 (QUIC)
105111
quinn = "0.11"

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,16 @@ async fn main() {
106106
***WebSocket**: Full permessage-deflate negotiation and compression
107107
***OpenAPI**: Improved reference integrity and native validation docs
108108
***Async Validation**: Deep integration with application state for complex rules
109+
***gRPC Foundation**: New optional `rustapi-grpc` crate with Tonic/Prost integration and side-by-side HTTP + gRPC runners (`run_rustapi_and_grpc`, `run_rustapi_and_grpc_with_shutdown`)
110+
***CLI DX Update**: `cargo rustapi new` interactive feature selection now includes `grpc`
109111

110112
## 🗺️ Public Roadmap: Next 30 Days
111113

112114
We build in public. Here is our immediate focus for **February 2026**:
113115

114-
* [ ] **Visual Status Page**: Automatic health dashboard for all endpoints.
115-
* [ ] **gRPC Integration**: First-class support via Tonic.
116-
* [ ] **Distributed Tracing**: One-line OpenTelemetry setup.
116+
* [x] **Visual Status Page**: Automatic health dashboard for all endpoints.
117+
* [x] **gRPC Integration (Foundation)**: First-class optional crate via Tonic (`rustapi-grpc`) with RustAPI facade-level feature flag support.
118+
* [x] **Distributed Tracing**: One-line OpenTelemetry setup.
117119
* [ ] **RustAPI Cloud**: One-click deploy to major cloud providers.
118120

119121
## 📚 Documentation
@@ -122,6 +124,7 @@ We moved our detailed architecture, recipes, and deep-dives to the **[Cookbook](
122124

123125
* [System Architecture & Diagrams](docs/cookbook/src/architecture/system_overview.md)
124126
* [Performance Benchmarks](docs/cookbook/src/concepts/performance.md)
127+
* [gRPC Integration Guide](docs/cookbook/src/crates/rustapi_grpc.md)
125128
* [Full Examples](crates/rustapi-rs/examples/)
126129

127130
---

crates/cargo-rustapi/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ walkdir = "2.5"
2828
toml_edit = "0.22"
2929

3030
# Async
31-
tokio = { workspace = true, features = ["process", "fs"] }
31+
tokio = { workspace = true, features = ["process", "fs", "macros", "rt-multi-thread", "time", "signal"] }
3232

3333
# Serialization
3434
serde = { workspace = true }

crates/cargo-rustapi/src/commands/new.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,19 @@ pub async fn new_project(mut args: NewArgs) -> Result<()> {
9090
} else if args.yes {
9191
vec![]
9292
} else {
93-
let available = ["jwt", "cors", "rate-limit", "config", "toon", "ws", "view"];
93+
let available = [
94+
"jwt",
95+
"cors",
96+
"rate-limit",
97+
"config",
98+
"toon",
99+
"ws",
100+
"view",
101+
"grpc",
102+
];
94103
let defaults = match template {
95-
ProjectTemplate::Full => vec![true, true, true, true, false, false, false],
96-
ProjectTemplate::Web => vec![false, false, false, false, false, false, true],
104+
ProjectTemplate::Full => vec![true, true, true, true, false, false, false, false],
105+
ProjectTemplate::Web => vec![false, false, false, false, false, false, true, false],
97106
_ => vec![false; available.len()],
98107
};
99108

crates/rustapi-grpc/Cargo.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[package]
2+
name = "rustapi-grpc"
3+
description = "gRPC integration helpers for RustAPI powered by Tonic"
4+
documentation = "https://docs.rs/rustapi-grpc"
5+
version.workspace = true
6+
edition.workspace = true
7+
authors.workspace = true
8+
license.workspace = true
9+
repository.workspace = true
10+
keywords = ["web", "framework", "api", "grpc", "tonic"]
11+
categories = ["web-programming::http-server", "network-programming"]
12+
rust-version.workspace = true
13+
readme = "README.md"
14+
15+
[dependencies]
16+
rustapi-core = { workspace = true }
17+
tokio = { workspace = true, features = ["macros"] }
18+
tonic = { workspace = true, features = ["transport"] }
19+
prost = { workspace = true }
20+
21+
[dev-dependencies]
22+
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] }
23+
tonic-health = "0.14"

crates/rustapi-grpc/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# rustapi-grpc
2+
3+
`rustapi-grpc` provides gRPC integration helpers for RustAPI with [Tonic](https://github.com/hyperium/tonic).
4+
5+
## What it gives you
6+
7+
- `run_concurrently(http, grpc)`: run two server futures together.
8+
- `run_rustapi_and_grpc(app, http_addr, grpc)`: convenience helper for RustAPI + gRPC side-by-side.
9+
- `run_rustapi_and_grpc_with_shutdown(app, http_addr, signal, grpc_with_shutdown)`: shared shutdown signal for both servers.
10+
- Re-exports: `tonic`, `prost`.
11+
12+
## Example
13+
14+
```rust,ignore
15+
use rustapi_rs::grpc::{run_rustapi_and_grpc, tonic};
16+
use rustapi_rs::prelude::*;
17+
18+
#[rustapi_rs::get("/health")]
19+
async fn health() -> &'static str { "ok" }
20+
21+
#[tokio::main]
22+
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
23+
let http_app = RustApi::new().route("/health", get(health));
24+
25+
let grpc_addr = "127.0.0.1:50051".parse()?;
26+
let grpc_server = tonic::transport::Server::builder()
27+
.add_service(MyGreeterServer::new(MyGreeter::default()))
28+
.serve(grpc_addr);
29+
30+
run_rustapi_and_grpc(http_app, "127.0.0.1:8080", grpc_server).await?;
31+
Ok(())
32+
}
33+
```
34+
35+
## Shared shutdown (Ctrl+C)
36+
37+
```rust,ignore
38+
use rustapi_rs::grpc::{run_rustapi_and_grpc_with_shutdown, tonic};
39+
40+
let grpc_addr = "127.0.0.1:50051".parse()?;
41+
42+
run_rustapi_and_grpc_with_shutdown(
43+
http_app,
44+
"127.0.0.1:8080",
45+
tokio::signal::ctrl_c(),
46+
move |shutdown| {
47+
tonic::transport::Server::builder()
48+
.add_service(MyGreeterServer::new(MyGreeter::default()))
49+
.serve_with_shutdown(grpc_addr, shutdown)
50+
},
51+
).await?;
52+
```

0 commit comments

Comments
 (0)