Socket
Book a DemoInstallSign in
Socket

zntr.io/extproctor

Package Overview
Dependencies
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zntr.io/extproctor

Go Modules
Version
v0.0.0-20251217071741-f610707dad71
Version published
Created
Source

🧪 ExtProctor

A test runner for Envoy ExtProc implementations

Go Version License Go Report Card Documentation

FeaturesInstallationQuick StartDocumentationExamplesContributing

Why ExtProctor?

Implementing and evolving Envoy External Processing (ExtProc) services is error-prone. Behaviours depend on correct protobuf message structures and a sequence of callbacks that are difficult to test manually.

[!NOTE] This project is heavily inspired by Google Service Extensions where they use the same approach to test their service extensions.

ExtProctor provides a dedicated test runner that enables:

  • Automated regression testing for ExtProc implementations
  • Fast feedback loops during local development
  • CI/CD integration with machine-readable outputs
  • Version-controlled test cases using human-readable prototext manifests

Features

FeatureDescription
📝 Prototext ManifestsDefine test cases using human-readable prototext format
🔄 Full ExtProc SupportTest all processing phases: headers, body, and trailers
📸 Golden FilesCapture and compare responses using the golden file pattern
Parallel ExecutionRun tests concurrently for faster feedback
🏷️ Flexible FilteringFilter tests by name pattern or tags
📊 Multiple Output FormatsHuman-readable or JSON output for CI integration
🔌 Unix Socket SupportConnect to ExtProc services via Unix domain sockets
🔒 TLS SupportSecure gRPC connections with client certificates

Installation

Using Go

go install zntr.io/extproctor/cmd/extproctor@latest

From Source

git clone https://github.com/zntrio/extproctor.git
cd extproctor
go build -o extproctor ./cmd/extproctor

Verify Installation

extproctor --help

Quick Start

1. Create a Test Manifest

Create a file tests/basic.textproto:

name: "basic-test"
description: "Basic ExtProc test"

test_cases: {
  name: "add-header"
  description: "Verify ExtProc adds a custom header"
  tags: ["smoke"]

  request: {
    method: "GET"
    path: "/api/v1/users"
    scheme: "https"
    authority: "api.example.com"
    headers: {
      key: "content-type"
      value: "application/json"
    }
  }

  expectations: {
    phase: REQUEST_HEADERS
    headers_response: {
      set_headers: {
        key: "x-custom-header"
        value: "custom-value"
      }
    }
  }
}

2. Run the Tests

extproctor run ./tests/ --target localhost:50051

3. View Results

Running tests from 1 manifest(s)...

✓ basic-test/add-header (12ms)

Results: 1 passed, 0 failed, 0 skipped

Documentation

CLI Commands

extproctor run

Execute tests against an ExtProc service.

# Run all tests in a directory
extproctor run ./tests/ --target localhost:50051

# Run with Unix domain socket
extproctor run ./tests/ --unix-socket /var/run/extproc.sock

# Run with parallel execution
extproctor run ./tests/ --target localhost:50051 --parallel 4

# Filter by test name pattern
extproctor run ./tests/ --target localhost:50051 --filter "auth*"

# Filter by tags
extproctor run ./tests/ --target localhost:50051 --tags "smoke,regression"

# JSON output for CI pipelines
extproctor run ./tests/ --target localhost:50051 --output json

# Verbose mode for debugging
extproctor run ./tests/ --target localhost:50051 -v

# Update golden files
extproctor run ./tests/ --target localhost:50051 --update-golden

extproctor validate

Validate manifest syntax without running tests.

# Validate all manifests in a directory
extproctor validate ./tests/

# Validate specific files
extproctor validate test1.textproto test2.textproto

Command-Line Options

FlagDescriptionDefault
--targetExtProc service address (host:port)localhost:50051
--unix-socketUnix domain socket path
--tlsEnable TLS for gRPC connectionfalse
--tls-certTLS client certificate file
--tls-keyTLS client key file
--tls-caTLS CA certificate file
-p, --parallelNumber of parallel test executions1
-o, --outputOutput format (human, json)human
-v, --verboseEnable verbose outputfalse
--filterFilter tests by name pattern
--tagsFilter tests by tags (comma-separated)
--update-goldenUpdate golden files with actual responsesfalse

Note: --target and --unix-socket are mutually exclusive.

Manifest Format

Test manifests are written in Prototext format.

Structure

name: "manifest-name"
description: "Description of the test suite"

test_cases: {
  name: "test-case-name"
  description: "What this test validates"
  tags: ["tag1", "tag2"]

  request: {
    method: "POST"
    path: "/api/endpoint"
    scheme: "https"
    authority: "api.example.com"
    headers: {
      key: "content-type"
      value: "application/json"
    }
    body: '{"key": "value"}'
    process_request_body: true
    process_response_headers: true
  }

  expectations: {
    phase: REQUEST_HEADERS
    headers_response: {
      set_headers: {
        key: "x-custom"
        value: "value"
      }
    }
  }
}

Processing Phases

PhaseDescription
REQUEST_HEADERSProcessing request headers
REQUEST_BODYProcessing request body
REQUEST_TRAILERSProcessing request trailers
RESPONSE_HEADERSProcessing response headers
RESPONSE_BODYProcessing response body
RESPONSE_TRAILERSProcessing response trailers

Expectation Types

Headers Response
expectations: {
  phase: REQUEST_HEADERS
  headers_response: {
    set_headers: {
      key: "x-custom"
      value: "value"
    }
    remove_headers: "x-internal"
    append_headers: {
      key: "x-multi"
      value: "value"
    }
  }
}
Body Response
expectations: {
  phase: REQUEST_BODY
  body_response: {
    body: '{"modified": true}'
    common_response: {
      status: CONTINUE_AND_REPLACE
    }
  }
}
Trailers Response
expectations: {
  phase: REQUEST_TRAILERS
  trailers_response: {
    set_trailers: {
      key: "x-checksum-validated"
      value: "true"
    }
  }
}
Immediate Response (Short-circuit)
expectations: {
  phase: REQUEST_HEADERS
  immediate_response: {
    status_code: 403
    headers: {
      key: "content-type"
      value: "application/json"
    }
    body: '{"error": "forbidden"}'
  }
}

Golden Files

Use golden files for snapshot testing:

test_cases: {
  name: "golden-test"
  request: { ... }
  golden_file: "golden/test-response.textproto"
}

Update golden files when behavior changes intentionally:

extproctor run ./tests/ --target localhost:50051 --update-golden

Examples

The testdata/examples/ directory contains complete example manifests:

FileDescription
basic_headers.textprotoBasic header processing (add/remove headers)
auth_flow.textprotoAuthentication flow with immediate response rejection
body_processing.textprotoRequest body inspection and transformation
multi_phase_flow.textprotoMulti-phase processing across request/response lifecycle

Sample ExtProc Server

A sample ExtProc server is included for testing and reference:

# Start the sample server
go run ./sample/extproc/ --addr :50051

# Run tests against it
extproctor run ./sample/extproc/test/ --target localhost:50051

The sample server demonstrates:

  • Request headers processing with custom header injection
  • Request/response body handling
  • Response headers modification
  • gRPC health check endpoint

Development

Prerequisites

Building

go build -o extproctor ./cmd/extproctor

Running Tests

go test ./...

Regenerating Protobuf Code

buf generate

Project Structure

extproctor/
├── cmd/extproctor/          # CLI entry point
├── internal/
│   ├── cli/              # Command-line interface
│   ├── client/           # ExtProc gRPC client
│   ├── comparator/       # Response comparison logic
│   ├── golden/           # Golden file handling
│   ├── manifest/         # Manifest loading and validation
│   ├── reporter/         # Test result reporting
│   └── runner/           # Test execution engine
├── proto/                # Protobuf definitions
├── sample/extproc/       # Sample ExtProc server
└── testdata/examples/    # Example test manifests

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  • Fork the repository
  • Create your feature branch (git checkout -b feature/amazing-feature)
  • Commit your changes (git commit -m 'Add some amazing feature')
  • Push to the branch (git push origin feature/amazing-feature)
  • Open a Pull Request

Please make sure to:

  • Update tests as appropriate
  • Follow the existing code style
  • Update documentation for any new features

License

This project is licensed under the MIT License - see the LICENSE file for details.

Made with ❤️ for the Envoy community

FAQs

Package last updated on 17 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts