Skip to content

OpenAPI Migration Guide: From Existing API to Contract-Driven Development

This guide explains how API owners can migrate from traditional hand-coded APIs to OpenAPI-driven development using Connexion - the simplest and most direct approach to spec-first development.

Overview: The OpenAPI Development Model

Traditional API Development

Write Code → Extract Documentation → Hope Clients Match

OpenAPI-First Development with Connexion

Design Contract (OpenAPI Spec) → Write Python Functions → Connexion Routes Automatically

Benefits of OpenAPI-First

For API Owners (Server Side)

  • Automatic validation of requests/responses
  • Generated documentation that stays in sync
  • Consistent error handling across endpoints
  • Multiple client libraries generated automatically
  • Contract testing ensures API matches specification

For API Consumers (Client Side)

  • Type-safe clients in multiple languages
  • Automatic updates when API changes
  • Interactive documentation for testing
  • Consistent error handling across all endpoints

Migration Strategy for Existing APIs

Phase 1: Reverse Engineer OpenAPI Specification

Option A: Manual Analysis (Most Accurate)

bash
# Analyze existing endpoints manually  
curl https://your-api.com/api | jq
curl https://your-api.com/api/endpoint1 | jq
curl https://your-api.com/api/endpoint2 | jq

# Build OpenAPI spec by hand
# - Better handling of edge cases
# - More accurate parameter validation
# - Custom examples and documentation

Option B: Use Tools for Initial Structure

bash
# Use online tools or OpenAPI editors for structure
# - Swagger Editor: https://editor.swagger.io/
# - Insomnia/Postman: Export to OpenAPI
# - Existing API documentation tools

# Then manually refine for accuracy
vim openapi.yaml

Recommendation: Manual analysis gives best results, but tools can help with initial structure.

Phase 2: Gradual Migration (Zero-Risk Approach)

Step 1: Add OpenAPI Layer (Keep Existing Logic)

python
# Keep existing business logic intact
def legacy_list_documents():
    # Existing implementation - DON'T TOUCH
    docs = []
    for row in db.execute("SELECT * FROM documents"):
        doc = {
            'name': row[0],
            'ver': row[1],     # Old field names
            'rel': row[2],
            'data': row[3]
        }
        docs.append(doc)
    return docs

# Add OpenAPI wrapper that calls existing logic
@app.route('/api/documents')
@validate_openapi_request
@format_openapi_response  
def list_documents_openapi():
    # Call existing logic unchanged
    legacy_data = legacy_list_documents()
    
    # Transform to match OpenAPI specification
    openapi_format = {}
    for doc in legacy_data:
        openapi_format[doc['name']] = [{
            'version': doc['ver'],     # Map old → new field names
            'release': doc['rel'],
            'link': f"/api/documents/{doc['name']}/{doc['ver']}/{doc['rel']}"
        }]
    
    return openapi_format

Step 2: Extract Business Logic (Separation of Concerns)

python
# Separate business logic from API handling
class DocumentService:
    def get_all_documents(self):
        # Moved business logic here (unchanged)
        return self.existing_database_queries()
    
    def get_document_detail(self, name, version, release):
        # Existing logic, now in a service class
        return self.existing_detail_queries(name, version, release)

# OpenAPI-generated handler (clean separation)
@validate_openapi
def list_documents():
    service = DocumentService()
    return service.get_all_documents()  # Business logic untouched

Step 3: Optimize Business Logic (Independent Improvement)

python
# Now improve business logic without breaking API contract
class DocumentService:
    def get_all_documents(self):
        # Can refactor safely - OpenAPI contract protects clients
        return self.improved_queries_with_caching()

Why Connexion Over Code Generation

Connexion is simpler and more maintainable than OpenAPI Generator for Flask projects:

  • No code generation complexity
  • Direct function mapping to OpenAPI operations
  • Automatic validation and routing
  • Built-in Swagger UI
  • No regeneration issues

Setup Connexion

bash
# Install Connexion
pip install connexion[swagger-ui]

# Project structure
cyber-trackr-server/
├── app.py              # Main Connexion app
├── openapi.yaml        # Your OpenAPI specification
├── api/                # Your endpoint functions
   ├── __init__.py
   ├── documents.py    # Document endpoints
   ├── cci.py          # CCI endpoints
   └── rmf.py          # RMF endpoints
└── services/           # Business logic (safe from changes)
    ├── __init__.py
    ├── stig_service.py  # Your existing database logic
    ├── cci_service.py
    └── database.py

Client Code Generation

Multiple Language Support

bash
# Generate Ruby client (like cyber-trackr-live)
openapi-generator generate -i openapi.yaml -g ruby

# Generate Python client
openapi-generator generate -i openapi.yaml -g python

# Generate TypeScript client  
openapi-generator generate -i openapi.yaml -g typescript-fetch

# Generate Go client
openapi-generator generate -i openapi.yaml -g go

Client Usage Example

ruby
# Ruby client (auto-generated)
client = ApiClient.new
documents = client.list_all_documents

# Python client (auto-generated)  
client = ApiClient()
documents = client.list_all_documents()

# TypeScript client (auto-generated)
const client = new ApiClient()
const documents = await client.listAllDocuments()

Real-World Example: cyber.trackr.live Migration

What We Did (Reverse Engineering)

bash
# Manual analysis approach (most accurate)
env curl https://cyber.trackr.live/api | jq
env curl https://cyber.trackr.live/api/stig | jq  
env curl https://cyber.trackr.live/api/stig/Juniper_SRX_Services_Gateway_ALG/3/3 | jq

# Discovered edge cases automated tools would miss:
# - API returns text/html Content-Type but JSON body (server bug)
# - Date formats with leading spaces: " 30 Jan 2025"  
# - Requirements as object {V-214518: {...}} not array
# - Mixed content (STIGs + SRGs in same endpoint)

What We Built

  • Complete OpenAPI 3.1.1 specification with accurate schemas
  • Ruby client library with helper utilities
  • Interactive documentation with Scalar
  • Two-stage testing pattern for development workflow
  • Automated release process with version consistency

How cyber.trackr.live Owner Could Adopt This

Note: For the actual cyber.trackr.live implementation (Laravel/PHP + XML architecture), see the dedicated Laravel Migration Guide which addresses:

  • Laravel framework integration
  • XML XPath queries (no database)
  • Google Gemini AI integration
  • DISA XML drop processing
  • Minimal code changes approach

Immediate Benefits (No Code Changes)

bash
# Validate their API against our specification
spectral lint openapi.yaml
dredd openapi.yaml https://cyber.trackr.live/api

# Generate mock server for development
prism mock openapi.yaml

# Generate test cases
openapi-generator generate -i openapi.yaml -g test-cases

General Migration Path (For Other APIs)

python
# Phase 1: Wrapper approach (zero risk)
@app.route('/api/stig')
@validate_openapi  # Generated from our spec
def list_stigs():
    # Call their existing function unchanged
    result = their_existing_stig_function()
    
    # Transform to match our OpenAPI spec format
    return transform_to_openapi_format(result)

# Phase 2: Extract business logic  
class StigService:
    def get_all_stigs(self):
        # Their existing database logic (moved, not changed)
        return existing_queries()

# Phase 3: Generated handlers + business logic separation

Development Workflow with OpenAPI

Contract-First Development

bash
# 1. Design API contract
vim openapi.yaml

# 2. Validate specification  
spectral lint openapi.yaml

# 3. Generate server scaffolding
openapi-generator generate -i openapi.yaml -g python-flask

# 4. Generate client libraries
openapi-generator generate -i openapi.yaml -g ruby
openapi-generator generate -i openapi.yaml -g python

# 5. Implement business logic in protected files
vim business/service.py  # Never gets overwritten

# 6. Test contract compliance
dredd openapi.yaml http://localhost:5000/api

Version Management

yaml
# openapi.yaml - Single source of truth
info:
  version: 1.2.0  # Change here drives everything

# Regeneration picks up version automatically
# - Server code gets updated version
# - Client libraries get updated version  
# - Documentation shows updated version
# - Git tags match OpenAPI version

Breaking Changes Management

yaml
# Major version bump for breaking changes
info:
  version: 2.0.0

# Clients can specify version compatibility
gem 'your-api-client', '~> 1.0'  # Won't auto-update to 2.0

Testing Strategy

Contract Testing

bash
# Ensure API implementation matches specification
dredd openapi.yaml https://your-api.com/api

# Test client against specification
pact-broker  # Contract testing between services

Multi-Client Testing

bash
# Same API, multiple generated clients
ruby -e "puts RubyClient.new.list_documents.size"
python -c "print(len(PythonClient().list_documents()))"
node -e "console.log((await TsClient.listDocuments()).length)"

# All should return identical data

Benefits for API Ecosystem

For API Owners

  • Reduced maintenance - validation/formatting auto-generated
  • Better testing - multiple clients test your API automatically
  • Documentation synchronization - never out of date
  • Client feedback - spec improvements benefit everyone

For API Consumers

  • Reliable clients - generated from authoritative specification
  • Multiple languages - same API, different client languages
  • Automatic updates - when API evolves, clients can regenerate
  • Interactive testing - built-in documentation with "try it" features

For Both

  • Contract clarity - explicit agreement on API behavior
  • Collaborative improvement - spec changes benefit entire ecosystem
  • Reduced integration issues - contract testing catches problems early

Complete Connexion Implementation Example

This section shows the practical Connexion approach for implementing our OpenAPI specification server-side.

Step 1: Setup Connexion Project

bash
# Download our OpenAPI specification
curl -o openapi.yaml https://raw.githubusercontent.com/mitre/cyber-trackr-live/main/openapi/openapi.yaml

# Create project structure
mkdir cyber-trackr-server
cd cyber-trackr-server

# Install dependencies
pip install connexion[swagger-ui]
pip install flask-cors  # For CORS support

Step 2: Project Structure (Simple and Clean)

cyber-trackr-server/
├── app.py                  # Main Connexion application
├── openapi.yaml            # Our OpenAPI specification  
├── api/                    # API endpoint functions
│   ├── __init__.py
│   ├── documents.py        # Document endpoints
│   ├── cci.py             # CCI endpoints
│   └── rmf.py             # RMF endpoints
└── services/              # Business logic (YOUR CODE)
    ├── __init__.py
    ├── stig_service.py     # Your existing database logic
    ├── cci_service.py
    └── database.py

Step 3: Main Application (app.py)

python
# app.py - Main Connexion application
import connexion
from flask_cors import CORS

def create_app():
    # Create Connexion app
    app = connexion.App(__name__, specification_dir='.')
    
    # Add CORS support
    CORS(app.app)
    
    # Add our OpenAPI specification
    app.add_api('openapi.yaml')
    
    return app

if __name__ == '__main__':
    app = create_app()
    app.run(host='0.0.0.0', port=8080, debug=True)

Step 4: Update OpenAPI Spec for Connexion Routing

yaml
# openapi.yaml - Add operationId to connect to Python functions
paths:
  /api/stig:
    get:
      operationId: api.documents.list_all_documents  # Points to function
      summary: List all STIGs and SRGs
      responses:
        '200':
          description: Success
          
  /api/stig/{title}/{version}/{release}:
    get:
      operationId: api.documents.get_document  # Points to function
      summary: Get STIG or SRG document details
      parameters:
        - name: title
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success

Step 5: Implement API Functions (api/documents.py)

python
# api/documents.py - Your endpoint implementations
from services.stig_service import StigService

# Initialize your existing service
stig_service = StigService()

def list_all_documents():
    """List all STIGs and SRGs"""
    try:
        # Call your existing business logic directly
        result = stig_service.list_all_documents()
        return result, 200
    except Exception as e:
        return {"error": str(e)}, 500

def get_document(title, version, release):
    """Get STIG or SRG document details"""
    try:
        # Call your existing business logic directly
        result = stig_service.get_document(title, version, release)
        if result is None:
            return {"error": f"Document {title} not found"}, 404
        return result, 200
    except Exception as e:
        return {"error": str(e)}, 500

def get_requirement(title, version, release, vuln):
    """Get individual STIG/SRG requirement details"""
    try:
        result = stig_service.get_requirement(title, version, release, vuln)
        if result is None:
            return {"error": f"Requirement {vuln} not found"}, 404
        return result, 200
    except Exception as e:
        return {"error": str(e)}, 500

Step 6: Business Logic Layer (services/stig_service.py)

python
# services/stig_service.py - YOUR EXISTING BUSINESS LOGIC (UNCHANGED)
import sqlite3

class StigService:
    """
    Your existing STIG business logic - completely unchanged.
    Contains all your database queries, caching, business rules.
    """
    
    def __init__(self, db_path='cyber_trackr.db'):
        self.db_path = db_path
    
    def get_database_connection(self):
        """Your existing database connection method"""
        conn = sqlite3.connect(self.db_path)
        conn.row_factory = sqlite3.Row  # Dict-like access
        return conn
    
    def list_all_documents(self):
        """
        Your existing business logic for listing documents.
        Only the return format changes to match OpenAPI.
        """
        # Your existing database query (unchanged)
        with self.get_database_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("""
                SELECT name, version, release, date, released
                FROM stig_documents 
                ORDER BY name, version DESC, release DESC
            """)
            rows = cursor.fetchall()
        
        # Format for OpenAPI (minimal transformation)
        documents = {}
        for row in rows:
            doc_name = row['name']
            if doc_name not in documents:
                documents[doc_name] = []
            
            doc_version = {
                'version': str(row['version']),
                'release': str(row['release']),
                'date': row['date'] or '',
                'released': row['released'] or '',
                'link': f"/stig/{doc_name}/{row['version']}/{row['release']}"
            }
            documents[doc_name].append(doc_version)
        
        return documents
    
    def get_document(self, title, version, release):
        """Your existing logic - database queries unchanged"""
        # Your existing document query (unchanged)
        with self.get_database_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("""
                SELECT id, title, description, status, published
                FROM stig_documents 
                WHERE name = ? AND version = ? AND release = ?
            """, (title, version, release))
            doc_row = cursor.fetchone()
            
            if not doc_row:
                return None
            
            # Your existing requirements query (unchanged)
            cursor.execute("""
                SELECT vuln_id, title, rule, severity
                FROM stig_requirements 
                WHERE document_id = ?
            """, (doc_row['id'],))
            req_rows = cursor.fetchall()
        
        # Format requirements for OpenAPI
        requirements = {}
        for req in req_rows:
            requirements[req['vuln_id']] = {
                'title': req['title'],
                'rule': req['rule'], 
                'severity': req['severity'],
                'link': f"/stig/{title}/{version}/{release}/{req['vuln_id']}"
            }
        
        # Return dictionary matching OpenAPI schema
        return {
            'id': doc_row['id'],
            'title': doc_row['title'],
            'description': doc_row['description'],
            'status': doc_row['status'],
            'published': doc_row['published'],
            'requirements': requirements
        }

Step 7: Run the Server

bash
# Start the Connexion server
cd cyber-trackr-server
python app.py

# Connexion automatically provides:
# - API at: http://localhost:8080/api/stig
# - Swagger UI at: http://localhost:8080/ui/
# - OpenAPI spec at: http://localhost:8080/openapi.json

# Test the endpoints
curl http://localhost:8080/api/stig | jq
curl "http://localhost:8080/api/stig/Juniper_SRX_Services_Gateway_ALG/3/3" | jq

Step 8: When OpenAPI Spec Updates

bash
# 1. Get updated OpenAPI spec
curl -o openapi.yaml https://raw.githubusercontent.com/mitre/cyber-trackr-live/main/openapi/openapi.yaml

# 2. Update operationId fields to match your function names
# 3. Restart server - that's it!

# No regeneration needed - just update the spec file

Step 9: Business Logic Protection (Key Benefit)

WHAT CHANGES:                        WHAT STAYS SAFE:
├── openapi.yaml (when we update)    ├── services/
├── api/ functions (only if needed)  │   ├── stig_service.py      ✅ SAFE
                                     │   ├── cci_service.py       ✅ SAFE  
                                     │   └── database.py          ✅ SAFE
                                     ├── your_database.db         ✅ SAFE
                                     └── app.py                   ✅ SAFE

Step 10: Test with Our Generated Clients

bash
# Test your Connexion server with our Ruby client
ruby -e "
  require 'cyber_trackr_live'
  
  # Point our client to your Connexion server
  client = CyberTrackrClient::ApiClient.new
  client.config.host = 'http://localhost:8080'
  
  # Test with our generated client
  docs = client.list_all_documents
  puts \"Found #{docs.keys.size} document types\"
  
  # Test specific document
  doc = client.get_document('Juniper_SRX_Services_Gateway_ALG', '3', '3')
  puts \"Document has #{doc.requirements.size} requirements\"
"

The Complete Workflow - API Owner Perspective

  1. One-time setup: Create Connexion app with our OpenAPI spec (30 minutes)
  2. Move business logic: Extract existing code to services/ directory (1 hour)
  3. Connect functions: Map OpenAPI operations to Python functions (30 minutes)
  4. When our spec updates: Download new spec, restart server (2 minutes)
  5. Benefits: Always compliant, automatically tested, built-in documentation

Key Benefits of Connexion Approach

  1. Zero Business Logic Risk: Your existing database code never changes
  2. No Regeneration Complexity: Just update the OpenAPI spec file
  3. Built-in Documentation: Swagger UI automatically provided
  4. Automatic Validation: Request/response validation from OpenAPI spec
  5. Direct Function Mapping: Simple operationId → Python function connection
  6. Multi-Client Testing: Our Ruby/Python/Go clients automatically test your API
  7. Future-Proof: When we add new languages, they get tested clients automatically

This approach gives the cyber.trackr.live API owner the simplest migration path while gaining all the benefits of OpenAPI-first development.

Migration Checklist

Phase 1: Analysis & Planning

  • [ ] Analyze existing API endpoints and responses
  • [ ] Generate or create OpenAPI specification
  • [ ] Validate specification accuracy against live API
  • [ ] Plan migration approach (gradual vs full rewrite)

Phase 2: Implementation

  • [ ] Create wrapper layer that calls existing business logic
  • [ ] Add OpenAPI validation and formatting
  • [ ] Test new endpoints against specification
  • [ ] Gradually migrate business logic to service classes

Phase 3: Optimization

  • [ ] Generate server scaffolding with business logic separation
  • [ ] Migrate to generated handlers with protected implementation files
  • [ ] Add contract testing to CI/CD pipeline
  • [ ] Generate client libraries for consumers

Phase 4: Ecosystem

  • [ ] Publish OpenAPI specification for public use
  • [ ] Generate and distribute client libraries
  • [ ] Set up automated testing with multiple clients
  • [ ] Establish version management and breaking change policies

Tools and Resources

Code Generation

Validation & Testing

  • Spectral: OpenAPI specification linting
  • Dredd: API testing against OpenAPI specification
  • Prism: Mock server generation from OpenAPI

Documentation

  • Scalar: Interactive API documentation
  • RapiDoc: Alternative interactive documentation
  • Swagger UI: Traditional OpenAPI documentation

Migration Examples

  • cyber-trackr-live: Complete reverse-engineering example
  • train-juniper: Release process and version management patterns

Conclusion

OpenAPI-first development transforms API maintenance from a manual, error-prone process into an automated, contract-driven workflow. Using Connexion makes this migration simple and low-risk, allowing existing APIs to evolve without breaking changes while gaining all the benefits of contract-driven development.

The key insight: Start with the contract (OpenAPI spec), use Connexion for automatic routing and validation, and keep your business logic in separate service files.

Why Connexion is the Right Choice

  • Simplicity: No code generation complexity
  • Maintainability: Direct function mapping to OpenAPI operations
  • Flexibility: Easy to update when OpenAPI spec changes
  • Reliability: Automatic request/response validation
  • Developer Experience: Built-in Swagger UI and documentation

For API owners looking to adopt OpenAPI-first development, Connexion provides the most straightforward path while preserving existing business logic and ensuring future compatibility.

Future Architecture Considerations

Database Evolution Options

Depending on your performance and scalability needs:

SQLite (Minimal Complexity)

  • Single file database - easy to deploy anywhere
  • No server setup required
  • ACID compliance with good performance
  • Perfect for: Small to medium APIs, serverless deployments

PostgreSQL (Full Scale)

  • Production-grade relational database
  • High performance with complex queries
  • Advanced features (JSON columns, full-text search, etc.)
  • Perfect for: High-traffic APIs, complex data relationships

Static API Generation (Ultimate Performance)

For read-heavy APIs with stable data (like cyber.trackr.live), static builds provide the optimal solution:

When Static Build is Perfect

  • Read-heavy APIs: 99% GET requests, minimal writes
  • Stable data: Periodic updates (DISA drops, not real-time)
  • Structured data: Predictable schemas and relationships
  • No user state: No authentication, sessions, or personalization
  • Performance critical: Developers need fast, reliable responses

Implementation Pattern

bash
# Build process (runs when data changes)
generate-static-api --input data/ --output public/api/

# Results in:
/public/api/documents.json           # All documents list
/public/api/documents/doc1/3/3.json  # Individual documents
/public/api/cci.json                 # All CCIs
/public/api/cci/CCI-000001.json      # Individual CCI details

Generated File Structure

public/
├── api/
│   ├── stig.json                    # All STIGs list
│   ├── stig/
│   │   └── [title]/[version]/[release].json  # Individual STIGs
│   ├── cci.json                     # All CCIs
│   ├── cci/
│   │   └── [cci-id].json           # Individual CCIs
│   └── rmf/
│       └── controls.json           # RMF controls
└── docs/
    └── index.html                  # OpenAPI documentation

Build Process Example

python
# build_static_api.py
def build_static_api():
    # Use existing business logic
    service = DocumentService()
    
    # Generate all documents endpoint
    all_docs = service.get_all_documents()
    save_json('api/documents.json', all_docs)
    
    # Generate individual document files
    for doc_name, versions in all_docs.items():
        for version in versions:
            document = service.get_document(
                doc_name, 
                version['version'], 
                version['release']
            )
            
            # Include AI-generated content at build time
            if has_ai_features():
                document = enhance_with_ai(document)
            
            path = f"api/documents/{doc_name}/{version['version']}/{version['release']}.json"
            save_json(path, document)

CI/CD Integration

yaml
# .github/workflows/build-api.yml
name: Build Static API
on:
  schedule:
    - cron: '0 6 * * *'  # Daily check for data updates
  push:
    paths: ['data/**']

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build static API
        run: python build_static_api.py
      - name: Deploy to CDN
        run: |
          # Deploy to Netlify/CloudFlare/GitHub Pages
          npm install -g netlify-cli
          netlify deploy --prod --dir=public

Game-Changing Benefits

  • 🚀 Performance: 20-50ms response times globally (vs 200ms+ dynamic)
  • ♾️ Scalability: Handle millions of requests without server load
  • 💰 Cost: Near-zero ongoing costs (just CDN)
  • 🧠 AI Efficiency: Generate AI content once at build time, serve forever
  • 🔧 Simplicity: Just static files, no complex infrastructure
  • 🛡️ Reliability: CDN uptime (99.99%+) vs server reliability

Perfect for APIs Like cyber.trackr.live

Static build is ideal for:

  • STIG/SRG compliance data
  • Government standards and controls
  • Reference documentation APIs
  • Cybersecurity frameworks
  • Any read-heavy, stable dataset

Migration Path: Dynamic API → Static JSON → Enhanced with Database (if needed)

🎯 Why Static Build is Perfect for Many APIs

Perfect Match for These API Characteristics:

  1. Read-Heavy API: 99% GET requests, perfect for static files
  2. Stable Data: Periodic updates, not real-time changes
  3. Structured Data: Predictable schemas and relationships
  4. No User State: No authentication, sessions, or personalization
  5. Performance Critical: Developers want fast, reliable API responses

Game-Changing Benefits:

  1. 🚀 Performance: 20-50ms response times globally (vs 200ms+ dynamic)
  2. ♾️ Scalability: Handle millions of requests without server load
  3. 💰 Cost: Near-zero ongoing costs (just CDN)
  4. 🧠 AI Efficiency: Generate AI content once at build time, serve forever
  5. 🔧 Simplicity: Just static files, no complex infrastructure
  6. 🛡️ Reliability: CDN uptime (99.99%+) vs server reliability

Ideal Use Cases:

  • Government data APIs (STIGs, compliance standards)
  • Reference documentation (API specs, frameworks)
  • Cybersecurity frameworks (CIS Controls, NIST)
  • Financial data (rates, historical data)
  • Any read-heavy, stable dataset

Migration Path:

  1. Phase 1: Current dynamic API + OpenAPI docs
  2. Phase 2: Static build implementation (the sweet spot!)
  3. Phase 3: Enhanced with database only if needed

The static build approach transforms traditional APIs into high-performance, infinitely scalable, low-cost solutions while preserving existing business logic!

Released under the Apache-2.0 License.