Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 101 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ members = [
"crates/rustapi-view",
"crates/rustapi-testing",
"crates/rustapi-jobs",
"crates/rustapi-grpc",
"crates/cargo-rustapi",
]

Expand Down Expand Up @@ -79,6 +80,10 @@ criterion = { version = "0.5", features = ["html_reports"] }
tokio-tungstenite = "0.24"
tungstenite = "0.24"

# gRPC
tonic = "0.14"
prost = "0.14"

# Template engine
tera = "1.19"

Expand All @@ -100,6 +105,7 @@ rustapi-ws = { path = "crates/rustapi-ws", version = "0.1.335" }
rustapi-view = { path = "crates/rustapi-view", version = "0.1.335" }
rustapi-testing = { path = "crates/rustapi-testing", version = "0.1.335" }
rustapi-jobs = { path = "crates/rustapi-jobs", version = "0.1.335" }
rustapi-grpc = { path = "crates/rustapi-grpc", version = "0.1.335" }

# HTTP/3 (QUIC)
quinn = "0.11"
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,16 @@ async fn main() {
* ✅ **WebSocket**: Full permessage-deflate negotiation and compression
* ✅ **OpenAPI**: Improved reference integrity and native validation docs
* ✅ **Async Validation**: Deep integration with application state for complex rules
* ✅ **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`)
* ✅ **CLI DX Update**: `cargo rustapi new` interactive feature selection now includes `grpc`

## 🗺️ Public Roadmap: Next 30 Days

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

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

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

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

---
Expand Down
2 changes: 1 addition & 1 deletion crates/cargo-rustapi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ walkdir = "2.5"
toml_edit = "0.22"

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

# Serialization
serde = { workspace = true }
Expand Down
15 changes: 12 additions & 3 deletions crates/cargo-rustapi/src/commands/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,19 @@ pub async fn new_project(mut args: NewArgs) -> Result<()> {
} else if args.yes {
vec![]
} else {
let available = ["jwt", "cors", "rate-limit", "config", "toon", "ws", "view"];
let available = [
"jwt",
"cors",
"rate-limit",
"config",
"toon",
"ws",
"view",
"grpc",
];
let defaults = match template {
ProjectTemplate::Full => vec![true, true, true, true, false, false, false],
ProjectTemplate::Web => vec![false, false, false, false, false, false, true],
ProjectTemplate::Full => vec![true, true, true, true, false, false, false, false],
ProjectTemplate::Web => vec![false, false, false, false, false, false, true, false],
_ => vec![false; available.len()],
};

Expand Down
23 changes: 23 additions & 0 deletions crates/rustapi-grpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "rustapi-grpc"
description = "gRPC integration helpers for RustAPI powered by Tonic"
documentation = "https://docs.rs/rustapi-grpc"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
keywords = ["web", "framework", "api", "grpc", "tonic"]
categories = ["web-programming::http-server", "network-programming"]
rust-version.workspace = true
readme = "README.md"

[dependencies]
rustapi-core = { workspace = true }
tokio = { workspace = true, features = ["macros"] }
tonic = { workspace = true, features = ["transport"] }
prost = { workspace = true }
Comment on lines +16 to +19
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rustapi-grpc uses tokio::spawn and tokio::sync::watch, but the dependency only enables the macros feature. Other crates in this workspace explicitly list the Tokio features they rely on; consider adding the needed Tokio features here as well (at least rt and sync, and optionally time only for tests) so the crate doesn’t implicitly depend on Tokio default features or a workspace-wide configuration.

Copilot uses AI. Check for mistakes.

[dev-dependencies]
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] }
tonic-health = "0.14"
52 changes: 52 additions & 0 deletions crates/rustapi-grpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# rustapi-grpc

`rustapi-grpc` provides gRPC integration helpers for RustAPI with [Tonic](https://github.com/hyperium/tonic).

## What it gives you

- `run_concurrently(http, grpc)`: run two server futures together.
- `run_rustapi_and_grpc(app, http_addr, grpc)`: convenience helper for RustAPI + gRPC side-by-side.
- `run_rustapi_and_grpc_with_shutdown(app, http_addr, signal, grpc_with_shutdown)`: shared shutdown signal for both servers.
- Re-exports: `tonic`, `prost`.

## Example

```rust,ignore
use rustapi_rs::grpc::{run_rustapi_and_grpc, tonic};
use rustapi_rs::prelude::*;

#[rustapi_rs::get("/health")]
async fn health() -> &'static str { "ok" }

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let http_app = RustApi::new().route("/health", get(health));

let grpc_addr = "127.0.0.1:50051".parse()?;
let grpc_server = tonic::transport::Server::builder()
.add_service(MyGreeterServer::new(MyGreeter::default()))
.serve(grpc_addr);

run_rustapi_and_grpc(http_app, "127.0.0.1:8080", grpc_server).await?;
Ok(())
}
Comment on lines +14 to +32
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This README is for the rustapi-grpc crate, but the examples import from rustapi_rs::grpc. That makes it hard to copy/paste when depending on rustapi-grpc directly. Consider updating the examples to use rustapi_grpc + rustapi_core, or add a short section that clearly distinguishes “via rustapi-rs feature grpc” vs “direct rustapi-grpc usage”.

Copilot uses AI. Check for mistakes.
```

## Shared shutdown (Ctrl+C)

```rust,ignore
use rustapi_rs::grpc::{run_rustapi_and_grpc_with_shutdown, tonic};

let grpc_addr = "127.0.0.1:50051".parse()?;

run_rustapi_and_grpc_with_shutdown(
http_app,
"127.0.0.1:8080",
tokio::signal::ctrl_c(),
move |shutdown| {
tonic::transport::Server::builder()
.add_service(MyGreeterServer::new(MyGreeter::default()))
.serve_with_shutdown(grpc_addr, shutdown)
},
).await?;
```
Loading
Loading