Skip to content

evacchi/envoy-ext-server

Repository files navigation

Envoy External Processing Server

A Go-based extensible external processing server for Envoy Proxy, designed to handle HTTP request/response processing through Envoy's External Processing API.

Originally based on envoy-extproc-sdk-go

Overview

This server implements Envoy's External Processing service to intercept and modify HTTP requests and responses. It supports a plugin architecture that allows for both built-in Go plugins and WebAssembly modules.

Features

  • Plugin Architecture: Extensible filter chain system supporting multiple plugin types
  • Built-in Plugins: Ready-to-use filters for common processing tasks
  • Go Plugin Support: Dynamic loading of Go shared object plugins
  • WebAssembly Support: Execute Wasm modules for custom processing logic
  • Configuration-Driven: YAML-based configuration for easy deployment
  • Docker Support: Containerized deployment with Docker Compose

Quick Start

Prerequisites

  • Go 1.21+
  • just (for build automation)
  • Docker & Docker Compose (for containerized deployment)

Build and Run

# Build all components
just build

# Run with default configuration
go run main.go -c ext-server.yaml

# Or using just
just run

Docker Deployment

# Build and start with Docker Compose
just up

# Test the setup
just call /

# Stop services
just down

Configuration

The server is configured via YAML files. Example configuration (ext-server.yaml):

filter_chains:
  - filters:
      - name: timer
        type: built-in
      - name: wasm
        type: go-plugin
        path: plugins/wasm/goplugin/wasm.so
        config:
          name: hello
          path: plugins/wasm/wasm/hello.wasm
      - name: trivial
        type: built-in

Configuration Options

  • listen: Server listen address (default: tcp://:50051)
  • filter_chains: Array of filter chain configurations
    • filters: Array of filter definitions
      • name: Plugin identifier
      • type: Plugin type (built-in, go-plugin)
      • path: Path to plugin shared object (for go-plugin type)
      • config: Plugin-specific configuration

Available Plugins

Built-in Plugins

  • noop: No-operation filter for testing
  • timer: Adds timing information to requests
  • trivial: Simple request/response modification example

Go Plugins

  • wasm: WebAssembly module executor

WebAssembly Modules

  • hello: Example Wasm module demonstrating basic functionality

Development

Project Structure

├── main.go              # Application entry point
├── ext-server.yaml      # Default configuration
├── extproc/            # Envoy external processing implementation
├── pluginapi/          # Plugin API and interfaces
├── plugins/            # Plugin implementations
│   ├── noop/           # No-operation plugin
│   ├── timer/          # Timer plugin
│   ├── trivial/        # Trivial example plugin
│   └── wasm/           # WebAssembly plugin
├── e2e/                # End-to-end tests
└── justfile            # Build automation

Available Commands

# Development
just format      # Format Go code
just test        # Run unit tests
just build       # Build all components
just clean       # Clean build artifacts

# Running
just run         # Run server with default config

# Docker
just up          # Build and start with Docker Compose
just down        # Stop Docker services
just call        # Make test HTTP requests

# Maintenance
just update      # Update dependencies
just tidy        # Clean up Go modules

Creating New Plugins

Built-in Plugin

  1. Create a new directory under plugins/
  2. Implement the Plugin interface from pluginapi
  3. Register the plugin in the filter chain factory

Go Plugin

  1. Create a goplugin subdirectory in your plugin directory
  2. Implement a main.go with a New function returning a PluginFactory
  3. Build as a shared object: go build -buildmode=plugin

WebAssembly Plugin

  1. Write your Wasm module in Go (or any WASM-compatible language)
  2. Compile to Wasm (TinyGo is generally preferred)
  3. Configure the Wasm plugin to load your module

API

The server exposes Envoy's External Processing gRPC service on port 50051 (configurable). It implements the following service methods:

  • Process: Stream processing of HTTP requests/responses
  • HealthCheck: Health checking endpoint

Testing

Unit Tests

just test

Integration Tests

# Start the full stack
just up

# Make test requests
just call /
just call /health

# Check Envoy admin interface
curl localhost:9901/stats

Architecture

The system follows a modular architecture:

  1. Server Layer: gRPC server implementing Envoy's External Processing API
  2. Processing Layer: Request/response context management
  3. Plugin Layer: Configurable filter chain with plugin support
  4. Configuration Layer: YAML-based configuration management

About

A plugin host for Envoy using extproc, goplugin, with Wasm support (using wazero)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published