mockforge_grpc/lib.rs
1//! # MockForge gRPC
2//!
3//! Flexible gRPC mocking library with dynamic service discovery and HTTP bridge.
4//!
5//! This crate provides comprehensive gRPC mocking capabilities with:
6//!
7//! - **Dynamic Service Discovery**: Auto-discover and mock services from `.proto` files
8//! - **HTTP Bridge**: Expose gRPC services as REST APIs with OpenAPI documentation
9//! - **gRPC Reflection**: Built-in server reflection for service discovery
10//! - **Streaming Support**: Full support for unary, server, client, and bidirectional streaming
11//! - **Protocol Buffer Parsing**: Runtime parsing of `.proto` files without code generation
12//!
13//! ## Overview
14//!
15//! MockForge gRPC eliminates the need to hardcode service implementations. Simply provide
16//! `.proto` files, and MockForge will automatically:
17//!
18//! 1. Parse protobuf definitions
19//! 2. Generate mock service implementations
20//! 3. Handle all RPC methods (unary and streaming)
21//! 4. Optionally expose as REST APIs via HTTP Bridge
22//!
23//! ## Quick Start
24//!
25//! ### Basic gRPC Server
26//!
27//! ```rust,no_run
28//! use mockforge_grpc::start;
29//!
30//! #[tokio::main]
31//! async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
32//! // Start gRPC server on port 50051
33//! // Automatically discovers .proto files in ./proto directory
34//! start(50051).await?;
35//! Ok(())
36//! }
37//! ```
38//!
39//! ### With Custom Configuration
40//!
41//! ```rust,no_run
42//! use mockforge_grpc::{start_with_config, DynamicGrpcConfig};
43//! use mockforge_grpc::dynamic::http_bridge::HttpBridgeConfig;
44//! use mockforge_core::LatencyProfile;
45//!
46//! # async fn example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
47//! let config = DynamicGrpcConfig {
48//! proto_dir: "./my-protos".to_string(),
49//! enable_reflection: true,
50//! excluded_services: vec!["ExperimentalService".to_string()],
51//! http_bridge: Some(HttpBridgeConfig {
52//! enabled: true,
53//! base_path: "/api".to_string(),
54//! ..Default::default()
55//! }),
56//! ..Default::default()
57//! };
58//!
59//! let latency = Some(LatencyProfile::with_normal_distribution(120, 35.0));
60//! start_with_config(50051, latency, config).await?;
61//! # Ok(())
62//! # }
63//! ```
64//!
65//! ### HTTP Bridge Mode
66//!
67//! Expose gRPC services as REST APIs:
68//!
69//! ```rust,no_run
70//! use mockforge_grpc::{start_with_config, DynamicGrpcConfig};
71//! use mockforge_grpc::dynamic::http_bridge::HttpBridgeConfig;
72//!
73//! # async fn example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
74//! let config = DynamicGrpcConfig {
75//! proto_dir: "./proto".to_string(),
76//! http_bridge: Some(HttpBridgeConfig {
77//! enabled: true,
78//! base_path: "/api".to_string(),
79//! ..Default::default()
80//! }),
81//! ..Default::default()
82//! };
83//!
84//! start_with_config(50051, None, config).await?;
85//! // Now accessible via:
86//! // - gRPC: localhost:50051
87//! // - REST: http://localhost:8080/api/{service}/{method}
88//! // - OpenAPI: http://localhost:8080/api/docs
89//! # Ok(())
90//! # }
91//! ```
92//!
93//! ### TLS/mTLS Configuration
94//!
95//! Enable TLS encryption for secure gRPC connections:
96//!
97//! ```rust,no_run
98//! use mockforge_grpc::{start_with_config, DynamicGrpcConfig, GrpcTlsConfig};
99//!
100//! # async fn example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
101//! // Basic TLS
102//! let config = DynamicGrpcConfig {
103//! proto_dir: "./proto".to_string(),
104//! tls: Some(GrpcTlsConfig::new("server.crt", "server.key")),
105//! ..Default::default()
106//! };
107//!
108//! // Or with mutual TLS (client certificate verification)
109//! let mtls_config = DynamicGrpcConfig {
110//! proto_dir: "./proto".to_string(),
111//! tls: Some(GrpcTlsConfig::with_mtls("server.crt", "server.key", "client-ca.crt")),
112//! ..Default::default()
113//! };
114//!
115//! start_with_config(50051, None, config).await?;
116//! # Ok(())
117//! # }
118//! ```
119//!
120//! TLS can also be configured via environment variables:
121//! - `GRPC_TLS_CERT`: Path to server certificate (PEM format)
122//! - `GRPC_TLS_KEY`: Path to server private key (PEM format)
123//! - `GRPC_TLS_CLIENT_CA`: Optional path to client CA for mTLS
124//!
125//! ## Dynamic Service Discovery
126//!
127//! MockForge automatically discovers and mocks all services defined in your `.proto` files:
128//!
129//! ```protobuf
130//! // user.proto
131//! service UserService {
132//! rpc GetUser(GetUserRequest) returns (GetUserResponse);
133//! rpc ListUsers(ListUsersRequest) returns (stream User);
134//! rpc CreateUser(stream CreateUserRequest) returns (CreateUserResponse);
135//! rpc Chat(stream ChatMessage) returns (stream ChatMessage);
136//! }
137//! ```
138//!
139//! All four method types (unary, server streaming, client streaming, bidirectional) are
140//! automatically supported without any code generation or manual implementation.
141//!
142//! ## gRPC Reflection
143//!
144//! Enable reflection for service discovery by gRPC clients:
145//!
146//! ```bash
147//! # List services
148//! grpcurl -plaintext localhost:50051 list
149//!
150//! # Describe a service
151//! grpcurl -plaintext localhost:50051 describe UserService
152//!
153//! # Call a method
154//! grpcurl -plaintext -d '{"user_id": "123"}' localhost:50051 UserService/GetUser
155//! ```
156//!
157//! ## HTTP Bridge
158//!
159//! The HTTP Bridge automatically converts gRPC services to REST endpoints:
160//!
161//! ```bash
162//! # gRPC call
163//! grpcurl -d '{"user_id": "123"}' localhost:50051 UserService/GetUser
164//!
165//! # Equivalent HTTP call
166//! curl -X POST http://localhost:8080/api/userservice/getuser \
167//! -H "Content-Type: application/json" \
168//! -d '{"user_id": "123"}'
169//!
170//! # OpenAPI documentation
171//! curl http://localhost:8080/api/docs
172//! ```
173//!
174//! ## Advanced Data Synthesis
175//!
176//! Generate realistic mock data using intelligent field inference:
177//!
178//! - Detects field types from names (`email`, `phone`, `id`, etc.)
179//! - Maintains referential integrity across related messages
180//! - Supports deterministic seeding for reproducible tests
181//!
182//! ## Key Modules
183//!
184//! - [`dynamic`]: Dynamic service discovery and mocking
185//! - [`reflection`]: gRPC reflection protocol implementation
186//! - [`registry`]: Service and method registry
187//!
188//! ## Examples
189//!
190//! See the [examples directory](https://github.com/SaaSy-Solutions/mockforge/tree/main/examples)
191//! for complete working examples.
192//!
193//! ## Related Crates
194//!
195//! - [`mockforge-core`](https://docs.rs/mockforge-core): Core mocking functionality
196//! - [`mockforge-data`](https://docs.rs/mockforge-data): Synthetic data generation
197//!
198//! ## Documentation
199//!
200//! - [MockForge Book](https://docs.mockforge.dev/)
201//! - [gRPC Mocking Guide](https://docs.mockforge.dev/user-guide/grpc-mocking.html)
202//! - [API Reference](https://docs.rs/mockforge-grpc)
203
204use mockforge_core::LatencyProfile;
205
206pub mod dynamic;
207pub mod reflection;
208pub mod registry;
209
210/// Generated Protocol Buffer code from .proto files
211///
212/// This module contains auto-generated Rust code from Protocol Buffer definitions.
213/// The generated code provides message types and service stubs for gRPC operations.
214///
215/// # Note
216///
217/// The generated code in this module is excluded from missing documentation checks
218/// as it is automatically generated from `.proto` files and documentation should
219/// be added to the source `.proto` files instead.
220#[allow(missing_docs)]
221pub mod generated {
222 // Include all generated proto files
223 tonic::include_proto!("mockforge.greeter");
224}
225
226pub use dynamic::proto_parser::ProtoService;
227pub use dynamic::service_generator::MockResponse;
228pub use dynamic::{DynamicGrpcConfig, GrpcTlsConfig, ServiceRegistry};
229pub use reflection::{MockReflectionProxy, ProxyConfig, ReflectionProxy};
230pub use registry::GrpcProtoRegistry;
231
232/// Start gRPC server with default configuration
233pub async fn start(port: u16) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
234 start_with_latency(port, None).await
235}
236
237/// Start gRPC server with latency configuration
238pub async fn start_with_latency(
239 port: u16,
240 latency_profile: Option<LatencyProfile>,
241) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
242 let config = DynamicGrpcConfig::default();
243 start_with_config(port, latency_profile, config).await
244}
245
246/// Start gRPC server with custom configuration
247pub async fn start_with_config(
248 port: u16,
249 latency_profile: Option<LatencyProfile>,
250 config: DynamicGrpcConfig,
251) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
252 dynamic::start_dynamic_server(port, config, latency_profile).await
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258
259 #[test]
260 fn test_dynamic_grpc_config_default() {
261 let _config = DynamicGrpcConfig::default();
262 // Config should be created successfully
263 }
264
265 #[test]
266 fn test_latency_profile_creation() {
267 let profile = LatencyProfile::default();
268 assert_eq!(profile.base_ms, 50);
269 assert_eq!(profile.jitter_ms, 20);
270 assert_eq!(profile.min_ms, 0);
271 }
272
273 #[test]
274 fn test_latency_profile_custom() {
275 let profile = LatencyProfile::new(100, 25);
276
277 assert_eq!(profile.base_ms, 100);
278 assert_eq!(profile.jitter_ms, 25);
279 assert_eq!(profile.min_ms, 0);
280 }
281}