at-jet 0.4.0

High-performance HTTP + Protobuf API framework for mobile services
Documentation
# AT-Jet

High-performance HTTP + Protobuf API framework for mobile services.

> **Not just a wrapper** - AT-Jet is an opinionated, production-ready foundation for mobile API development. See [Architecture Rationale]docs/ARCHITECTURE.md for why this project exists.

## Why AT-Jet?

Building mobile APIs with Protobuf over HTTP requires solving the same problems repeatedly:
- Content-type negotiation
- Request body size limits
- Consistent error handling
- Client library generation
- Team coding conventions

**Without AT-Jet** (30+ lines per handler):
```rust
async fn create_user(headers: HeaderMap, body: Bytes) -> impl IntoResponse {
    // Check content-type... validate size... decode proto... handle errors...
}
```

**With AT-Jet** (5 lines):
```rust
async fn create_user(ProtobufRequest(req): ProtobufRequest<CreateUserRequest>) -> ProtobufResponse<User> {
    ProtobufResponse::ok(User { id: 1, name: req.name })
}
```

## Features

- **HTTP/1.1 and HTTP/2 support** via axum
- **Protobuf request/response handling** with automatic content negotiation
- **Dual-format support** - Protobuf for production, JSON for debugging (with key authorization)
- **CDN-friendly** design for global mobile users
- **Middleware support** for authentication, logging, compression
- **Type-safe routing** with compile-time guarantees
- **Efficient bandwidth** - Protobuf is 60-70% smaller than JSON
- **Schema evolution** - Protobuf handles backward/forward compatibility

## Quick Start

Add to your `Cargo.toml`:

```toml
[dependencies]
at-jet = "0.3"
tokio = { version = "1", features = ["full"] }
prost = "0.13"

[build-dependencies]
prost-build = "0.13"
```

> See [Quick Start Guide]docs/QUICK_START.md for a complete 5-minute tutorial.

### Server Example

```rust
use at_jet::prelude::*;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let server = JetServer::new()
        .route("/api/users", get(list_users).post(create_user))
        .route("/api/users/:id", get(get_user))
        .with_cors()
        .with_compression();

    server.serve("0.0.0.0:8080").await?;
    Ok(())
}

async fn get_user(Path(id): Path<i32>) -> ProtobufResponse<User> {
    let user = User { id, name: "John".to_string() };
    ProtobufResponse::ok(user)
}

async fn list_users() -> ProtobufResponse<ListUsersResponse> {
    // Return list of users
    ProtobufResponse::ok(response)
}

async fn create_user(
    ProtobufRequest(req): ProtobufRequest<CreateUserRequest>
) -> ProtobufResponse<User> {
    // Create user from request
    ProtobufResponse::created(user)
}
```

### Client Example

```rust
use at_jet::prelude::*;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Protobuf client (production)
    let client = JetClient::new("https://api.example.com")?;

    // GET request
    let user: User = client.get("/api/users/123").await?;

    // POST request
    let request = CreateUserRequest { name: "John".to_string() };
    let created: User = client.post("/api/users", &request).await?;

    // JSON debug client (for development)
    let debug_client = JetClient::builder()
        .base_url("https://api.example.com")
        .debug_key("dev-debug-key")
        .build()?;

    // JSON requests for debugging
    let user_json: UserJson = debug_client.get_json("/api/users/123").await?;
    let raw_json = debug_client.get_json_raw("/api/users").await?;
    println!("Response: {}", raw_json);

    Ok(())
}
```

## Dual-Format Support (Protobuf + JSON)

AT-Jet supports both Protobuf (production) and JSON (debugging) formats. JSON requires authorization via debug keys to prevent accidental use in production.

### Why Require Authorization for JSON?

Protobuf provides schema evolution guarantees that JSON lacks:
- **Field numbers** enable backward/forward compatibility
- **Unknown fields** are preserved during deserialization
- **Optional fields** have well-defined defaults

If clients accidentally use JSON in production, they lose these guarantees and may break when the schema evolves. The debug key requirement ensures JSON is only used intentionally.

### Configuring Debug Keys

```rust
use at_jet::prelude::*;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Configure authorized debug keys (call once at startup)
    configure_debug_keys(vec![
        "alice-dev-key".to_string(),
        "bob-dev-key".to_string(),
        "qa-team-key".to_string(),
    ]);

    // Or disable JSON completely (production default)
    // configure_debug_keys(vec![]);

    let server = JetServer::new()
        .route("/api/users", post(create_user))
        .with_cors();

    server.serve("0.0.0.0:8080").await?;
    Ok(())
}
```

### Using Dual-Format Handlers

```rust
use at_jet::prelude::*;

// Dual-format handler - accepts both Protobuf and JSON
async fn create_user(
    ApiRequest { body, format }: ApiRequest<CreateUserRequest>
) -> ApiResponse<User> {
    let user = User { id: 1, name: body.name };
    ApiResponse::ok(format, user)  // Response format matches Accept header
}
```

### Client Usage

```bash
# Protobuf request (production - no debug key needed)
curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/x-protobuf" \
  -H "Accept: application/x-protobuf" \
  --data-binary @request.pb

# JSON request (debugging - requires valid debug key)
curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "X-Debug-Format: alice-dev-key" \
  -d '{"name": "John"}'

# JSON request without debug key → rejected with 415 Unsupported Media Type
curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{"name": "John"}'
```

### Format Selection Rules

| Request Format | Response Format | Condition |
|---------------|-----------------|-----------|
| Protobuf | Protobuf | Default (production) |
| JSON | JSON | Valid `X-Debug-Format` header |
| JSON | Error 415 | Missing/invalid debug key |
| Protobuf | JSON | Accept: application/json + valid debug key |

## Architecture

```
Mobile Clients (iOS, Android, Web)
   CDN (Global)
  ┌─────────────┐
  │   AT-Jet    │  ◄── HTTP + Protobuf
  │   Server    │
  └─────────────┘
  ┌─────────────┐
  │  Backend    │  ◄── ZUS-RS (internal RPC)
  │  Services   │
  └─────────────┘
```

## Why HTTP + Protobuf?

| Factor | JSON | Protobuf |
|--------|------|----------|
| **Size** | 100% | 30-40% (60-70% smaller) |
| **Parse Speed** | 100% | 10-20% (5-10x faster) |
| **Schema Evolution** | Manual | Built-in |
| **Type Safety** | Runtime | Compile-time |

## Running Examples

```bash
# Start server
cargo run --example basic_server

# In another terminal, run client
cargo run --example basic_client
```

## Documentation

- [Quick Start]docs/QUICK_START.md - Get running in 5 minutes
- [User Guide]docs/USER_GUIDE.md - Complete feature documentation
- [Architecture Rationale]docs/ARCHITECTURE.md - Why AT-Jet exists and design decisions
- [API Docs]https://docs.rs/at-jet - Generated API documentation
- [CLAUDE.md]CLAUDE.md - Development guidance and coding conventions

## License

MIT OR Apache-2.0