# OpenAPI Integration
The gateway can automatically generate REST connectors from OpenAPI (Swagger) specification files. This enables quick integration of REST APIs without manual endpoint configuration.
## Supported Formats
| OpenAPI 3.0.x | `.json` | None |
| OpenAPI 3.1.x | `.json` | None |
| Swagger 2.0 | `.json` | None |
| YAML (any version) | `.yaml`, `.yml` | `yaml` |
## Quick Start
```rust
use grpc_graphql_gateway::{Gateway, OpenApiParser};
// Parse OpenAPI spec and create REST connector
let connector = OpenApiParser::from_file("petstore.yaml")?
.with_base_url("https://api.petstore.io/v2")
.build()?;
let gateway = Gateway::builder()
.add_rest_connector("petstore", connector)
.build()?;
```
## Loading Options
### From a File
```rust
// JSON file
let connector = OpenApiParser::from_file("api.json")?.build()?;
// YAML file (requires 'yaml' feature)
let connector = OpenApiParser::from_file("api.yaml")?.build()?;
```
### From a URL
```rust
let connector = OpenApiParser::from_url("https://api.example.com/openapi.json")
.await?
.build()?;
```
### From a String
```rust
let json_content = r#"{"openapi": "3.0.0", ...}"#;
let connector = OpenApiParser::from_string(json_content, false)?.build()?;
// For YAML content
let yaml_content = "openapi: '3.0.0'\n...";
let connector = OpenApiParser::from_string(yaml_content, true)?.build()?;
```
### From JSON Value
```rust
let json_value: serde_json::Value = serde_json::from_str(content)?;
let connector = OpenApiParser::from_json(json_value)?.build()?;
```
## Configuration Options
### Base URL Override
Override the server URL from the spec:
```rust
let connector = OpenApiParser::from_file("api.json")?
.with_base_url("https://api.staging.example.com") // Use staging
.build()?;
```
### Timeout
Set a default timeout for all endpoints:
```rust
use std::time::Duration;
let connector = OpenApiParser::from_file("api.json")?
.with_timeout(Duration::from_secs(60))
.build()?;
```
### Operation Prefix
Add a prefix to all operation names to avoid conflicts:
```rust
let connector = OpenApiParser::from_file("petstore.json")?
.with_prefix("petstore_") // listPets -> petstore_listPets
.build()?;
```
## Filtering Operations
### By Tags
Only include operations with specific tags:
```rust
let connector = OpenApiParser::from_file("api.json")?
.with_tags(vec!["pets".to_string(), "store".to_string()])
.build()?;
```
### Custom Filter
Use a predicate function for fine-grained control:
```rust
let connector = OpenApiParser::from_file("api.json")?
.filter_operations(|operation_id, path| {
// Only include non-deprecated v2 endpoints
!operation_id.contains("deprecated") && path.starts_with("/api/v2")
})
.build()?;
```
## What Gets Generated
The parser automatically generates:
### Endpoints
Each path operation becomes a GraphQL field:
| `GET /pets` | `listPets` query |
| `POST /pets` | `createPet` mutation |
| `GET /pets/{petId}` | `getPet` query |
| `DELETE /pets/{petId}` | `deletePet` mutation |
### Arguments
- **Path parameters** → Required field arguments
- **Query parameters** → Optional field arguments
- **Request body** → Input arguments (auto-templated)
### Response Types
Response schemas are converted to GraphQL types:
```yaml
# OpenAPI
Pet:
type: object
properties:
id:
type: integer
name:
type: string
tag:
type: string
```
Becomes a GraphQL type with field selection.
## Listing Operations
Before building, you can list all available operations:
```rust
let parser = OpenApiParser::from_file("api.json")?;
for op in parser.list_operations() {
println!("{}: {} {} (tags: {:?})",
op.operation_id,
op.method,
op.path,
op.tags
);
if let Some(summary) = op.summary {
println!(" {}", summary);
}
}
```
## Accessing Spec Information
```rust
let parser = OpenApiParser::from_file("api.json")?;
let info = parser.info();
println!("API: {} v{}", info.title, info.version);
if let Some(desc) = &info.description {
println!("Description: {}", desc);
}
```
## YAML Support
To enable YAML parsing, add the `yaml` feature:
```toml
[dependencies]
grpc_graphql_gateway = { version = "0.3", features = ["yaml"] }
```
## Example: Petstore Integration
```rust
use grpc_graphql_gateway::{Gateway, OpenApiParser};
use std::time::Duration;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Parse the Petstore OpenAPI spec
let petstore = OpenApiParser::from_url(
"https://petstore3.swagger.io/api/v3/openapi.json"
)
.await?
.with_base_url("https://petstore3.swagger.io/api/v3")
.with_timeout(Duration::from_secs(30))
.with_tags(vec!["pet".to_string()]) // Only pet operations
.with_prefix("pet_") // Namespace operations
.build()?;
// Create the gateway
let gateway = Gateway::builder()
.with_descriptor_set_bytes(DESCRIPTORS)
.add_grpc_client("service", grpc_client)
.add_rest_connector("petstore", petstore)
.serve("0.0.0.0:8888".to_string())
.await?;
Ok(())
}
```
## Multiple REST APIs
Combine multiple OpenAPI specs:
```rust
// Payment API
let stripe = OpenApiParser::from_file("stripe-openapi.json")?
.with_prefix("stripe_")
.build()?;
// Email API
let sendgrid = OpenApiParser::from_file("sendgrid-openapi.json")?
.with_prefix("email_")
.build()?;
// User service (gRPC)
let gateway = Gateway::builder()
.with_descriptor_set_bytes(USER_DESCRIPTORS)
.add_grpc_client("users", users_client)
.add_rest_connector("stripe", stripe)
.add_rest_connector("sendgrid", sendgrid)
.build()?;
```
## Best Practices
1. **Use prefixes** when combining multiple APIs to avoid naming conflicts
2. **Filter by tags** to include only the operations you need
3. **Override base URLs** for different environments (dev, staging, prod)
4. **Check available operations** before building to understand what will be generated
5. **Enable YAML** feature only if you need it (adds serde_yaml dependency)
## Limitations
- **Authentication**: OpenAPI security schemes are not automatically applied. Use request interceptors for auth.
- **Complex schemas**: Very complex schemas (allOf, oneOf, anyOf) may be simplified.
- **Webhooks**: OpenAPI 3.1 webhooks are not supported.
- **Callbacks**: Async callbacks are not supported.