MVFC.Aspire.Helpers.ApigeeEmulator
9.0.0
See the version list below for details.
dotnet add package MVFC.Aspire.Helpers.ApigeeEmulator --version 9.0.0
NuGet\Install-Package MVFC.Aspire.Helpers.ApigeeEmulator -Version 9.0.0
<PackageReference Include="MVFC.Aspire.Helpers.ApigeeEmulator" Version="9.0.0" />
<PackageVersion Include="MVFC.Aspire.Helpers.ApigeeEmulator" Version="9.0.0" />
<PackageReference Include="MVFC.Aspire.Helpers.ApigeeEmulator" />
paket add MVFC.Aspire.Helpers.ApigeeEmulator --version 9.0.0
#r "nuget: MVFC.Aspire.Helpers.ApigeeEmulator, 9.0.0"
#:package MVFC.Aspire.Helpers.ApigeeEmulator@9.0.0
#addin nuget:?package=MVFC.Aspire.Helpers.ApigeeEmulator&version=9.0.0
#tool nuget:?package=MVFC.Aspire.Helpers.ApigeeEmulator&version=9.0.0
MVFC.Aspire.Helpers.ApigeeEmulator
π§π· Leia em PortuguΓͺs
Helpers for integrating the Google Apigee Emulator with .NET Aspire projects, enabling local API proxy development and testing.
Motivation
Working with Apigee API proxies locally usually means:
- Spinning up the emulator container manually with the correct image and ports.
- Remembering to build and deploy the proxy bundle (ZIP) every time you make changes.
- Manually configuring TargetServers to point at your backend services.
- Dealing with
host.docker.internaland port mismatches between your host and Docker.
With .NET Aspire you can define containers, but you still need to:
- Configure the emulator image, control port, and traffic port.
- Build and deploy your apiproxy bundle to the emulator on startup.
- Dynamically wire TargetServers to match the Aspire-allocated backend ports.
MVFC.Aspire.Helpers.ApigeeEmulator provides:
AddApigeeEmulator(...)to start the emulator with sensible defaults.WithWorkspace(...)to point at your local proxy bundle and define a proxy health endpoint.WithEnvironment(...)to set the Apigee environment name.WithBackend(...)to automatically resolve Aspire backend endpoints as TargetServers.
Overview
This project facilitates the configuration and integration of the Apigee Emulator in distributed .NET Aspire applications, providing extension methods to:
- Add the Apigee Emulator container with pre-configured ports.
- Deploy the proxy bundle (
apiproxy) automatically on startup. - Dynamically inject TargetServer configurations pointing at Aspire-managed backends.
- Merge static and dynamic
targetservers.jsondefinitions for hybrid scenarios.
Apigee Emulator advantages
- Develop and test API proxies locally without a Google Cloud account.
- Validate traffic policies, security flows, and SharedFlows before pushing to production.
- Support Trace/Debug sessions for request inspection.
- Integrate emulator traffic with Aspire-managed backend services.
Compatible Images
- Emulator
gcr.io/apigee-release/hybrid/apigee-emulator(default in this helper)
Project Structure
MVFC.Aspire.Helpers.ApigeeEmulator: Helpers and extensions library for Apigee Emulator.
Features
- Adds the Apigee Emulator container with default image and ports.
- Deploys the proxy bundle automatically when the emulator is ready.
- Resolves Aspire backend ports and injects TargetServer configurations.
- Merges existing static
targetservers.jsonwith dynamically generated entries. - Provides fluent AppHost configuration methods.
Installation
dotnet add package MVFC.Aspire.Helpers.ApigeeEmulator
Quick Aspire usage (AppHost)
using Aspire.Hosting;
using MVFC.Aspire.Helpers.ApigeeEmulator;
var builder = DistributedApplication.CreateBuilder(args);
var apigeeWorkspace = Path.Combine(
Directory.GetCurrentDirectory(),
"apigee-workspace");
var api = builder.AddProject<Projects.MyApi>("my-api");
var apigee = builder.AddApigeeEmulator("apigee-emulator")
.WithWorkspace(
workspacePath: apigeeWorkspace,
healthCheckPath: "/demo/health-check")
.WithEnvironment("local")
.WithBackend(api, "origin");
await builder.Build().RunAsync();
If WithWorkspace(...) is not called, the emulator container still starts normally, but no proxy bundle is deployed automatically.
This is useful for manual emulator testing or when you want to control deployment outside the helper.
Ports
| Port | Default | Description |
|---|---|---|
| Control | 7071 β 8080 (container) |
Management and deploy API |
| Traffic | 8998 β 8998 (container) |
API gateway traffic |
Provisioning diagram
sequenceDiagram
participant Aspire as .NET Aspire
participant Container as Apigee Emulator Container
participant Hook as Deploy Lifecycle Hook
participant Backend as Aspire Backend
Aspire->>Container: Start container (apigee-emulator)
Container-->>Aspire: Ready (control port available)
Aspire->>Hook: Trigger AfterResourcesCreatedEvent
Hook->>Backend: Wait for backend Running state
Backend-->>Hook: Running (port resolved)
Hook->>Hook: Build ZIP (merge targetservers.json)
Hook->>Container: POST /v1/emulator/deploy
Container-->>Hook: Deploy successful
Hook-->>Aspire: Deployment completed
Public methods
AddApigeeEmulatorβ Adds the emulator container with default image and ports.WithWorkspaceβ Sets the local path to the apiproxy bundle and the proxy health check path.WithEnvironmentβ Sets the Apigee environment name (default:"local").WithDockerImageβ Overrides the Docker image and tag.WithBackendβ Configures an Aspire backend as a TargetServer for the proxy.
Runtime behavior
- The helper waits until the emulator resource reaches the
Runningstate before deployment. - It also waits for configured backend resources to become available before generating TargetServers.
- The apiproxy bundle is copied to a temporary directory, optionally merged with dynamic
targetservers.json, zipped, deployed, and then cleaned up. - Backend resolution supports both Aspire projects and container resources.
Troubleshooting
Container does not become ready
- The first startup may take longer because the emulator image needs to be downloaded locally.
- Pull the image manually before running Aspire if startup time becomes an issue:
docker pull gcr.io/apigee-release/hybrid/apigee-emulator - Check whether Docker is running and able to create containers normally.
Bundle deploy is skipped
- Automatic deploy only happens when
WithWorkspace(...)is configured with both a workspace path and a proxy health endpoint. - If those values are not set, the container still starts, but the helper intentionally skips deployment.
Backend is unreachable from the emulator
- When using
.WithBackend(...), the helper configures the backend endpoint to bypass the Aspire proxy. - For ASP.NET Core projects, it also forces the backend to bind to
0.0.0.0, which is required for Docker-to-host access. - If you configure the backend manually, make sure the service listens on an address reachable from Docker.
host.docker.internal issues on Linux
- On Linux, the helper adds
--add-host host.docker.internal:host-gatewayautomatically. - If Docker still cannot resolve it, verify that your Docker Engine supports
host-gateway.
Port already in use
- Override the default ports if
7071or8998are already occupied:builder.AddApigeeEmulator( name: "apigee-emulator", controlPort: 7072, trafficPort: 8999);
Proxy health check never succeeds
- Confirm that the
healthCheckPathpassed toWithWorkspace(...)is a valid route exposed by your deployed proxy. - If the proxy deploys successfully but that route returns non-success status codes, Aspire startup may continue retrying until timeout.
Playground proxy (example only)
The sections below document the example proxy included in the
playground/folder. They describe the sample Apigee proxy used to demonstrate the helper in a realistic setup. They are not required to use the NuGet package itself.
Architecture and policies of the example proxy
After validating the example project and the final configuration present in proxies/default.xml, this document reflects the actual routing structure, request flow, and configured policies.
General flow diagram
flowchart TD
A["Request β /demo/*"] --> B{"Method / Route?"}
B -->|OPTIONS| C["CORS Preflight (AM-Cors) β 200 No Backend"]
B -->|DELETE/PUT/PATCH| D["Method Not Allowed (RF) β 405"]
B -->|/sharedflow-check| Q["SharedFlow Check (FC-CallLogging)"]
B -->|/spike-arrest| E["Spike Arrest Test (SA-SpikeArrest)"]
B -->|/notfound| F["Not Found Demo (RF-NotFound) β 404"]
B -->|/transform| G["Transform Envelope (JS-TransformResponse)"]
B -->|/quota-test| H["Quota Rate Limit (QU-RateLimit)"]
B -->|/health-check| I["Health Check (ServiceCallout + AM)"]
B -->|/cached| J{"Cache Hit? (LookupCache)"}
B -->|/admin| K["Admin Panel (AccessControl IP)"]
B -->|/secure| L["Secure Resource (BasicAuth + JS Valid.)"]
B -->|/xml| M["XML to JSON Format Convert"]
B -->|/status/**| N["TargetRule: public (httpbin)"]
B -->|Others| O["TargetRule: default (origin)"]
J -->|Yes| J1["AM-CacheHit β Responds 200"]
J -->|No| J2["Target Backend β Populates PC-Cache + AM-Miss"]
E & G & H & I & J2 & K & L & M & N & O & Q --> P["PostFlow: Adds CORS + Custom Headers + FC-CallLogging"]
Policies implemented directly in flows
| Route / Flow | Used Policies | Practical Goal in Current Project |
|---|---|---|
/sharedflow-check |
FC-CallLogging.xml |
Verifies integration with the common-logging SharedFlow by injecting execution headers and metadata. |
/spike-arrest |
SA-SpikeArrest.xml |
Blocks interactions that exceed immediate static volumetry. |
OPTIONS (All) |
AM-CorsPreflightResponse.xml |
Handles preflight validation and avoids backend forwarding. |
DELETE, PUT, PATCH |
RF-MethodNotAllowed.xml |
Raises a fault for disallowed methods in this demo proxy. |
/notfound |
RF-NotFound.xml |
Produces an artificial 404 response quickly through RaiseFault. |
/transform |
JS-TransformResponse.xml |
Wraps backend responses using JavaScript in the response pipeline. |
/quota-test |
QU-RateLimit.xml |
Restricts transactions under a defined quota window. |
/health-check |
SC-HealthCheck.xml, EV-HealthStatus.xml, AM-SetHealthHeader.xml |
Calls a dependency, extracts state, and enriches headers with the result. |
/cached |
LC-ResponseCache.xml, AM-CacheHit.xml, PC-ResponseCache.xml, AM-CacheMissHeader.xml |
Reads and populates response cache depending on hit or miss. |
/admin |
AC-AllowLocalOnly.xml |
Restricts access based on allowed IP ranges. |
/secure |
BA-DecodeBasicAuth.xml, JS-ValidateCredentials.xml, RF-Unauthorized.xml |
Validates Basic Auth credentials and raises Unauthorized when invalid. |
/xml |
X2J-ConvertResponse.xml |
Converts XML responses to JSON before returning to the caller. |
PostFlow policies
Whether the response comes from backend success, an intercepted response, or a planned error, the PostFlow enriches the outgoing message:
AM-AddCorsHeaders.xml: Adds headers required to avoid browser CORS issues.AM-AddCustomHeaders.xml: Appends extra request and tracking metadata.FC-CallLogging.xml: Delegates shared logging behavior to thecommon-loggingSharedFlow.
Global faults
AM-DefaultFaultResponse.xml: Standardizes the JSON fault payload when Apigee raises an unhandled system error.
Requirements
- .NET 9+
- Aspire.Hosting >= 9.5.0
- Docker running locally
License
Apache-2.0
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Aspire.Hosting (>= 13.1.2)
-
net9.0
- Aspire.Hosting (>= 13.1.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 9.0.3 | 105 | 4/12/2026 |
| 9.0.2 | 93 | 4/12/2026 |
| 9.0.1 | 99 | 4/12/2026 |
| 9.0.0 | 101 | 4/12/2026 |
| 8.0.2 | 98 | 4/11/2026 |
| 8.0.1 | 110 | 4/3/2026 |
| 8.0.0 | 101 | 4/2/2026 |
| 7.3.3 | 104 | 3/31/2026 |
| 7.3.2 | 102 | 3/30/2026 |
| 7.3.1 | 103 | 3/30/2026 |
| 7.3.0 | 101 | 3/30/2026 |
| 7.2.2 | 112 | 3/29/2026 |
| 7.2.1 | 101 | 3/29/2026 |
| 7.2.0 | 105 | 3/29/2026 |