## File: README.md
# Easegress
[](https://goreportcard.com/report/github.com/easegress-io/easegress)
[](https://github.com/easegress-io/easegress/actions/workflows/test.yml)
[](https://codecov.io/gh/easegress-io/easegress)
[](https://hub.docker.com/r/megaease/easegress)
[](https://opensource.org/licenses/Apache-2.0)
[](https://github.com/easegress-io/easegress/blob/main/go.mod)
[](https://cloud-native.slack.com/messages/easegress)
[](https://www.bestpractices.dev/projects/8265)
[](https://app.fossa.com/projects/git%2Bgithub.com%2Feasegress-io%2Feasegress?ref=badge_shield)
- [What is Easegress](#what-is-easegress)
- [Features](#features)
- [Getting Started](#getting-started)
- [Launch Easegress](#launch-easegress)
- [Reverse Proxy](#reverse-proxy)
- [Use Cases](#use-cases)
- [Documentation](#documentation)
- [Easegress Portal](#easegress-portal)
- [Screenshots](#screenshots)
- [Community](#community)
- [Contributing](#contributing)
- [License](#license)
## What is Easegress
`Easegress` is a Cloud Native traffic orchestration system designed for:
- **High Availability:** Built-in Raft consensus & leader election provides 99.99% availability.
- **Traffic Orchestration:** Simple orchestration of various filters for each traffic pipeline.
- **High Performance:** Lightweight and essential features speed up the performance.
- **Observability:** There are many meaningful statistics periodically in a readable way.
- **Extensibility:** It's easy to develop your own filter or controller with high-level programming language.
- **Integration:** The simple interfaces make it easy to integrate with other systems, such as Kubernetes Ingress, [EaseMesh](https://github.com/megaease/easemesh) sidecar, Workflow, etc.
The architecture of Easegress:
And you can check [Easegress DeepWiki Page](https://deepwiki.com/easegress-io/easegress) to dive into more details.
## Features
- **Service Management**
- **Multiple protocols:**
- HTTP/1.1
- HTTP/2
- HTTP/3(QUIC)
- MQTT
- **Rich Routing Rules:** exact path, path prefix, regular expression of the path, method, headers, clientIPs.
- **Resilience&Fault Tolerance**
- **CircuitBreaker:** temporarily blocks possible failures.
- **RateLimiter:** limits the rate of incoming requests.
- **Retry:** repeats failed executions.
- **TimeLimiter:** limits the duration of execution.
- **Deployment Management**
- **Blue-green Strategy:** switches traffic at one time.
- **Canary Strategy:** schedules traffic slightly.
- **API Management**
- **API Aggregation:** aggregates results of multiple APIs.
- **API Orchestration:** orchestrates the flow of APIs.
- **Security**
- **IP Filter:** Limits access to IP addresses.
- **Static HTTPS:** static certificate files.
- **API Signature:** supports [HMAC](https://en.wikipedia.org/wiki/HMAC) verification.
- **JWT Verification:** verifies [JWT Token](https://jwt.io/).
- **OAuth2:** validates [OAuth/2](https://datatracker.ietf.org/doc/html/rfc6749) requests.
- **Let's Encrypt:** automatically manage certificate files.
- **Pipeline-Filter Mechanism**
- **Filter Management:** makes it easy to develop new filters.
- **Service Mesh**
- **Mesh Master:** is the control plane to manage the lifecycle of mesh services.
- **Mesh Sidecar:** is the data plane as the endpoint to do traffic interception and routing.
- **Mesh Ingress Controller:** is the mesh-specific ingress controller to route external traffic to mesh services.
> Notes: This feature is leveraged by [EaseMesh](https://github.com/megaease/easemesh)
- **Third-Part Integration**
- **FaaS** integrates with the serverless platform Knative.
- **Service Discovery** integrates with Eureka, Consul, Etcd, and Zookeeper.
- **Ingress Controller** integrates with Kubernetes as an ingress controller.
- **Extensibility**
- **WebAssembly** executes user developed [WebAssembly](https://webassembly.org/) code.
- **High Performance and Availability**
- **Adaption**: adapts request, response in the handling chain.
- **Validation**: headers validation, OAuth2, JWT, and HMAC verification.
- **Load Balance:** round-robin, random, weighted random, IP hash, header hash and support sticky sessions.
- **Cache:** for the backend servers.
- **Compression:** compresses body for the response.
- **Hot-Update:** updates both config and binary of Easegress in place without losing connections.
- **Operation**
- **Easy to Integrate:** command line([egctl](docs/02.Tutorials/2.1.egctl-Usage.md)), Easegress Portal, HTTP clients such as curl, postman, etc.
- **Distributed Tracing**
- Built-in [OpenTelemetry](https://opentelemetry.io/), which provides a vendor-neutral API.
- **Observability**
- **Node:** role(primary, secondary), raft leader status, healthy or not, last heartbeat time, and so on
- **Traffic:** in multi-dimension: server and backend.
- **Throughput:** total and error statistics of request count, TPS/m1, m5, m15, and error percent, etc.
- **Latency:** p25, p50, p75, p95, p98, p99, p999.
- **Data Size:** request and response size.
- **Status Codes:** HTTP status codes.
- **TopN:** sorted by aggregated APIs(only in server dimension).
- **AI Integration**
- **Proxy:** proxy requests to LLM providers like OpenAI, DeepSeek, Anthropic, etc.
- **Anthropic API Adaption:** adapts requests and responses in Anthropic API to OpenAI format.
- **Vector Database:** integrates with vector databases for caching.
- **Monitoring:** provides insights into the performance and usage of AI models.
## Getting Started
The basic usage of Easegress is to quickly set up a proxy for the backend servers.
### Launch Easegress
Easegress can be installed from pre-built binaries or from source. For details, see [Install](docs/01.Getting-Started/1.2.Install.md).
Then we can execute the server:
```bash
$ easegress-server
2023-09-06T15:12:49.256+08:00 INFO cluster/config.go:110 config: advertise-client-urls: ...
...
```
By default, Easegress opens ports 2379, 2380, and 2381; however, you can modify these settings along with other arguments either in the configuration file or via command-line arguments. For a complete list of arguments, please refer to the `easegress-server --help` command.
After launching successfully, we could check the status of the one-node cluster.
```bash
$ egctl get member
...
$ egctl describe member
...
```
### Reverse Proxy
Assuming you have two backend HTTP services running at `127.0.0.1:9095` and `127.0.0.1:9096`, you can initiate an HTTP proxy from port 10080 to these backends using the following command:
```bash
$ egctl create httpproxy demo --port 10080 \
--rule="/pipeline=http://127.0.0.1:9095,http://127.0.0.1:9096"
```
Then try it:
```bash
curl -v 127.0.0.1:10080/pipeline
```
The request will be forwarded to either `127.0.0.1:9095/pipeline` or `127.0.0.1:9096/pipeline`, utilizing a round-robin load-balancing policy.
More about getting started with Easegress:
- [Quick Start](docs/01.Getting-Started/1.1.Quick-Start.md)
- [Install Easegress](docs/01.Getting-Started/1.2.Install.md)
- [Main Concepts](docs/01.Getting-Started/1.3.Concepts.md)
## Use Cases
The following examples show how to use Easegress for different scenarios.
- [API Aggregation](docs/02.Tutorials/2.3.Pipeline-Explained.md#api-aggregation) - Aggregating many APIs into a single API.
- [Cluster Deployment](docs/05.Administration/5.1.Config-and-Cluster-Deployment.md) - How to deploy multiple Easegress cluster nodes.
- [Canary Release](docs/03.Advanced-Cookbook/3.04.Canary-Release.md) - How to do canary release with Easegress.
- [Distributed Tracing](docs/03.Advanced-Cookbook/3.05.Distributed-Tracing.md) - How to do APM tracing - Zipkin.
- [FaaS](docs/03.Advanced-Cookbook/3.09.FaaS.md) - Supporting Knative FaaS integration
- [Flash Sale](docs/03.Advanced-Cookbook/3.09.FaaS.md) - How to do high concurrent promotion sales with Easegress
- [Kubernetes Ingress Controller](docs/04.Cloud-Native/4.1.Kubernetes-Ingress-Controller.md) - How to integrate with Kubernetes as ingress controller
- [LoadBalancer](docs/02.Tutorials/2.3.Pipeline-Explained.md#load-balancer) - A number of the strategies of load balancing
- [MQTTProxy](docs/03.Advanced-Cookbook/3.01.MQTT-Proxy.md) - An Example to MQTT proxy with Kafka backend.
- [Multiple API Orchestration](docs/03.Advanced-Cookbook/3.03.Multiple-API-Orchestration.md) - An Telegram translation bot.
- [Performance](docs/03.Advanced-Cookbook/3.11.Performance.md) - Performance optimization - compression, caching etc.
- [Pipeline](docs/02.Tutorials/2.3.Pipeline-Explained.md) - How to orchestrate HTTP filters for requests/responses handling
- [Resilience and Fault Tolerance](docs/02.Tutorials/2.4.Resilience.md) - CircuitBreaker, RateLimiter, Retry, TimeLimiter, etc. (Porting from [Java resilience4j](https://github.com/resilience4j/resilience4j))
- [Security](docs/02.Tutorials/2.5.Traffic-Verification.md) - How to do authentication by Header, JWT, HMAC, OAuth2, etc.
- [Service Registry](docs/03.Advanced-Cookbook/3.06.Service-Registry.md) - Supporting the Microservice registries - Zookeeper, Eureka, Consul, Nacos, etc.
- [WebAssembly](docs/03.Advanced-Cookbook/3.07.WasmHost.md) - Using AssemblyScript to extend the Easegress
- [WebSocket](docs/02.Tutorials/2.6.Websocket.md) - WebSocket proxy for Easegress
- [Workflow](docs/03.Advanced-Cookbook/3.10.Workflow.md) - An Example to make a workflow for a number of APIs.
For full list, see [Tutorials](docs/02.Tutorials/README.md) and [Cookbook](docs/03.Advanced-Cookbook/README.md).
## Documentation
- [Getting Started](docs/01.Getting-Started/README.md)
- [Tutorials](docs/02.Tutorials/README.md)
- [Advanced Cookbook](docs/03.Advanced-Cookbook/README.md)
- [Cloud Native](docs/04.Cloud-Native/README.md)
- [Administration](docs/05.Administration/README.md)
- [Development](docs/06.Development-for-Easegress/README.md)
- [Reference](docs/07.Reference/README.md)
## Easegress Portal
[Easegress Portal](https://github.com/easegress-io/easegress-portal) is an intuitive, open-source user interface for the Easegress traffic orchestration system. Developed with React.js, this portal provides config management, metrics, and visualizations, enhancing the overall Easegress experience.
### Screenshots
**1. Cluster Management**
**2. Traffic Management**
**3. Pipeline Management**
## Community
- Open [GitHub issues](https://github.com/easegress-io/easegress/issues/new/choose) for bugs, feature requests, questions, and documentation problems.
- Join the [Easegress Slack channel](https://cloud-native.slack.com/messages/easegress) for public development discussion.
- Report security vulnerabilities privately to Yun Long .
### Community Tools
- [KubeStellar Console Guided Install](https://console.kubestellar.io/missions/install-easegress) - Step-by-step guided installation with pre-flight checks, validation, troubleshooting, and rollback.
## Contributing
See [Contributing guide](./CONTRIBUTING.md#contributing). The project welcomes contributions and suggestions that abide by the [CNCF Code of Conduct](./CODE_OF_CONDUCT.md).
## License
Easegress is under the Apache 2.0 license. See the [LICENSE](./LICENSE) file for details.
[](https://app.fossa.com/projects/git%2Bgithub.com%2Feasegress-io%2Feasegress?ref=badge_large)
---
## File: doc/cookbook/k8s-ingress-controller.md
This document has been moved to [here](../../docs/04.Cloud-Native/4.1.Kubernetes-Ingress-Controller.md).
---
## File: doc/reference/ingresscontroller.md
This document has been moved to [here](../../docs/07.Reference/7.03.Ingress-Controller.md).
---
## File: doc/ingresscontroller.md
This document has been moved to [here](../docs/07.Reference/7.03.Ingress-Controller.md).
---
## File: docs/07.Reference/7.01.Controllers.md
# Controllers
- [System Controllers](#system-controllers)
- [ServiceRegistry](#serviceregistry)
- [TrafficController](#trafficcontroller)
- [RawConfigTrafficController](#rawconfigtrafficcontroller)
- [HTTPServer](#httpserver)
- [AccessLogVariable](#accesslogvariable)
- [GRPCServer](#grpcserver)
- [Pipeline](#pipeline)
- [StatusSyncController](#statussynccontroller)
- [Business Controllers](#business-controllers)
- [GlobalFilter](#globalfilter)
- [EaseMonitorMetrics](#easemonitormetrics)
- [FaaSController](#faascontroller)
- [IngressController](#ingresscontroller)
- [ConsulServiceRegistry](#consulserviceregistry)
- [EtcdServiceRegistry](#etcdserviceregistry)
- [EurekaServiceRegistry](#eurekaserviceregistry)
- [ZookeeperServiceRegistry](#zookeeperserviceregistry)
- [NacosServiceRegistry](#nacosserviceregistry)
- [AutoCertManager](#autocertmanager)
- [AIGatewayController](#aigatewaycontroller)
- [WAFController](#wafcontroller)
- [Common Types](#common-types)
- [tracing.Spec](#tracingspec)
- [spanlimits.Spec](#spanlimitsspec)
- [batchlimits.Spec](#batchlimitsspec)
- [exporter.Spec](#exporterspec)
- [jaeger.Spec](#jaegerspec)
- [zipkin.Spec](#zipkinspec)
- [otlp.Spec](#otlpspec)
- [zipkin.DeprecatedSpec](#zipkindeprecatedspec)
- [ipfilter.Spec](#ipfilterspec)
- [httpserver.Rule](#httpserverrule)
- [httpserver.Host](#httpserverhost)
- [httpserver.Path](#httpserverpath)
- [httpserver.Header](#httpserverheader)
- [pipeline.Spec](#pipelinespec)
- [pipeline.FlowNode](#pipelineflownode)
- [filters.Filter](#filtersfilter)
- [grpcserver.Rule](#grpcserverrule)
- [grpcserver.Method](#grpcservermethod)
- [grpcserver.Header](#grpcserverheader)
- [easemonitormetrics.Kafka](#easemonitormetricskafka)
- [nacos.ServerSpec](#nacosserverspec)
- [autocertmanager.DomainSpec](#autocertmanagerdomainspec)
- [resilience.Policy](#resiliencepolicy)
- [Retry Policy](#retry-policy)
- [CircuitBreaker Policy](#circuitbreaker-policy)
- [AIGatewayController.ProviderSpec](#aigatewaycontrollerproviderspec)
- [Supported Providers](#supported-providers)
- [AIGatewayController.MiddlewareSpec](#aigatewaycontrollermiddlewarespec)
- [AIGatewayController.SemanticCacheSpec](#aigatewaycontrollersemanticcachespec)
- [AIGatewayController.EmbeddingSpec](#aigatewaycontrollerembeddingspec)
- [AIGatewayController.VectorDBSpec](#aigatewaycontrollervectordbspec)
- [AIGatewayController.RedisSpec](#aigatewaycontrollerredisspec)
- [AIGatewayController.PostgresSpec](#aigatewaycontrollerpostgresspec)
- [AIGatewayController.QdrantSpec](#aigatewaycontrollerqdrantspec)
- [WAFController.RuleGroupSpec](#wafcontrollerrulegroupspec)
- [WAFController.RuleSpec](#wafcontrollerrulespec)
- [WAFController.IPBlockerSpec](#wafcontrolleripblockerspec)
- [WAFController.GeoIPBlockerSpec](#wafcontrollergeoipblockerspec)
As the [architecture diagram](../imgs/architecture.png) shows, the controller is the core entity to control kinds of working. There are two kinds of controllers overall:
- System Controller: It is created one and only one instance in every Easegress node, which can't be deleted. They mainly aim to control essential system-level stuff.
- Business Controller: It could be created, updated, deleted by admin operation. They control various resources such as mesh traffic, service discovery, faas, and so on.
In another view, Easegress as a traffic orchestration system, we could classify them into traffic controller and non-traffic controller:
- Traffic Controller: It invokes TrafficController to handle its specific traffic, such as MeshController.
- Non-Traffic Controller: It doesn't handle business traffic, such as EurekaServiceRegistry, even though it has admin traffic with Eureka.
The two categories are conceptual, which means they are not strict distinctions. We just use them as terms to clarify controllers technically.
## System Controllers
For now, all system controllers can not be configured. It may gain this capability if necessary in the future.
### ServiceRegistry
We use the system controller `ServiceRegistry` as the service hub for all service registries. Current drivers are
- [ConsulServiceRegistry](#consulserviceregistry)
- [EtcdServiceRegistry](#etcdserviceregistry)
- [EurekaServiceRegistry](#eurekaserviceregistry)
- [ZookeeperServiceRegistry](#zookeeperserviceregistry)
- [NacosServiceRegistry](#nacosserviceregistry)
The drivers need to offer notifying change periodically, and operations to the external service registry.
### TrafficController
TrafficController handles the lifecycle of Traffic Gates (like HTTPServer) and Pipeline and their relationship. It manages the resource in a namespaced way. Traffic gates accepts incoming traffic and routes it to Pipelines in the same namespace. Most other controllers could handle traffic by leverage the ability of TrafficController..
### RawConfigTrafficController
RawConfigTrafficController maps all traffic static configurations to TrafficController in the namespace `default`. We could use `egctl` to manage the configuration of servers and pipelines in the default namespace.
#### HTTPServer
HTTPServer is a server that listens on one port to route all traffic to available pipelines. Its simplest config looks like:
```yaml
kind: HTTPServer
name: http-server-example
port: 80
rules:
- paths:
- pathPrefix: /pipeline
backend: http-pipeline-example
```
| Name | Type | Description | Required |
| ---------------- | ---------------------------------- | ---------------------------------------------------------------------------------------- | -------------------- |
| http3 | bool | Whether to support HTTP3(QUIC) | No |
| port | uint16 | The HTTP port listening on | Yes |
| keepAlive | bool | Whether to support keepalive | Yes (default: false) |
| keepAliveTimeout | string | The timeout of keepalive | Yes (default: 60s) |
| maxConnections | uint32 | The max connections with clients | Yes (default: 10240) |
| https | bool | Whether to use HTTPS | Yes (default: false) |
| cacheSize | uint32 | The size of cache, 0 means no cache | No |
| xForwardedFor | bool | Whether to set X-Forwarded-For header by own ip | No |
| tracing | [tracing.Spec](#tracingspec) | Distributed tracing settings | No |
| certBase64 | string | Public key of PEM encoded data in base64 encoded format | No |
| keyBase64 | string | Private key of PEM encoded data in base64 encoded format | No |
| certs | map[string]string | Public keys of PEM encoded data, the key is the logic pair name, which must match keys | No |
| keys | map[string]string | Private keys of PEM encoded data, the key is the logic pair name, which must match certs | No |
| ipFilter | [ipfilter.Spec](#ipfilterspec) | IP Filter for all traffic under the server | No |
| routerKind | string | Kind of router. see [routers](7.06.Routers.md) | No (default: Order) |
| rules | [][httpserver.Rule](#httpserverrule) | Router rules | No |
| autoCert | bool | Do HTTP certification automatically | No |
| clientMaxBodySize | int64 | Max size of request body. the default value is 4MB. Requests with a body larger than this option are discarded. When this option is set to `-1`, Easegress takes the request body as a stream and the body can be any size, but some features are not possible in this case, please refer [Stream](7.05.Stream.md) for more information. | No |
| caCertBase64 | string | Define the root certificate authorities that servers use if required to verify a client certificate by the policy in TLS Client Authentication. | No |
| globalFilter | string | Name of [GlobalFilter](#globalfilter) for all backends | No |
| accessLogFormat | string | Format of access log, default is `[{{Time}}] [{{RemoteAddr}} {{RealIP}} {{Method}} {{URI}} {{Proto}} {{StatusCode}}] [{{Duration}} rx:{{ReqSize}}B tx:{{RespSize}}B] [{{Tags}}]`, variable is delimited by "{{" and "}}", please refer [Access Log Variable](#accesslogvariable) for all built-in variables | No |
##### AccessLogVariable
| Name | Description |
| ---------------- | ----------------------------------------------------------------- |
| Time | Start time for handling the request |
| RemoteAddr | Network address that sent the request |
| RealIP | Real IP of the request |
| Method | HTTP method (GET, POST, PUT, etc.) for the request |
| URI | Unmodified request-target of the Request-Line |
| Proto | Protocol version for the request |
| StatusCode | HTTP status code for the response |
| Duration | Duration time for handing the request |
| ReqSize | Size read from the request |
| RespSize | Size write to the response |
| ReqHeaders | Request HTTP headers |
| RespHeaders | Response HTTP headers |
| Tags | Tags for handing the request |
#### GRPCServer
The `GRPCServer` in Easegress provides robust functionality tailored to gRPC protocol interactions. With its IP filtering feature, traffic can be selectively allowed or blocked, ensuring that only desired clients can communicate with the services. Additionally, the server's routing rules offer flexible methods to determine how each incoming request is processed and forwarded, based on host, method, headers, and other criteria.
``` yaml
name: server-grpc
kind: GRPCServer
port: 8080
# The maximum number of connections allowed by gRPC Server.
# Default value 10240
maxConnections: 10240
# IP Filter for all traffic under the server
ipFilter:
blockIPs: []
allowIPs: []
blockByDefault: false
# routing rules
rules:
# Rules for host matching.
# If not match, GRPCServer will check next rule.
- host:
hostRegexp:
methods:
- method: /Sale/AddProduct # Exact method match
backend: sale-pipeline
- methodPrefix: /IT # Matches method with the given prefix
backend: it-pipeline
- headers: # Matches by header
- key: x-geo-country
values: ["CN", "EU", "US"]
- key: user-agent
values: ["SaleClient/1.0.0"]
matchAllHeader: false
backend: header-pipeline
- methodRegexp: .* # Match by regexp
backend: other-pipeline
# more rules
- methods:
...
```
##### Example Requests
- A gRPC request with method `/Sale/AddProduct` will be routed to the `sale-pipeline`.
- Any request with a method starting with `/IT` (e.g., `/IT/UpdateSoftware`) will be directed to the `it-pipeline`.
- If a client sends a request with headers `x-geo-country` set to `CN` and `user-agent` set to `SaleClient/1.0.0`, it will be handled by the `header-pipeline`.
- All other requests (due to the wildcard `methodRegexp`) will be sent to the `other-pipeline`.
##### Configuration
The below parameters will help manage connections better
| Name | Type | Description | Required |
|------|------|-------------|----------|
| maxConnections | uint32 | The maximum number of connections allowed by gRPC Server , default value 10240, min is 1 | No |
| minTimeClientSendPing | duration | The minimum amount of time a client should wait before sending a keepalive ping, default value is 5 minutes | No |
| permitClintSendPingWithoutStream | duration | If true, server allows keepalive pings even when there are no active streams(RPCs). If false, and client sends ping when there are no active streams, server will send GOAWAY and close the connection. default false | No |
| maxConnectionIdle | duration | A duration for the amount of time after which an idle connection would be closed by sending a GoAway. Idleness duration is defined since the most recent time the number of outstanding RPCs became zero or the connection establishment. default value is infinity | No |
| maxConnectionAge | duration | A duration for the maximum amount of time a connection may exist before it will be closed by sending a GoAway. A random jitter of ±10% will be added to MaxConnectionAge to prevent connection storms. default value is infinity | No |
| maxConnectionAgeGrace | duration | An additive period after MaxConnectionAge after which the connection will be forcibly closed. default value is infinity | No |
| keepaliveTime | duration | After a duration of this time if the server doesn't see any activity it pings the client to see if the transport is still alive. If set below 1s, a minimum value of 1s will be used instead. default value is 2 hours. | No |
| keepaliveTimeout | duration | After having pinged for keepalive check, the server waits for a duration of Timeout and if no activity is seen even after that the connection is closed. default value is 20 seconds |No |
| ipFilter | [ipfilter.Spec](#ipfilterspec) | IP Filter for all traffic | No |
| rules | [][grpcserver.Rule](#grpcserverrule) | Router rules | No |
#### Pipeline
Pipeline is used to orchestrate filters. Its simplest config looks like:
```yaml
name: http-pipeline-example1
kind: Pipeline
flow:
- filter: proxy
filters:
- name: proxy
kind: Proxy
pools:
- servers:
- url: http://127.0.0.1:9095
```
The `flow` defines the execution order of filters. You can use `jumpIf` to
change the order.
For example, if a request’s header doesn’t have the key `X-Id` or its value
is not `user1` or `user2`, then the `validator` filter returns result `invalid`
and the pipeline jumps to `END`.
```yaml
name: http-pipeline-example2
kind: Pipeline
flow:
- filter: validator
jumpIf:
# END is a built-in filter, it stops the execution of the pipeline.
invalid: END
- filter: proxy
filters:
- name: validator
kind: Validator
headers:
X-Id:
values: ["user1", "user2"]
- name: proxy
kind: Proxy
pools:
- servers:
- url: http://127.0.0.1:9095
```
> `jumpIf` can only jump to filters behind the current filter.
The `resilience` field defines resilience policies, if a filter implements the `filters.Resiliencer` interface (for now, only the `Proxy` filter implements the interface), the pipeline injects the policies into the filter instance after creating it.
A filter can implement the `filters.Resiliencer` interface to support resilience. There are two kinds of resilience, `Retry` and `CircuitBreaker`. Check [resilience](../02.Tutorials/2.4.Resilience.md) for more details. The following config adds a retry policy to the proxy filter:
```yaml
name: http-pipeline-example3
kind: Pipeline
flow:
- filter: proxy
filters:
- name: proxy
kind: Proxy
pools:
- servers:
- url: http://127.0.0.1:9095
retryPolicy: retry
resilience:
- name: retry
kind: Retry
maxAttempts: 3
```
In this case, if `proxy` returns non-empty results, then resilience retry reruns the `proxy` filter until `proxy` returns empty results or gets the max attempts.
The `flow` also supports `namespace`, so the pipeline can support workflows that contain multiple requests and responses.
```yaml
name: http-pipeline-example4
kind: Pipeline
flow:
- filter: validator
jumpIf:
invalid: END
- filter: requestBuilderFoo
namespace: foo
- filter: proxyFoo
namespace: foo
- filter: requestBuilderBar
namespace: bar
- filter: proxyBar
namespace: bar
- filter: responseBuilder
filters:
- name: requestBuilder
kind: RequestBuilder
...
...
```
In this case, `requestBuilderFoo` creates a request in namespace `foo`, and `proxyFoo` sends `foo` request and puts the response into namespace `foo`. `requestBuilderBar` creates a request in namespace `bar` and `proxyBar` sends `bar` request and puts the response into namespace `bar`. Finally, `requestBuilder` creates a response and puts it into the default namespace.
> If not set, the filter works in the default namespace `DEFAULT`.
The `alias` in `flow` gives a filter an alias to help re-use the filter so that we can use the alias to distinguish each of its appearances in the flow.
```yaml
name: http-pipeline-example5
kind: Pipeline
flow:
- filter: validator
jumpIf:
invalid: proxy2
- filter: proxy
# when meeting filter END, the pipeline execution stops and returns.
- filter: END
- filter: proxy
alias: proxy2
- filter: responseAdaptor
filters:
- name: proxy
kind: Proxy
...
```
In this case, we give second `proxy` alias `proxy2`, so request is invalid, it jumps to second proxy.
The `data` field defines static user data for the pipeline, which can be
accessed by filters. For example, in the below pipeline, the body of the result
request of the RequestBuilder will be `hello world`, which is the value of
data item `foo`.
```yaml
name: http-pipeline-example6
kind: Pipeline
flow:
...
filters:
- name: requestBuilder
kind: RequestBuilder
template: |
body: {{.data.PIPELINE.foo}}
data:
foo: "hello world"
```
| Name | Type | Description | Required |
| ------------- | -------- | -------------- | -------------------- |
| flow | [][FlowNode](#pipelineflownode) | The execution order of filters, if empty, will use the order of the filter definitions. | No |
| filters | []map[string]interface{} | Defines filters, please refer [Filters](7.02.Filters.md) for details of a specific filter kind. | Yes |
| resilience | []map[string]interface{} | Defines resilience policies, please refer [Resilience Policy](#resiliencepolicy) for details of a specific resilience policy. | No |
| data | map[string]interface{} | Static user data of the pipeline. | No |
### StatusSyncController
No config.
## Business Controllers
### GlobalFilter
`GlobalFilter` is a special pipeline that can be executed before or/and after all pipelines in a server. For example:
```yaml
name: globalFilter-example
kind: GlobalFilter
beforePipeline:
flow:
- filter: validator
filters:
- name: validator
kind: Validator
...
# fallthrough controls the error handling behavior in different pipelines.
# specifying whether subsequent stages should execute despite encountering errors in earlier stages.
# By default, encountering an error in either the beforePipeline or the pipeline stages halts the entire process.
fallthrough:
# false indicates that if an error occurs in the beforePipeline, the pipeline will not execute.
beforePipeline: false
# false means that if an error occurs in the pipeline, the afterPipeline will not execute.
pipeline: false
---
name: server-example
kind: HTTPServer
globalFilter: globalFilter-example
...
```
In this case, all requests in HTTPServer `server-example` go through GlobalFilter `globalFilter-example` before executing any other pipelines.
| Name | Type | Description | Required |
|------|------|-------------|----------|
| beforePipeline | [pipeline.Spec](#pipelinespec) | Spec for before pipeline | No |
| afterPipeline | [pipeline.Spec](#pipelinespec) | Spec for after pipeline | No |
### EaseMonitorMetrics
EaseMonitorMetrics is adapted to monitor metrics of Easegress and send them to Kafka. The config looks like:
```yaml
kind: EaseMonitorMetrics
name: easemonitor-metrics-example
kafka:
brokers: ["127.0.0.1:9092"]
topic: metrics
```
| Name | Type | Description | Required |
| ----- | ---------------------------------------------------- | -------------------- | -------- |
| kafka | [easemonitormetrics.Kafka](#easemonitormetricskafka) | Kafka related config | Yes |
### FaaSController
A FaaSController is a business controller for handling Easegress and FaaS products integration purposes. It abstracts `FaasFunction`, `FaaSStore` and, `FaasProvider`. Currently, we only support `Knative` type `FaaSProvider`.
For the full reference document please check - [FaaS Controller](7.04.FaaSController.md)
### IngressController
The IngressController is an implementation of [Kubernetes ingress controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/), it watches Kubernetes Ingress, Service, Endpoints, and Secrets then translates them to Easegress HTTP server and pipelines. The config looks like:
```yaml
kind: IngressController
name: ingress-controller-example
kubeConfig:
masterURL:
namespaces: ["default"]
ingressClass: easegress
httpServer:
port: 8080
https: false
keepAlive: true
keepAliveTimeout: 60s
maxConnections: 10240
```
| Name | Type | Description | Required |
| ------------ | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
| kubeConfig | string | Path of the Kubernetes configuration file. | No |
| masterURL | string | The address of the Kubernetes API server. | No |
| namespaces | []string | An array of Kubernetes namespaces which the IngressController needs to watch, all namespaces are watched if left empty. | No |
| ingressClass | string | The IngressController only handles `Ingresses` with `ingressClassName` set to the value of this option. | No (default: easegress) |
| httpServer | [httpserver.Spec](#httpserver) | Basic configuration for the shared HTTP traffic gate. The routing rules will be generated dynamically according to Kubernetes ingresses and should not be specified here. | Yes |
**Note**: IngressController uses `kubeConfig` and `masterURL` to connect to Kubernetes, at least one of them must be specified when deployed outside of a Kubernetes cluster, and both are optional when deployed inside a cluster.
### ConsulServiceRegistry
ConsulServiceRegistry supports service discovery for Consul as backend. The config looks like:
```yaml
kind: ConsulServiceRegistry
name: consul-service-registry-example
address: '127.0.0.1:8500'
scheme: http
syncInterval: 10s
```
| Name | Type | Description | Required |
| ------------ | -------- | ---------------------------- | ----------------------------- |
| address | string | Consul server address | Yes (default: 127.0.0.1:8500) |
| scheme | string | Communication scheme | Yes (default: http) |
| datacenter | string | Datacenter name | No |
| token | string | ACL token for communication | No |
| namespace | string | Namespace to use | No |
| syncInterval | string | Interval to synchronize data | Yes (default: 10s) |
| serviceTags | []string | Service tags to query | No |
### EtcdServiceRegistry
EtcdServiceRegistry support service discovery for Etcd as backend. The config looks like:
```yaml
kind: EtcdServiceRegistry
name: etcd-service-registry-example
endpoints: ['127.0.0.1:12379']
prefix: "/services/"
cacheTimeout: 10s
```
| Name | Type | Description | Required |
| ------------ | -------- | ------------------------------ | ------------------------- |
| endpoints | []string | Endpoints of Etcd servers | Yes |
| prefix | string | Prefix of the keys of services | Yes (default: /services/) |
| cacheTimeout | string | Timeout of cache | Yes (default: 60s) |
### EurekaServiceRegistry
EurekaServiceRegistry supports service discovery for Eureka as backend. The config looks like:
```yaml
kind: EurekaServiceRegistry
name: eureka-service-registry-example
endpoints: ['http://127.0.0.1:8761/eureka']
syncInterval: 10s
```
| Name | Type | Description | Required |
| ------------ | -------- | ---------------------------- | ------------------------------------------- |
| endpoints | []string | Endpoints of Eureka servers | Yes (default: ) |
| syncInterval | string | Interval to synchronize data | Yes (default: 10s) |
### ZookeeperServiceRegistry
ZookeeperServiceRegistry supports service discovery for Zookeeper as backend. The config looks like:
```yaml
kind: ZookeeperServiceRegistry
name: zookeeper-service-registry-example
zkservices: [127.0.0.1:2181]
prefix: /services
conntimeout: 6s
syncInterval: 10s
```
| Name | Type | Description | Required |
| ------------ | -------- | ---------------------------- | ----------------------------- |
| zkservices | []string | Zookeeper service addresses | Yes (default: 127.0.0.1:2181) |
| connTimeout | string | Timeout of connection | Yes (default: 6s) |
| prefix | string | Prefix of services | Yes (default: /) |
| syncInterval | string | Interval to synchronize data | Yes (default: 10s) |
### NacosServiceRegistry
NacosServiceRegistry supports service discovery for Nacos as backend. The config looks like:
```yaml
kind: NacosServiceRegistry
name: nacos-service-registry-example
syncInterval: 10s
servers:
- scheme: http
port: 8848
contextPath: /nacos
ipAddr: 127.0.0.1
```
| Name | Type | Description | Required |
| ------------ | ------------------------------------- | ---------------------------- | ------------------ |
| servers | [][nacosServerSpec](#nacosserverspec) | Servers of Nacos | Yes |
| syncInterval | string | Interval to synchronize data | Yes (default: 10s) |
| namespace | string | The namespace of Nacos | No |
| username | string | The username of client | No |
| password | string | The password of client | No |
### AutoCertManager
AutoCertManager automatically manage HTTPS certificates. The config looks like:
```yaml
kind: AutoCertManager
name: autocert
email: someone@megaease.com
directoryURL: https://acme-v02.api.letsencrypt.org/directory
renewBefore: 720h
enableHTTP01: true
enableTLSALPN01: true
enableDNS01: true
domains:
- name: "*.megaease.com"
dnsProvider:
name: dnspod
zone: megaease.com
apiToken:
```
| Name | Type | Description | Required |
| --------------- | ------------------------------------------ | ------------------------------------------------------------------------------------ | ---------------------------------- |
| email | string | An email address for CA account | Yes |
| directoryURL | string | The endpoint of the CA directory | No (default to use Let's Encrypt) |
| renewBefore | string | A certificate will be renewed before this duration of its expire time | No (default 720 hours) |
| enableHTTP01 | bool | Enable HTTP-01 challenge (Easegress need to be accessable at port 80 when true) | No (default true) |
| enableTLSALPN01 | bool | Enable TLS-ALPN-01 challenge (Easegress need to be accessable at port 443 when true) | No (default true) |
| enableDNS01 | bool | Enable DNS-01 challenge | No (default true) |
| domains | [][DomainSpec](#autocertmanagerdomainspec) | Domains to be managed | Yes |
### AIGatewayController
AIGatewayController is a controller for managing AI Gateway resources. It provides control plane functionality for the AI Gateway, allowing Filter AIGatewayProxy to leverage AI models for processing requests and responses.
```yaml
kind: AIGatewayController
name: AIGatewayController
providers:
- name: openai-provider
providerType: openai
baseURL: https://api.openai.com
apiKey: sk-proj-openai-api-key # Replace with your OpenAI API key
- name: deepseek-provider
providerType: deepseek
baseURL: https://api.deepseek.com
apiKey: sk-deepseek-api-key # Replace with your DeepSeek API key
version: easegress.megaease.com/v2
```
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| providers | [][ProviderSpec](#aigatewaycontrollerproviderspec) | List of AI providers configuration | No |
| middlewares | [][MiddlewareSpec](#aigatewaycontrollermiddlewarespec) | List of middleware configuration for request processing | No |
### WAFController
```yaml
name: waf-controller
kind: WAFController
ruleGroups:
- name: sqlinjection
rules:
customRules: |
// https://github.com/corazawaf/coraza-coreruleset/blob/main/rules/%40crs-setup.conf.example
// check coraza core rule set recommend setup file
owaspRules:
- REQUEST-901-INITIALIZATION.conf
- REQUEST-942-APPLICATION-ATTACK-SQLI.conf
- REQUEST-949-BLOCKING-EVALUATION.conf
- name: geoipblocker
rules:
geoIPBlocker:
dbPath: /Country.mmdb
dbUpdateCron: "0 0 1 * *"
deniedCountries:
- XX
```
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
|ruleGroups | [][RuleGroupSpec](#wafcontrollerrulegroupspec) | A list of configurations for one or more WAF rule groups. | Yes |
## Common Types
### tracing.Spec
| Name | Type | Description | Required |
| ----------- | -------------------------- | ----------------------------- | -------- |
| serviceName | string | The service name of top level | Yes |
| attributes | map[string]string | Attributes to include to every span. | No |
| tags | map[string]string | Deprecated. Tags to include to every span. This option will be kept until the next major version incremented release. | No |
| spanLimits | [spanlimits.Spec](#spanlimitsspec) | SpanLimitsSpec represents the limits of a span. | No |
| sampleRate | float64 | The sample rate for collecting metrics, the range is [0, 1]. For backward compatibility, if the exporter is empty, the default is to use zipkin.sampleRate | No (default: 1) |
| batchLimits | [batchlimits.Spec](#batchlimitsspec) | BatchLimitsSpec describes BatchSpanProcessorOptions | No |
| exporter | [exporter.Spec](#exporterspec) | ExporterSpec describes exporter. exporter and zipkin cannot both be empty | No |
| zipkin | [zipkin.DeprecatedSpec](#zipkindeprecatedspec) | ZipkinDeprecatedSpec describes Zipkin. If exporter is configured, this option does not take effect. This option will be kept until the next major version incremented release. | No |
| headerFormat | string | HeaderFormat represents which format should be used for context propagation. options: [trace-conext](https://www.w3.org/TR/trace-context/),b3. For backward compatibility, the historical Zipkin configuration remains in b3 format. | No (default: trace-conext) |
#### spanlimits.Spec
| Name | Type | Description | Required |
| ----------- | -------------------------- | ----------------------------- | -------- |
| attributeValueLengthLimit | int | AttributeValueLengthLimit is the maximum allowed attribute value length, Setting this to a negative value means no limit is applied| No (default:-1) |
| attributeCountLimit | int | AttributeCountLimit is the maximum allowed span attribute count| No (default:128)|
| eventCountLimit | int | EventCountLimit is the maximum allowed span event count| No (default:128)|
| linkCountLimit | int | LinkCountLimit is the maximum allowed span link count| No (default:128)|
| attributePerEventCountLimit | int | AttributePerEventCountLimit is the maximum number of attributes allowed per span event| No (default:128)|
| attributePerLinkCountLimit | int | AttributePerLinkCountLimit is the maximum number of attributes allowed per span link| No (default:128)|
#### batchlimits.Spec
| Name | Type | Description | Required |
| ----------- | -------------------------- | ----------------------------- | -------- |
| maxQueueSize | int |MaxQueueSize is the maximum queue size to buffer spans for delayed processing| No (default:2048) |
| batchTimeout | int | BatchTimeout is the maximum duration for constructing a batch| No (default:5000 msec)|
| exportTimeout | int | ExportTimeout specifies the maximum duration for exporting spans| No (default:30000 msec)|
| maxExportBatchSize | int | MaxExportBatchSize is the maximum number of spans to process in a single batch| No (default:512)|
#### exporter.Spec
| Name | Type | Description | Required |
| ----------- | -------------------------- | ----------------------------- | -------- |
| jaeger | [jaeger.Spec](#jaegerspec) | JaegerSpec describes Jaeger | No |
| zipkin | [zipkin.Spec](#zipkinspec) | ZipkinSpec describes Zipkin | No |
| otlp | [otlp.Spec](#otlpspec) | OTLPSpec describes OpenTelemetry exporter | No |
#### jaeger.Spec
| Name | Type | Description | Required |
| ----------- | -------------------------- | ----------------------------- | -------- |
| mode | string |Jaeger's access mode | Yes (options: agent,collector) |
| endpoint | string |In agent mode, endpoint must be host:port, in collector mode it is url| No|
| username | string |The username used in collector mode| No |
| password | string | The password used in collector mode| No|
#### zipkin.Spec
| Name | Type | Description | Required |
|---------------|---------|----------------------------------------------------------------------------------------------------| -------- |
| endpoint | string | The zipkin server URL | Yes |
#### otlp.Spec
| Name | Type | Description | Required |
| ----------- | -------------------------- | ----------------------------- | -------- |
| protocol | string | Connection protocol of otlp | Yes (options: http,grpc) |
| endpoint | string | Endpoint of the otlp collector| Yes|
| insecure | bool | Whether to allow insecure connections| No (default: false)|
| compression | string |Compression describes the compression used for payloads sent to the collector| No (options: gzip) |
#### zipkin.DeprecatedSpec
| Name | Type | Description | Required |
|---------------|---------|----------------------------------------------------------------------------------------------------| -------- |
| ~~hostPort~~ | string | Deprecated. The host:port of the service | No |
| serverURL | string | The zipkin server URL | Yes |
| sampleRate | float64 | The sample rate for collecting metrics, the range is [0, 1] | Yes |
| ~~disableReport~~ | bool | Deprecated. Whether to report span model data to zipkin server | No |
| ~~sameSpan~~ | bool | Deprecated. Whether to allow to place client-side and server-side annotations for an RPC call in the same span | No |
| ~~id128Bit~~ | bool | Deprecated. Whether to start traces with 128-bit trace id | No |
### ipfilter.Spec
| Name | Type | Description | Required |
| -------------- | -------- | ---------------------------------------------------- | -------------------- |
| blockByDefault | bool | Set block is the default action if not matching | Yes (default: false) |
| allowIPs | []string | IPs to be allowed to pass (support IPv4, IPv6, CIDR) | No |
| blockIPs | []string | IPs to be blocked to pass (support IPv4, IPv6, CIDR) | No |
### httpserver.Rule
| Name | Type | Description | Required |
| ---------- | ----------------------------------- | ------------------------------------------------------------- | -------- |
| ipFilter | [ipfilter.Spec](#ipfilterspec) | IP Filter for all traffic under the rule | No |
| host | string | Exact host or wildcard. For example "*.example.com" or "www.example.com". | No |
| hostRegexp | string | Host in regular expression to match | No |
| hosts | [][httpserver.Host](#httpserverhost) | Hosts to match | No |
| paths | [][httpserver.Path](#httpserverpath) | Path matching rules, empty means to match nothing. Note that multiple paths are matched in the order of their appearance in the spec, this is different from Nginx. | No |
**Note**: if `host` or `hostRegexp` is not empty, they will be added into
`hosts` at runtime, and if the result `hosts` is empty, all hosts are matched.
### httpserver.Host
| Name | Type | Description | Required |
| ------------- | ------------------------ | ---------------------------------------------------------------------- | -------- |
| isRegexp | bool | Whether `value` is regular expression or exact value, default is false | No |
| value | string | Host value to match. Wildcard is supported. | Yes |
### httpserver.Path
| Name | Type | Description | Required |
| ------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| ipFilter | [ipfilter.Spec](#ipfilterspec) | IP Filter for all traffic under the path | No |
| path | string | Exact path to match | No |
| pathPrefix | string | Prefix of the path to match | No |
| pathRegexp | string | Path in regular expression to match | No |
| rewriteTarget | string | Use pathRegexp.[ReplaceAllString](https://golang.org/pkg/regexp/#Regexp.ReplaceAllString)(path, rewriteTarget) or pathPrefix [strings.Replace](https://pkg.go.dev/strings#Replace) to rewrite request path | No |
| methods | []string | Methods to match, empty means to allow all methods | No |
| headers | [][httpserver.Header](#httpserverheader) | Headers to match (the requests matching headers won't be put into cache) | No |
| backend | string | backend name (pipeline name in static config, service name in mesh) | Yes |
| clientMaxBodySize | int64 | Max size of request body, will use the option of the HTTP server if not set. the default value is 4MB. Requests with a body larger than this option are discarded. When this option is set to `-1`, Easegress takes the request body as a stream and the body can be any size, but some features are not possible in this case, please refer [Stream](7.05.Stream.md) for more information. | No |
| matchAllHeader | bool | Match all headers that are defined in headers, default is `false`. | No |
| matchAllQuery | bool | Match all queries that are defined in queries, default is `false`. | No |
### httpserver.Header
There must be at least one of `values` and `regexp`.
| Name | Type | Description | Required |
| ------- | -------- | ------------------------------------------------------------------- | -------- |
| key | string | Header key to match | Yes |
| values | []string | Header values to match | No |
| regexp | string | Header value in regular expression to match | No |
### pipeline.Spec
| Name | Type | Description | Required |
|------|------|-------------|----------|
| flow | [pipeline.FlowNode](#pipelineflownode) | Flow of pipeline | No |
| filters | [][filters.Filter](#filtersfilter) | Filter definitions of pipeline | Yes |
| resilience | [][resilience.Policy](#resiliencepolicy) | Resilience policy for backend filters | No |
### pipeline.FlowNode
| Name | Type | Description | Required |
| ------ | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| filter | string | The filter name | Yes |
| jumpIf | map[string]string | Jump to another filter conditionally, the key is the result of the current filter, the value is the target filter name/alias. `END` is the built-in value for the ending of the pipeline | No |
| namespace | string | Namespace of the filter | No |
| alias | string | Alias name of the filter | No |
### filters.Filter
The self-defining specification of each filter references to [filters](7.02.Filters.md).
| Name | Type | Description | Required |
| ------------------------------------ | ------ | -------------- | -------- |
| name | string | Name of filter | Yes |
| kind | string | Kind of filter | Yes |
| [self-defining fields](7.02.Filters.md) | - | - | - |
### grpcserver.Rule
| Name | Type | Description | Required |
|------|------|-------------|----------|
| host | string | Exact host to match | No |
| hostRegexp | string | Host in regular expression to match | No |
| methods | [][grpcserver.Method](#grpcservermethod) | Method matching rules, empty means to match nothing. | No |
| ipFilter | [ipFilter.Spec](#ipfilterspec) | IP Filter for all traffic under the rule | No |
### grpcserver.Method
| Name | Type | Description | Required |
|------|------|-------------|----------|
| method | string | Exact method to match | No |
| methodPrefix | string | Prefix of the method to match | No |
| methodRegexp | string | Method in regular expression to match | No |
| backend | string | backend name (pipeline name in static config, service name in mesh) | No |
| headers | [][grpcserver.Header](#grpcserverheader) | Headers to match | No |
| matchAllHeader | bool | Match all headers that are defined in headers, default is false. | No |
| ipFilter | [ipFilter.Spec](#ipfilterspec) | IP Filter for all traffic under the method | No |
### grpcserver.Header
| Name | Type | Description | Required |
|------|------|-------------|----------|
| key | string | Header key to match | Yes |
| values | []string | Header values to match | No |
| regexp | string | Header value in regular expression to match | No |
### easemonitormetrics.Kafka
| Name | Type | Description | Required |
| ------- | -------- | ---------------- | ----------------------------- |
| brokers | []string | Broker addresses | Yes (default: localhost:9092) |
| topic | string | Produce topic | Yes |
### nacos.ServerSpec
| Name | Type | Description | Required |
| ----------- | ------ | -------------------------------------------- | -------- |
| ipAddr | string | The ip address | Yes |
| port | uint16 | The port | Yes |
| scheme | string | The scheme of protocol (support http, https) | No |
| contextPath | string | The context path | No |
### autocertmanager.DomainSpec
| Name | Type | Description | Required |
| ----------- | ----------------- | --------------------------| ------------------------------------ |
| name | string | The name of the domain | Yes |
| dnsProvider | map[string]string | DNS provider information | No (Yes if `DNS-01` chanllenge is desired) |
The fields in `dnsProvider` vary from DNS providers, but:
- `name` and `zone` are required for all DNS providers.
- `nsAddress` and `nsNetwork` are optional name server information for all DNS
providers, if provided, AutoCertManager will leverage them to speed up the
DNS record lookup. `nsAddress` is the address of the name server, must always
include the port number, `nsNetwork` is the network protocol of name server,
it should be `udp` in most cases.
Below table list other required fields for each supported DNS provider (Note: `google` is temporarily disabled due to dependency conflict):
| DNS Provider Name | Required Fields |
| ----------------- | ------------------------------------------------------------------- |
| alidns | accessKeyId, accessKeySecret |
| azure | tenantId, clientId, clientSecret, subscriptionId, resourceGroupName |
| cloudflare | apiToken |
| digitalocean | apiToken |
| dnspod | apiToken |
| duckdns | apiToken |
| google | project |
| hetzner | authApiToken |
| route53 | accessKeyId, secretAccessKey, awsProfile |
| vultr | apiToken |
### resilience.Policy
| Name | Type | Description | Required |
| -------------------- | ------ | -------------- | -------- |
| name | string | Name of filter | Yes |
| kind | string | Kind of filter | Yes |
| other kind specific fields of the policy kind | - | - | - |
#### Retry Policy
A retry policy configures how to retry a failed request.
| Name | Type | Description | Required |
|------|------|-------------|----------|
| maxAttempts | int | The maximum number of attempts (including the initial one). Default is 3 | No |
| waitDuration | string | The base wait duration between attempts. Default is 500ms | No |
| backOffPolicy | string | The back-off policy for wait duration, could be `EXPONENTIAL` or `RANDOM` and the default is `RANDOM`. If configured as `EXPONENTIAL`, the base wait duration becomes 1.5 times larger after each failed attempt | No |
| randomizationFactor | float64 | Randomization factor for actual wait duration, a number in interval `[0, 1]`, default is 0. The actual wait duration used is a random number in interval `[(base wait duration) * (1 - randomizationFactor), (base wait duration) * (1 + randomizationFactor)]` | No |
#### CircuitBreaker Policy
CircuitBreaker leverges a finite state machine to implement the processing logic, the state machine has three states: `CLOSED`, `OPEN`, and `HALF_OPEN`. When the state is `CLOSED`, requests pass through normally, state transits to `OPEN` if request failure rate or slow request rate reach a configured threshold and requests will be shor-circuited in this state. After a configured duration, state transits from `OPEN` to `HALF_OPEN`, in which a limited number of requests are permitted to pass through while other requests are still short-circuited, and state transit to `CLOSED` or `OPEN`
based on the results of the permitted requests.
When `CLOSED`, it uses a sliding window to store and aggregate the result of recent requests, the window can either be `COUNT_BASED` or `TIME_BASED`. The `COUNT_BASED` window aggregates the last N requests and the `TIME_BASED` window aggregates requests in the last N seconds, where N is the window size.
Below is an example configuration with both `COUNT_BASED` and `TIME_BASED` policies.
Policy `circuit-breaker-example-count` short-circuits requests if more than half of recent requests failed.
Policy `circuit-breaker-example-time` short-circuits requests if more than 60% of recent requests failed.
> failed means that backend filter returns non-empty results.
```yaml
kind: CircuitBreaker
name: circuit-breaker-example-count
slidingWindowType: COUNT_BASED
failureRateThreshold: 50
slidingWindowSize: 100
---
kind: CircuitBreaker
name: circuit-breaker-example-time
slidingWindowType: TIME_BASED
failureRateThreshold: 60
slidingWindowSize: 100
```
| Name | Type | Description | Required |
|------|------|-------------|----------|
| slidingWindowType | string | Type of the sliding window which is used to record the outcome of requests when the CircuitBreaker is `CLOSED`. Sliding window can either be `COUNT_BASED` or `TIME_BASED`. If the sliding window is `COUNT_BASED`, the last `slidingWindowSize` requests are recorded and aggregated. If the sliding window is `TIME_BASED`, the requests of the last `slidingWindowSize` seconds are recorded and aggregated. Default is `COUNT_BASED` | No |
| failureRateThreshold | int8 | Failure rate threshold in percentage. When the failure rate is equal to or greater than the threshold the CircuitBreaker transitions to `OPEN` and starts short-circuiting requests. Default is 50 | No |
| slowCallRateThreshold | int8 | Slow rate threshold in percentage. The CircuitBreaker considers a request as slow when its duration is greater than `slowCallDurationThreshold`. When the percentage of slow requests is equal to or greater than the threshold, the CircuitBreaker transitions to `OPEN` and starts short-circuiting requests. Default is 100 | No |
| slowCallDurationThreshold | string | Duration threshold for slow call | No |
| slidingWindowSize | uint32 | The size of the sliding window which is used to record the outcome of requests when the CircuitBreaker is `CLOSED`. Default is 100 | No |
| permittedNumberOfCallsInHalfOpenState | uint32 | The number of permitted requests when the CircuitBreaker is `HALF_OPEN`. Default is 10 | No |
| minimumNumberOfCalls | uint32 | The minimum number of requests which are required (per sliding window period) before the CircuitBreaker can calculate the error rate or slow requests rate. For example, if `minimumNumberOfCalls` is 10, then at least 10 requests must be recorded before the failure rate can be calculated. If only 9 requests have been recorded the CircuitBreaker will not transition to `OPEN` even if all 9 requests have failed. Default is 10 | No |
| maxWaitDurationInHalfOpenState | string | The maximum wait duration which controls the longest amount of time a CircuitBreaker could stay in `HALF_OPEN` state before it switches to `OPEN`. Value 0 means CircuitBreaker would wait infinitely in `HALF_OPEN` State until all permitted requests have been completed. Default is 0| No |
| waitDurationInOpenState | string | The time that the CircuitBreaker should wait before transitioning from `OPEN` to `HALF_OPEN`. Default is 60s | No |
See more details about `Retry`, `CircuitBreaker`, or other resilience policies in [the Resilience Policy documentation](../02.Tutorials/2.4.Resilience.md).
### AIGatewayController.ProviderSpec
| Name | Type | Description | Required |
| ------------ | ----------------- | -------------------------------------------------------------- | -------- |
| name | string | Unique name of the provider | Yes |
| providerType | string | Type of the provider (see below) | Yes |
| baseURL | string | Base URL for the provider API | Yes |
| apiKey | string | API key for authentication | Yes |
| headers | map[string]string | Additional headers to include in requests | No |
| endpoint | string | Endpoint URL (used for Azure OpenAI) | No |
| deploymentID | string | Deployment ID (used for Azure OpenAI) | No |
| apiVersion | string | API version (used for Azure OpenAI) | No |
#### Supported Providers
The providerType can be one of the following:
- anthropic
- azure
- bedrock
- cohere
- deepseek
- gemini
- mistral
- ollama
- openai
- qwen
### AIGatewayController.MiddlewareSpec
| Name | Type | Description | Required |
| ------------- | ------------------------------------------- | ---------------------------------------------- | -------- |
| name | string | Unique name of the middleware | Yes |
| kind | string | Type of middleware (e.g., SemanticCache) | Yes |
| semanticCache | [SemanticCacheSpec](#aigatewaycontrollersemanticcachespec) | Configuration for semantic cache middleware | No |
### AIGatewayController.SemanticCacheSpec
| Name | Type | Description | Required |
| --------------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| embeddings | [EmbeddingSpec](#aigatewaycontrollerembeddingspec) | Configuration for embedding provider | Yes |
| vectorDB | [VectorDBSpec](#aigatewaycontrollervectordbspec) | Configuration for vector database | Yes |
| readOnly | bool | Whether the cache is read-only | No |
| contentTemplate | string | Template for extracting content from requests | No |
### AIGatewayController.EmbeddingSpec
| Name | Type | Description | Required |
| ------------ | ----------------- | ---------------------------------------------- | -------- |
| providerType | string | Type of embedding provider | Yes |
| baseURL | string | Base URL for the embedding API | Yes |
| apiKey | string | API key for authentication | Yes |
| headers | map[string]string | Additional headers to include in requests | No |
| model | string | Model name for embeddings | Yes |
### AIGatewayController.VectorDBSpec
| Name | Type | Description | Required |
| -------------- | ---------------------------------------- | ---------------------------------------------- | -------- |
| type | string | Type of vector database (e.g., redis) | Yes |
| threshold | float64 | Similarity threshold for vector search | Yes |
| collectionName | string | Name of the collection/index | Yes |
| redis | [RedisSpec](#aigatewaycontrollerredisspec) | Redis-specific configuration | No |
| postgres | [PostgresSpec](#aigatewaycontrollerpostgresspec) | PostgreSQL-specific configuration | No |
| qdrant | [QdrantSpec](#aigatewaycontrollerqdrantspec) | Qdrant-specific configuration | No |
### AIGatewayController.RedisSpec
| Name | Type | Description | Required |
| -------- | ------ | ------------------------------ | -------- |
| url | string | Redis server address | Yes |
### AIGatewayController.PostgresSpec
| Name | Type | Description | Required |
| ------------- | ------ | ------------------------------ | -------- |
| connectionURL | string | PostgreSQL connection URL | Yes |
### AIGatewayController.QdrantSpec
| Name | Type | Description | Required |
| ------ | ------ | ----------------------- | -------- |
| host | string | Qdrant server host | Yes |
| port | int | Qdrant gRPC port | Yes |
| apiKey | string | Qdrant API key | No |
| useTLS | bool | Enable TLS | No |
### WAFController.RuleGroupSpec
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| name | string | A unique name for the rule group. | Yes |
| loadOwaspCrs | bool | Indicates whether to load the OWASP Core Rule Set. For more details, please check Coraza CRS. | No |
| rules | [RuleSpec](#wafcontrollerrulespec) | Defines the specific rules included in this rule group. | Yes |
### WAFController.RuleSpec
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| owaspRules | []string | Defines the OWASP rules to be applied. See the examples at Coraza CRS for more details. | No |
| customRules | string | Defines custom WAF rules. | No |
| ipBlocker | [IPBlockerSpec](#wafcontrolleripblockerspec) | Defines access control rules based on IP addresses (whitelist/blacklist). | No |
| geoIPBlocker | [GeoIPBlockerSpec](#wafcontrollergeoipblockerspec) | Defines access control rules based on geolocation (GeoIP). | No |
### WAFController.IPBlockerSpec
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| whitelist | []string | A list of IP addresses that are allowed access. | No |
| blacklist | []string | A list of IP addresses that are denied access. | No |
### WAFController.GeoIPBlockerSpec
| Name | Type | Description | Required |
| ----------- | ----------------------------------------- | ----------------------------------------------------- | -------- |
| dbPath | string | The file path to the GeoIP database. | Yes |
| dbUpdateCron | string | A cron expression for automatically updating the GeoIP database on a schedule. | No |
| allowedCountries | []string | A list of country codes (e.g., "US", "CN") that are allowed access. | No |
| deniedCountries | []string | A list of country codes that are denied access. | No|
---
## File: docs/07.Reference/7.02.Filters.md
# Filters
- [Proxy](#proxy)
- [Health Check](#health-check)
- [Request Host](#request-host)
- [Configuration](#configuration)
- [Results](#results)
- [SimpleHTTPProxy](#simplehttpproxy)
- [Configuration](#configuration-1)
- [Results](#results-1)
- [WebSocketProxy](#websocketproxy)
- [Health Check](#health-check-1)
- [Configuration](#configuration-2)
- [Results](#results-2)
- [CORSAdaptor](#corsadaptor)
- [Configuration](#configuration-3)
- [Results](#results-3)
- [Fallback](#fallback)
- [Configuration](#configuration-4)
- [Results](#results-4)
- [Mock](#mock)
- [Configuration](#configuration-5)
- [Results](#results-5)
- [RemoteFilter](#remotefilter)
- [Configuration](#configuration-6)
- [Results](#results-6)
- [RequestAdaptor](#requestadaptor)
- [Configuration](#configuration-7)
- [Results](#results-7)
- [RequestBuilder](#requestbuilder)
- [Configuration](#configuration-8)
- [Results](#results-8)
- [RateLimiter](#ratelimiter)
- [Configuration](#configuration-9)
- [Results](#results-9)
- [ResponseAdaptor](#responseadaptor)
- [Configuration](#configuration-10)
- [Results](#results-10)
- [ResponseBuilder](#responsebuilder)
- [Configuration](#configuration-11)
- [Results](#results-11)
- [Validator](#validator)
- [Configuration](#configuration-12)
- [Results](#results-12)
- [WasmHost](#wasmhost)
- [Configuration](#configuration-13)
- [Results](#results-13)
- [Kafka](#kafka)
- [Configuration](#configuration-14)
- [Results](#results-14)
- [HeaderToJSON](#headertojson)
- [Configuration](#configuration-15)
- [Results](#results-15)
- [CertExtractor](#certextractor)
- [Configuration](#configuration-16)
- [Results](#results-16)
- [HeaderLookup](#headerlookup)
- [Configuration](#configuration-17)
- [Results](#results-17)
- [ResultBuilder](#resultbuilder)
- [Configuration](#configuration-18)
- [Results](#results-18)
- [DataBuilder](#databuilder)
- [Configuration](#configuration-19)
- [Results](#results-19)
- [OIDCAdaptor](#oidcadaptor)
- [Configuration](#configuration-20)
- [Results](#results-20)
- [OPAFilter](#opafilter)
- [Configuration](#configuration-21)
- [Results](#results-21)
- [Redirector](#redirector)
- [Configuration](#configuration-22)
- [Results](#results-22)
- [RedirectorV2](#redirectorv2)
- [Configuration](#configuration-23)
- [Results](#results-23)
- [GRPCProxy](#grpcproxy)
- [Configuration](#configuration-24)
- [Results](#results-24)
- [AIGatewayProxy](#aigatewayproxy)
- [Configuration](#configuration-25)
- [Results](#results-25)
- [WAF](#waf)
- [Configuration](#configuration-26)
- [Results](#results-26)
- [Common Types](#common-types)
- [pathadaptor.Spec](#pathadaptorspec)
- [pathadaptor.RegexpReplace](#pathadaptorregexpreplace)
- [httpheader.AdaptSpec](#httpheaderadaptspec)
- [proxy.ServerPoolSpec](#proxyserverpoolspec)
- [proxy.Server](#proxyserver)
- [proxy.LoadBalanceSpec](#proxyloadbalancespec)
- [proxy.StickySessionSpec](#proxystickysessionspec)
- [proxy.HealthCheckSpec](#proxyhealthcheckspec)
- [proxy.MemoryCacheSpec](#proxymemorycachespec)
- [proxy.RequestMatcherSpec](#proxyrequestmatcherspec)
- [grpcproxy.ServerPoolSpec](#grpcproxyserverpoolspec)
- [grpcproxy.RequestMatcherSpec](#grpcproxyrequestmatcherspec)
- [StringMatcher](#stringmatcher)
- [proxy.MethodAndURLMatcher](#proxymethodandurlmatcher)
- [urlrule.URLRule](#urlruleurlrule)
- [proxy.Compression](#proxycompression)
- [proxy.MTLS](#proxymtls)
- [websocketproxy.WebSocketServerPoolSpec](#websocketproxywebsocketserverpoolspec)
- [mock.Rule](#mockrule)
- [mock.MatchRule](#mockmatchrule)
- [ratelimiter.Policy](#ratelimiterpolicy)
- [httpheader.ValueValidator](#httpheadervaluevalidator)
- [validator.JWTValidatorSpec](#validatorjwtvalidatorspec)
- [validator.BasicAuthValidatorSpec](#validatorbasicauthvalidatorspec)
- [basicAuth.LDAPSpec](#basicauthldapspec)
- [signer.Spec](#signerspec)
- [signer.HeaderHoisting](#signerheaderhoisting)
- [signer.Literal](#signerliteral)
- [validator.OAuth2ValidatorSpec](#validatoroauth2validatorspec)
- [validator.OAuth2TokenIntrospect](#validatoroauth2tokenintrospect)
- [validator.OAuth2JWT](#validatoroauth2jwt)
- [kafka.Topic](#kafkatopic)
- [kafka.Key](#kafkakey)
- [headertojson.HeaderMap](#headertojsonheadermap)
- [headerlookup.HeaderSetterSpec](#headerlookupheadersetterspec)
- [requestadaptor.SignerSpec](#requestadaptorsignerspec)
- [Template Of Builder Filters](#template-of-builder-filters)
- [HTTP Specific](#http-specific)
A Filter is a request/response processor. Multiple filters can be orchestrated
together to form a pipeline, each filter returns a string result after it
finishes processing the input request/response. An empty result means the
input was successfully processed by the current filter and can go forward
to the next filter in the pipeline, while a non-empty result means the pipeline
or preceding filter needs to take extra action.
## Proxy
The Proxy filter is a proxy of the backend service.
Below is one of the simplest Proxy configurations, it forward requests
to `http://127.0.0.1:9095` or `http://127.0.0.1:9096` or `http://127.0.0.1:9097` based on `roundRobin`.
```yaml
kind: Proxy
name: proxy-example-1
pools:
- servers:
- url: http://127.0.0.1:9095
- url: http://127.0.0.1:9096
- url: http://127.0.0.1:9097
loadBalance:
policy: roundRobin
maxRedirection: 10
```
Pool without `filter` is considered the main pool, other pools with `filter`
are considered candidate pools. Proxy first checks if one of the candidate
pools can process a request. For example, the first candidate pool in the
below configuration selects and processes requests with the header
`X-Candidate:candidate`, the second candidate pool randomly selects and
processes 400‰ of requests, and the main pool processes the other 600‰
of requests.
```yaml
kind: Proxy
name: proxy-example-2
pools:
- servers:
- url: http://127.0.0.1:9095
filter:
headers:
X-Candidate:
exact: candidate
- servers:
- url: http://127.0.0.1:9096
filter:
permil: 400 # between 0 and 1000
policy: random
- servers:
- url: http://127.0.0.1:9097
maxRedirection: 10
```
Servers of a pool can also be dynamically configured via service discovery,
the below configuration gets a list of servers by `serviceRegistry` &
`serviceName`, and only servers that have tag `v2` are selected.
```yaml
kind: Proxy
name: proxy-example-3
pools:
- serverTags: ["v2"]
serviceName: service-001
serviceRegistry: eureka-service-registry-example
loadBalance:
policy: roundRobin
maxRedirection: 10
```
### Health Check
Perform a health check on the servers in the pool. If a server fails the check, it will be marked as unhealthy, and requests will be rerouted to other healthy servers until it regains health.
```yaml
name: proxy
kind: Proxy
pools:
- servers:
- url: http://127.0.0.1:9095
- url: http://127.0.0.1:9096
- url: http://127.0.0.1:9097
healthCheck:
# interval between health checks (default: 60s)
interval: 60s
# timeout for health check response (default: 3s)
timeout: 3s
# fail threshold to mark server as unhealthy (default: 1)
fails: 1
# success threshold to mark server as healthy (default: 1)
pass: 1
# health check request port (defaults to server's port, e.g., 9095)
port: 10080
# uri for health check http request
uri: /health
# http method for health check
method: GET
# http request headers for health check
headers:
X-Health-Check: easegress
# http request body for health check
body: "you-body-here"
# username for basic authentication
username: admin
# password for basic authentication
password: xxxxxx
# response validation criteria (default: 2xx and 3xx status codes)
match:
# acceptable status code ranges
statusCodes:
- [200, 299] # 2xx
- [300, 399] # 3xx
# response header validation
# name is header key.
# value is header value, can be empty.
# type is type of value, can be "exact" or "regexp".
headers:
- name: X-Status
value: healthy
type: exact
# response body validation
# type can be "contains" or "regexp".
body:
value: "healthy"
type: contains
```
### Request Host
By default, if the client's request host is `example.com` and the pools.servers.url is IP-based, Easegress will forward the request to the backend with the host `example.com`. However, if `pools.servers.url` is a domain, such as `http://demo.com:9090`, Easegress will automatically update the request's host to `demo.com:9090` before sending it to the backend. To prevent this and retain the original client request host, use the `keepHost` option as shown below:
```yaml
kind: Proxy
name: proxy-example-3
pools:
- servers:
- url: http://demo.com:9090
keepHost: true
loadBalance:
policy: roundRobin
maxRedirection: 10
```
Conversely, if your `pools.servers.url` is IP-based and you prefer the backend request to use this IP, activate the `setUpstreamHost` option as illustrated below:
```yaml
kind: Proxy
name: proxy-example-4
pools:
- setUpstreamHost: true
servers:
- url: http://demo.com:9090
loadBalance:
policy: roundRobin
maxRedirection: 10
```
Note that `keepHost` takes precedence over `setUpstreamHost` because `keepHost` applies to individual servers, whereas `setUpstreamHost` affects the entire pool.
### Configuration
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| pools | [proxy.ServerPoolSpec](#proxyserverpoolspec) | The pool without `filter` is considered the main pool, other pools with `filter` are considered candidate pools, and a `Proxy` must contain exactly one main pool. When `Proxy` gets a request, it first goes through the candidate pools, and if one of the pool's filter matches the request, servers of this pool handle the request, otherwise, the request is passed to the main pool. | Yes |
| mirrorPool | [proxy.ServerPoolSpec](#proxyserverpoolspec) | Define a mirror pool, requests are sent to this pool simultaneously when they are sent to candidate pools or main pool | No |
| compression | [proxy.Compression](#proxycompression) | Response compression options | No |
| mtls | [proxy.MTLS](#proxymtls) | mTLS configuration | No |
| maxIdleConns | int | Controls the maximum number of idle (keep-alive) connections across all hosts. Default is 10240 | No |
| maxIdleConnsPerHost | int | Controls the maximum idle (keep-alive) connections to keep per-host. Default is 1024 | No |
| serverMaxBodySize | int64 | Max size of response body. the default value is 4MB. Responses with a body larger than this option are discarded. When this option is set to `-1`, Easegress takes the response body as a stream and the body can be any size, but some features are not possible in this case, please refer [Stream](7.05.Stream.md) for more information. | No |
| maxRedirection | int | The maxRedirection parameter determines the maximum number of redirections allowed by the HTTP client for each request. A default value of zero means that redirection is not allowed, while a number greater than zero specifies the maximum allowed number of redirections. | No |
### Results
| Value | Description |
| ------------- | -------------------------------------------------------|
| internalError | Encounters an internal error |
| clientError | Client-side (Easegress) network error |
| serverError | Server-side network error |
| failureCode | Resp failure code matches failureCodes set in poolSpec |
## SimpleHTTPProxy
The `SimpleHTTPProxy` filter is a simplified version of the Proxy filter, unlike
`Proxy`, which are mainly used as reverse proxy, this filter is mainly for
forward proxies.
The following example demonstrates a basic configuration for `SimpleHTTPProxy`.
Unlike the `Proxy` filter, the backend service's address is not specified in
the `SimpleHTTPProxy` configuration. Instead, the request URL is used directly,
allowing for the use of a single `SimpleHTTPProxy` instance for any backend
services.
```yaml
name: simple-http-proxy
kind: Pipeline
flow:
- filter: requestBuilder
- filter: proxy
filters:
- kind: RequestBuilder
name: requestBuilder
template: |
url: http://127.0.0.1:9095
method: GET
- kind: SimpleHTTPProxy
name: proxy
```
The following example demonstrates a forward proxy setup. Requests directed to 'example.com' will be forwarded, while all other requests will be denied. It's important to note that when operating a forward proxy, the paths attribute in the `HTTPServer` rule should be left empty. This is because, for HTTPS requests, the client initiates a `CONNECT` request which does not include a path.
```yaml
kind: HTTPServer
name: httpserver
port: 8088
keepAlive: true
https: false
rules:
- host: 'example.com'
paths:
- backend: pipeline-forward
---
name: pipeline-forward
kind: Pipeline
filters:
- name: forward-proxy
kind: SimpleHTTPProxy
serverMaxBodySize: -1
```
To test this forward proxy configuration, use the following command:
```bash
https_proxy=http://127.0.0.1:8088 http_proxy=http://127.0.0.1:8088 curl https://example.com
```
### Configuration
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| retryPolicy | string | Retry policy name | No |
| timeout | string | Request calceled when timeout | No |
| compression | [proxy.Compression](#proxycompression) | Response compression options | No |
| maxIdleConns | int | Controls the maximum number of idle (keep-alive) connections across all hosts. Default is 10240 | No |
| maxIdleConnsPerHost | int | Controls the maximum idle (keep-alive) connections to keep per-host. Default is 1024 | No |
| serverMaxBodySize | int64 | Max size of response body. the default value is 4MB. Responses with a body larger than this option are discarded. When this option is set to `-1`, Easegress takes the response body as a stream and the body can be any size, but some features are not possible in this case, please refer [Stream](7.05.Stream.md) for more information. | No |
### Results
| Value | Description |
| ------------- | -------------------------------------------------------|
| internalError | Encounters an internal error |
| clientError | Client-side (Easegress) network error |
| serverError | Server-side network error |
## WebSocketProxy
The WebSocketProxy filter is a proxy of the websocket backend service.
Below is one of the simplest WebSocketProxy configurations, it forwards
the websocket connection to `ws://127.0.0.1:9095` or `ws://127.0.0.1:9096` or `ws://127.0.0.1:9097`.
```yaml
kind: WebSocketProxy
name: proxy-example-1
pools:
- servers:
- url: ws://127.0.0.1:9095
# keepHost: true, the `Host` will be the same as the original request
# If the backend is a load balancer, it would prove to be highly beneficial
keepHost: true
- url: ws://127.0.0.1:9096
- url: ws://127.0.0.1:9097
loadBalance:
policy: roundRobin
# the max number of bytes to read for a single message in client/server connection.
# default is 32769, set -1 to disable limit.
clientMaxMsgSize: 32769
serverMaxMsgSize: 32769
```
Same as the `Proxy` filter:
- a `filter` can be configured on a pool.
- the servers of a pool can be dynamically configured via service discovery.
- When there are multiple servers in a pool, the pool can do a load balance
between them.
Note, when routing traffic to a pipeline with a `WebSocketProxy`, the
`HTTPServer` must set the corresponding `clientMaxBodySize` to `-1`, as
below:
```yaml
name: demo-server
kind: HTTPServer
port: 8080
rules:
- paths:
path: /ws
clientMaxBodySize: -1 # REQUIRED!
backend: websocket-pipeline
```
### Health Check
Perform a health check on the servers in the pool. If a server fails the check, it will be marked as unhealthy, and requests will be rerouted to other healthy servers until it regains health. Health check for websocket proxy contains both http way or websocket way. The HTTP check involves a request-response evaluation similar to a Proxy filter. In the WebSocket method, a successful connection yields a 101 status code. Additional headers can be set and evaluated in both methods.
If you send both two ways of health check, then a server passes both HTTP and WebSocket health checks, it will be considered healthy.
```
/* Detailed source-code truncated for AI context efficiency. */
```
### Configuration
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| pools | [websocketproxy.WebSocketServerPoolSpec](#websocketproxywebsocketserverpoolspec) | The pool without `filter` is considered the main pool, other pools with `filter` are considered candidate pools, and a `Proxy` must contain exactly one main pool. When `WebSocketProxy` gets a request, it first goes through the candidate pools, and if it matches one of the pool's filter, servers of this pool handle the connection, otherwise, it is passed to the main pool. | Yes |
### Results
| Value | Description |
| ------------- | -------------------------------------------------------|
| internalError | Encounters an internal error |
| clientError | Client-side network error |
## CORSAdaptor
The CORSAdaptor handles the [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) preflight, simple and not so simple request for the backend service.
The below example configuration handles the CORS `GET` request from `*.megaease.com`.
```yaml
kind: CORSAdaptor
name: cors-adaptor-example
allowedOrigins: ["http://*.megaease.com"]
allowedMethods: [GET]
```
### Configuration
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| allowedOrigins | []string | An array of origins a cross-domain request can be executed from. If the special `*` value is present in the list, all origins will be allowed. An origin may contain a wildcard (*) to replace 0 or more characters (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penalty. Only one wildcard can be used per origin. Default value is `*` | No |
| allowedMethods | []string | An array of methods the client is allowed to use with cross-domain requests. The default value is simple methods (HEAD, GET, and POST) | No |
| allowedHeaders | []string | An array of non-simple headers the client is allowed to use with cross-domain requests. If the special `*` value is present in the list, all headers will be allowed. The default value is [] but "Origin" is always appended to the list | No |
| allowCredentials | bool | Indicates whether the request can include user credentials like cookies, HTTP authentication, or client-side SSL certificates | No |
| exposedHeaders | []string | Indicates which headers are safe to expose to the API of a CORS API specification | No |
| maxAge | int | Indicates how long (in seconds) the results of a preflight request can be cached. The default is 0 stands for no max age | No |
### Results
| Value | Description |
| ----------- | ------------------------------------------------------------------- |
| preflighted | The request is a preflight one and has been processed successfully. |
| rejected | The request was rejected by CORS checking. |
## Fallback
The Fallback filter mocks a response as the fallback action of other filters.
The below example configuration mocks the response with a specified status
code, headers, and body.
```yaml
kind: Fallback
name: fallback-example
mockCode: 200
mockHeaders:
Content-Type: application/json
mockBody: '{"message": "The feature turned off, please try it later."}'
```
### Configuration
| Name | Type | Description | Required |
| ----------- | ----------------- | ------------------------------------------------------------------------------------ | -------- |
| mockCode | int | This code overwrites the status code of the original response | Yes |
| mockHeaders | map[string]string | Headers to be added/set to the original response | No |
| mockBody | string | Default is an empty string, overwrite the body of the original response if specified | No |
### Results
| Value | Description |
| -------- | ---------------------------------------------------------------------------- |
| fallback | The fallback steps have been executed, this filter always return this result |
| responseNotFound | No response found |
## Mock
The Mock filter mocks responses according to configured rules, mainly for
testing purposes.
Below is an example configuration to mock response for requests to path
`/users/1` with specified status code, headers, and body, also with a 100ms
delay to mock the time for request processing.
```yaml
kind: Mock
name: mock-example
rules:
- match:
path: /users/1
code: 200
headers:
Content-Type: application/json
body: '{"name": "alice", "age": 30}'
delay: 100ms
```
### Configuration
| Name | Type | Description | Required |
| ----- | ------------------------ | ------------- | -------- |
| rules | [][mock.Rule](#mockrule) | Mocking rules | Yes |
### Results
| Value | Description |
| ------ | ----------------------------------------------------------------- |
| mocked | The request matches one of the rules and response has been mocked |
## RemoteFilter
The RemoteFilter is a filter making remote service act as an internal filter.
It forwards original request & response information to the remote service and
returns a result according to the response of the remote service.
The below example configuration forwards request & response information to
`http://127.0.0.1:9096/verify`.
```yaml
kind: RemoteFilter
name: remote-filter-example
url: http://127.0.0.1:9096/verify
timeout: 500ms
```
### Configuration
| Name | Type | Description | Required |
| ------- | ------ | -------------------------------------- | -------- |
| url | string | Address of remote service | Yes |
| timeout | string | Timeout duration of the remote service | No |
### Results
| Value | Description |
| --------------- | --------------------------------------------------------------------------------------------- |
| failed | Failed to send the request to remote service, or remote service returns a non-2xx status code |
| responseAlready | The remote service returns status code 205 |
## RequestAdaptor
The RequestAdaptor modifies the original request according to configuration.
The example configuration below adds prefix `/v3` to the request path.
```yaml
kind: RequestAdaptor
name: request-adaptor-example
path:
addPrefix: /v3
```
The example configuration below removes header `X-Version` from all `GET` requests and set header with key `Host` and value from current request host. See more details about template in [here](#template-of-builder-filters).
```yaml
kind: RequestAdaptor
name: request-adaptor-example
method: GET
header:
del: ["X-Version"]
template: |
method: '{{ .req.Method }}'
header:
set:
Host: '{{ .req.Host }}'
```
The structure of template follows the structure of `Configuration` below.
The example configuration below modifies the request path using regular expressions.
```yaml
kind: RequestAdaptor
name: request-adaptor-example
path:
regexpReplace:
regexp: "^/([a-z]+)/([a-z]+)" # groups /$1/$2 for lowercase alphabet
replace: "/$2/$1" # changes the order of groups
```
The example configuration below signs the request using the
[Amazon Signature V4](https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html)
signing process, with the default configuration of this signing process.
```yaml
kind: RequestAdaptor
name: request-adaptor-example
path:
signer:
for: "aws4"
```
### Configuration
| Name | Type | Description | Required |
| -----------| -------------------------------------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -------- |
| method | string | If provided, the method of the original request is replaced by the value of this option | No |
| path | [pathadaptor.Spec](#pathadaptorspec) | Rules to revise request path | No |
| header | [httpheader.AdaptSpec](#httpheaderadaptspec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
| host | string | If provided the host of the original request is replaced by the value of this option. | No |
| decompress | string | If provided, the request body is replaced by the value of decompressed body. Now support "gzip" decompress | No |
| compress | string | If provided, the request body is replaced by the value of compressed body. Now support "gzip" compress | No |
| sign | [requestadaptor.SignerSpec](#requestadaptorsignerspec) | If provided, sign the request using the [Amazon Signature V4](https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html) signing process with the configuration | No |
| template | string | template to create request adaptor, please refer the [template](#template-of-builder-filters) for more information | No |
| leftDelim | string | left action delimiter of the template, default is `{{` | No |
| rightDelim | string | right action delimiter of the template, default is `}}` | No |
**NOTE**: template field takes higher priority than the static field with the same name.
### Results
| Value | Description |
| -------------- | ---------------------------------------- |
| decompressFail | the request body can not be decompressed |
| compressFail | the request body can not be compressed |
| signFail | the request body can not be signed |
## RequestBuilder
The RequestBuilder creates a new request from existing requests/responses
according to the configuration, and saves the new request into the
[namespace](7.01.Controllers.md#pipeline) it is bound.
The example configuration below creates a reference to the request of
namespace `DEFAULT`.
```yaml
name: requestbuilder-example-1
kind: RequestBuilder
protocol: http
sourceNamespace: DEFAULT
```
The example configuration below creates an HTTP request with method `GET`,
url `http://127.0.0.1:8080`, header `X-Mock-Header:mock-value`, and body
`this is the body`.
```yaml
name: requestbuilder-example-1
kind: RequestBuilder
protocol: http
template: |
method: get
url: http://127.0.0.1:8080
headers:
X-Mock-Header:
- mock-value
body: "this is the body"
```
### Configuration
| Name | Type | Description | Required |
|-----------------|--------|-----------------------------------------------|----------|
| protocol | string | protocol of the request to build, default is `http`. | No |
| sourceNamespace | string | add a reference to the request of the source namespace | No |
| template | string | template to create request, the schema of this option must conform with `protocol`, please refer the [template](#template-of-builder-filters) for more information | No |
| leftDelim | string | left action delimiter of the template, default is `{{` | No |
| rightDelim | string | right action delimiter of the template, default is `}}` | No |
**NOTE**: `sourceNamespace` and `template` are mutually exclusive, you must
set one and only one of them.
### Results
| Value | Description |
| -------------- | ---------------------------------------- |
| buildErr | error happens when build request |
## RateLimiter
RateLimiter protects backend service for high availability and reliability
by limiting the number of requests sent to the service in a configured duration.
Below example configuration limits `GET`, `POST`, `PUT`, `DELETE` requests
to path which matches regular expression `^/pets/\d+$` to 50 per 10ms, and a
request fails if it cannot be permitted in 100ms due to high concurrency
requests count.
```yaml
kind: RateLimiter
name: rate-limiter-example
policies:
- name: policy-example
timeoutDuration: 100ms
limitRefreshPeriod: 10ms
limitForPeriod: 50
defaultPolicyRef: policy-example
urls:
- methods: [GET, POST, PUT, DELETE]
url:
regex: ^/pets/\d+$
policyRef: policy-example
```
### Configuration
| Name | Type | Description | Required |
| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- |
| policies | [][ratelimiter.Policy](#ratelimiterpolicy) | Policy definitions | Yes |
| defaultPolicyRef | string | The default policy, if no `policyRef` is configured in one of the `urls`, it uses this policy | No |
| urls | [][urlrule.URLRule](#urlruleurlrule) | An array of request match criteria and policy to apply on matched requests. Note that a standalone RateLimiter instance is created for each item of the array, even two or more items can refer to the same policy | Yes |
### Results
| Value | Description |
| ----------- | ---------------------------------------------------------- |
| rateLimited | The request has been rejected as a result of rate limiting |
## ResponseAdaptor
The ResponseAdaptor modifies the input response according to the configuration.
Below is an example configuration that adds a header named `X-Response-Adaptor`
with the value `response-adaptor-example` to the input response.
```yaml
kind: ResponseAdaptor
name: response-adaptor-example
header:
add:
X-Response-Adaptor: response-adaptor-example
```
### Configuration
| Name | Type | Description | Required |
| ------ | -------- |---------------------------------------------------------------------------------------------------------------------| -------- |
| header | [httpheader.AdaptSpec](#httpheaderadaptspec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
| compress | string | compress body, currently only support gzip | No |
| decompress | string | decompress body, currently only support gzip | No |
| template | string | template to create response adaptor, please refer the [template](#template-of-builder-filters) for more information | No |
| leftDelim | string | left action delimiter of the template, default is `{{` | No |
| rightDelim | string | right action delimiter of the template, default is `}}` | No |
**NOTE**: template field takes higher priority than the static field with the same name.
### Results
| Value | Description |
| ---------------- | ---------------------------------------------------------- |
| responseNotFound | responseNotFound response is not found |
| decompressFailed | error happens when decompress body |
| compressFailed | error happens when compress body |
## ResponseBuilder
The ResponseBuilder creates a new response from existing requests/responses
according to the configuration, and saves the new response into the
[namespace](7.01.Controllers.md#pipeline) it is bound.
The example configuration below creates a reference to the response of
namespace `DEFAULT`.
```yaml
name: responsebuilder-example-1
kind: ResponseBuilder
protocol: http
sourceNamespace: DEFAULT
```
The example configuration below creates an HTTP response with status code
200, header `X-Mock-Header:mock-value`, and body `this is the body`.
```yaml
name: responsebuilder-example-1
kind: ResponseBuilder
protocol: http
template: |
statusCode: 200
headers:
X-Mock-Header:
- mock-value
body: "this is the body"
```
### Configuration
| Name | Type | Description | Required |
|-----------------|--------|-----------------------------------------------|----------|
| protocol | string | protocol of the response to build, default is `http`. | No |
| sourceNamespace | string | add a reference to the response of the source namespace | No |
| template | string | template to create response, the schema of this option must conform with `protocol`, please refer the [template](#template-of-builder-filters) for more information | No |
| leftDelim | string | left action delimiter of the template, default is `{{` | No |
| rightDelim | string | right action delimiter of the template, default is `}}` | No |
**NOTE**: `sourceNamespace` and `template` are mutually exclusive, you must
set one and only one of them.
### Results
| Value | Description |
| -------------- | ---------------------------------------- |
| buildErr | error happens when build response. |
## Validator
The Validator filter validates requests, forwards valid ones, and rejects
invalid ones. Four validation methods (`headers`, `jwt`, `signature`, `oauth2`
and `basicAuth`) are supported up to now, and these methods can either be
used together or alone. When two or more methods are used together, a request
needs to pass all of them to be forwarded.
Below is an example configuration for the `headers` validation method.
Requests which has a header named `Is-Valid` with value `abc` or `goodplan`
or matches regular expression `^ok-.+$` are considered to be valid.
```yaml
kind: Validator
name: header-validator-example
headers:
Is-Valid:
values: ["abc", "goodplan"]
regexp: "^ok-.+$"
```
Below is an example configuration for the `jwt` validation method.
```yaml
kind: Validator
name: jwt-validator-example
jwt:
cookieName: auth
algorithm: HS256
secret: 6d79736563726574
```
Below is an example configuration for the `signature` validation method,
note multiple access keys id/secret pairs can be listed in `accessKeys`,
but there's only one pair here as an example.
```yaml
kind: Validator
name: signature-validator-example
signature:
accessKeys:
AKID: SECRET
```
Below is an example configuration for the `oauth2` validation method which
uses a token introspection server for validation.
```yaml
kind: Validator
name: oauth2-validator-example
oauth2:
tokenIntrospect:
endPoint: https://127.0.0.1:8443/auth/realms/test/protocol/openid-connect/token/introspect
clientId: easegress
clientSecret: 42620d18-871d-465f-912a-ebcef17ecb82
insecureTls: false
```
Here's an example of `basicAuth` validation method which uses
[Apache2 htpasswd](https://manpages.debian.org/testing/apache2-utils/htpasswd.1.en.html)
formatted encrypted password file for validation.
```yaml
kind: Validator
name: basicAuth-validator-example
basicAuth:
mode: "FILE"
userFile: /etc/apache2/.htpasswd
```
### Configuration
| Name | Type | Description | Required |
| --------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| headers | map[string][httpheader.ValueValidator](#httpheadervaluevalidator) | Header validation rules, the key is the header name and the value is validation rule for corresponding header value, a request needs to pass all of the validation rules to pass the `headers` validation | No |
| jwt | [validator.JWTValidatorSpec](#validatorjwtvalidatorspec) | JWT validation rule, validates JWT token string from the `Authorization` header or cookies | No |
| signature | [signer.Spec](#signerspec) | Signature validation rule, implements an [Amazon Signature V4](https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html) compatible signature validation validator, with customizable literal strings | No |
| oauth2 | [validator.OAuth2ValidatorSpec](#validatoroauth2validatorspec) | The `OAuth/2` method support `Token Introspection` mode and `Self-Encoded Access Tokens` mode, only one mode can be configured at a time | No |
| basicAuth | [validator.BasicAuthValidatorSpec](#validatorbasicauthvalidatorspec) | The `BasicAuth` method support `FILE`, `ETCD` and `LDAP` mode, only one mode can be configured at a time. | No |
### Results
| Value | Description |
| ------- | ----------------------------------- |
| invalid | The request doesn't pass validation |
## WasmHost
The WasmHost filter implements a host environment for user-developed
[WebAssembly](https://webassembly.org/) code. Below is an example
configuration that loads wasm code from a file, and more details could be
found in [this document](../03.Advanced-Cookbook/3.07.WasmHost.md).
```yaml
name: wasm-host-example
kind: WasmHost
maxConcurrency: 2
code: /home/megaease/wasm/hello.wasm
timeout: 200ms
```
Note: this filter is disabled in the default build of `Easegress`, it can
be enabled by:
```bash
make GOTAGS=wasmhost
```
or
```bash
make wasm
```
### Configuration
| Name | Type | Description | Required |
| -------------- | ----------------- | ----------------------------------------------------------------------------------------------- | -------- |
| maxConcurrency | int32 | The maximum requests the filter can process concurrently. Default is 10 and minimum value is 1. | Yes |
| code | string | The wasm code, can be the base64 encoded code, or path/url of the file which contains the code. | Yes |
| timeout | string | Timeout for wasm execution, default is 100ms. | Yes |
| parameters | map[string]string | Parameters to initialize the wasm code. | No |
### Results
| Value | Description |
| --------------------------------------------------------------------------- | -------------------------------------------------- |
| outOfVM | Can not found an available wasm VM. |
| wasmError | An error occurs during the execution of wasm code. |
| wasmResult1 Results defined and returned by wasm code. |
| ... |
| wasmResult9 |
## Kafka
The Kafka filter converts HTTP Requests to Kafka messages and sends them to
the Kafka backend. The topic of the Kafka message comes from the HTTP header,
if not found, then the default topic will be used. The payload of the Kafka
message comes from the body of the HTTP Request.
Below is an example configuration.
```yaml
kind: Kafka
name: kafka-example
backend: [":9093"]
# sync determines the usage of AsyncProducer or SyncProducer for the Kafka filter.
# default is false. If set to true, encountering a message error will cause the Kafka filter
# to respond with a status code of 503 and a body containing "{err: "error message"}".
sync: false
topic:
# default topic for Kafka message
default: kafka-topic
# dynamic topic for Kafka message, get from http header
dynamic:
header: X-Kafka-Topic
key:
# default key for Kafka message
default: kafka-key
# dynamic key for Kafka message, get from http header
dynamic:
header: X-Kafka-Key
```
### Configuration
| Name | Type | Description | Required |
| ------------ | -------- | -------------------------------- | -------- |
| backend | []string | Addresses of Kafka backend | Yes |
| sync | bool | Usage of AsyncProducer or SyncProducer, default is false | No |
| topic | [Kafka.Topic](#kafkatopic) | the topic is Spec used to get Kafka topic used to send message to the backend | Yes |
| key | [Kafka.Key](#kafkakey) | the key is Spec used to get Kafka message key | No |
### Results
| Value | Description |
| ----------------------- | ------------------------------------ |
| parseErr | Failed to get Kafka message from the HTTP request |
## HeaderToJSON
The HeaderToJSON converts HTTP headers to JSON and combines it with the HTTP
request body. To use this filter, make sure your HTTP Request body is empty
or JSON schema.
Below is an example configuration.
```yaml
kind: HeaderToJSON
name: headertojson-example
headerMap:
- header: X-User-Name
json: username
- header: X-Type
json: type
```
### Configuration
| Name | Type | Description | Required |
| ------------ | -------- | -------------------------------- | -------- |
| headerMap | [][HeaderToJSON.HeaderMap](#headertojsonheadermap) | headerMap defines a map between HTTP header name and corresponding JSON field name | Yes |
### Results
| Value | Description |
| ----------------------- | --------------------------------------- |
| jsonEncodeDecodeErr | Failed to convert HTTP headers to JSON. |
| bodyReadErr | Request body is stream |
## CertExtractor
CertExtractor extracts a value from requests TLS certificates Subject or
Issuer metadata () and adds the
value to headers. Request can contain zero or multiple certificates so
the position (first, second, last, etc) of the certificate in the chain
is required.
Here's an example configuration, that adds a new header `tls-cert-postalcode`,
based on the PostalCode of the last TLS certificate's Subject:
```yaml
kind: "CertExtractor"
name: "postalcode-extractor"
certIndex: -1 # take last certificate in chain
target: "subject"
field: "PostalCode"
headerKey: "tls-cert-postalcode"
```
### Configuration
| Name | Type | Description | Required |
| ------------ | -------- | -------------------------------- | -------- |
| certIndex | int16 | The index of the certificate in the chain. Negative indexes from the end of the chain (-1 is the last index, -2 second last etc.) | Yes |
| target | string | Either `subject` or `issuer` of the [x509.Certificate](https://pkg.go.dev/crypto/x509#Certificate) | Yes |
| field | string | One of the string or string slice fields from | Yes |
| headerKey | string | Extracted value is added to this request header key. | Yes |
### Results
The CertExtractor is always success and returns no results.
## HeaderLookup
HeaderLookup checks [custom data](../06.Development-for-Easegress/6.2.Custom-Data.md) stored in etcd and put them into HTTP header.
Suppose you create a custom data kind of `client-info` and post a data key `client1` with the value:
```yaml
name: client1
id: 123
kind: vip
```
Then HeaderLookup with the following configuration adds `X-Id:123` and `X-Kind:vip` to HTTP request header.
```yaml
name: headerlookup-example-1
kind: HeaderLookup
etcdPrefix: client-info # get custom data kind
headerKey: client1 # get custom data name
headerSetters:
- etcdKey: id # custom data value of id
headerKey: X-Id
- etcdKey: kind # custom data value of kind
headerKey: X-Kind
```
You can also use `pathRegExp` to check different keys for different requests. When `pathRegExp` is defined, `pathRegExp` is used with `regexp.FindStringSubmatch` to identify a group from the path. The first captured group is appended to the etcd key in the following format: `{headerKey's value}-{regex group}`.
Suppose you create a custom data kind of `client-info` and post several data:
```yaml
name: client-abc
id: 123
kind: vip
name: client-def
id: 124
kind: vvip
```
Then HeaderLookup with the following configuration adds `X-Id:123` and `X-Kind:vip` for requests with path `/api/abc`, adds `X-Id:124` and `X-Kind:vvip` for requests with path `/api/def`.
```yaml
name: headerlookup-example-1
kind: HeaderLookup
etcdPrefix: client-info # get custom data kind
headerKey: client # get custom data name
pathRegExp: "^/api/([a-z]+)"
headerSetters:
- etcdKey: id # custom data value of id
headerKey: X-Id
- etcdKey: kind # custom data value of kind
headerKey: X-Kind
```
### Configuration
| Name | Type | Description | Required |
|------|------|-------------|----------|
| etcdPrefix | string | Kind of custom data | Yes |
| headerKey | string | Name of custom data in given kind | Yes |
| pathRegExp | string | Reg used to get key from request path | No |
| headerSetters | [][headerlookup.HeaderSetterSpec](#headerlookup.HeaderSetterSpec) | Set custom data value to http header | Yes |
### Results
HeaderLookup has no results.
## ResultBuilder
ResultBuilder generates a string, which will be the result of the filter.
This filter exists to work with the [`jumpIf` mechanism](7.01.Controllers.md#pipeline) for conditional jumping.
Currently, the result string can only be `result0` - `result9`, this will be
changed in the future to allow arbitrary result string.
For example, we can use the following configuration to check if the request
body contains an `image` field, and forward it to `proxy1` or `proxy2`
conditionally.
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: resultBuilder
jumpIf:
result1: proxy1
result2: proxy2
- filter: proxy1
- filter: END
- filter: proxy2
filters:
- name: resultBuilder
kind: ResultBuilder
template: |
{{- if .requests.DEFAULT.JSONBody.image}}result1{{else}}result2{{end -}}
```
### Configuration
| Name | Type | Description | Required |
|-----------------|--------|-----------------------------------------------|----------|
| template | string | template to create result, please refer the [template](#template-of-builer-filters) for more information | No |
| leftDelim | string | left action delimiter of the template, default is `{{` | No |
| rightDelim | string | right action delimiter of the template, default is `}}` | No |
### Results
| Value | Description |
| --------------------------------------------------------------------------- | -------------------------------------------------- |
| unknown | The ResultBuilder generates an unknown result. |
| buildErr | Error happens when build the result. |
| result0 Results defined and returned by the template . |
| ... |
| result9 |
## DataBuilder
DataBuilder is used to manipulate and store data. The data from the previous
filter can be transformed and stored in the context so that the data can be
used in subsequent filters.
The example below shows how to use DataBuilder to store the request body in
the context.
```yaml
- name: requestBodyDataBuilder
kind: DataBuilder
dataKey: requestBody
template: |
{{.requests.DEFAULT.JSONBody | jsonEscape}}
```
### Configuration
| Name | Type | Description | Required |
|-----------------|--------|-----------------------------------------------|----------|
| template | string | template to create data, please refer the [template](#template-of-builer-filters) for more information | Yes |
| dataKey | string | key to store data | Yes |
| leftDelim | string | left action delimiter of the template, default is `{{` | No |
| rightDelim | string | right action delimiter of the template, default is `}}` | No |
### Results
| Value | Description |
|-----------------|---------------------------------------------------|
| buildErr | Error happens when building the data |
## OIDCAdaptor
OpenID Connect(OIDC) is an identity layer on top of the OAuth 2.0 protocol. It enables Clients to verify
the identity of the End-User based on the authentication performed by an Authorization Server, as well as
to obtain basic profile information about the End-User.
For identity platforms that implement standard OIDC specification like [Google Accounts](https://accounts.google.com)、[OKTA](https://www.okta.com/)、
[Auth0](https://auth0.com/)、[Authing](https://www.authing.cn/). configure `discovery` endpoint as below example:
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: oidc
jumpIf: { oidcFiltered: END }
filters:
- name: oidc
kind: OIDCAdaptor
cookieName: oidc-auth-cookie
clientId:
clientSecret:
discovery: https://accounts.google.com/.well-known/openid-configuration #Replace your own discovery
redirectURI: /oidc/callback
```
For third platforms that only implement OAuth2.0 like GitHub, users should configure `authorizationEndpoint`、
`tokenEndpoint`、`userinfoEndpoint` at the same time as below example:
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: oidc
jumpIf: { oidcFiltered: END }
filters:
- name: oidc
kind: OIDCAdaptor
cookieName: oidc-auth-cookie
clientId:
clientSecret:
authorizationEndpoint: https://github.com/login/oauth/authorize
tokenEndpoint: https://github.com/login/oauth/access_token
userinfoEndpoint: https://api.github.com/user
redirectURI: /oidc/callback
```
### Configuration
| Name | Type | Description | Required |
|-----------------------|--------|---------------------------------------------------------------------------------------------------------------------------|----------|
| clientId | string | The OAuth2.0 app client id | Yes |
| clientSecret | string | The OAuth2.0 app client secret | Yes |
| cookieName | string | Used to check if necessary to launch OpenIDConnect flow | No |
| discovery | string | Standard OpenID Connect discovery endpoint URL of the identity server | No |
| authorizationEndpoint | string | OAuth2.0 authorization endpoint URL | No |
| tokenEndpoint | string | OAuth2.0 token endpoint URL | No |
| userInfoEndpoint | string | OAuth2.0 user info endpoint URL | No |
| redirectURI | string | The callback uri registered in identity server, for example: `https://example.com/oidc/callback` or `/oidc/callback` | Yes |
### Results
| Value | Description |
|-----------------|----------------------------------------|
| oidcFiltered | The request is handled by OIDCAdaptor. |
After OIDCAdaptor handled, following OIDC related information can be obtained from Easegress HTTP request headers:
- **X-User-Info**: Base64 encoded OIDC End-User basic profile.
- **X-Origin-Request-URL**: End-User origin request URL before OpenID Connect or OAuth2.0 flow.
- **X-Id-Token**: The ID Token returned by OpenID Connect flow.
- **X-Access-Token**: The AccessToken returned by OpenId Connect or OAuth2.0 flow.
## OPAFilter
The [Open Policy Agent (OPA)](https://www.openpolicyagent.org/docs/latest/) is an open source,
general-purpose policy engine that unifies policy enforcement across the stack. It provides a
high-level declarative language, which can be used to define and enforce policies in
Easegress API Gateway. Currently, there are 160+ built-in operators and functions we can use,
for examples `net.cidr_contains` and `contains`.
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: opa-filter
jumpIf: { opaDenied: END }
filters:
- name: opa-filter
kind: OPAFilter
defaultStatus: 403
readBody: true
includedHeaders: a,b,c
policy: |
package http
default allow = false
allow {
input.request.method == "POST"
input.request.scheme == "https"
contains(input.request.path, "/")
net.cidr_contains("127.0.0.0/24",input.request.realIP)
}
```
The following table lists input request fields that can be used in an OPA policy to help enforce it.
| Name | Type | Description | Example |
|--------------------------|--------|-----------------------------------------------------------------------|--------------------------------------|
| input.request.method | string | The current http request method | "POST" |
| input.request.path | string | The current http request URL path | "/a/b/c" |
| input.request.path_parts | array | The current http request URL path parts | ["a","b","c"] |
| input.request.raw_query | string | The current http request raw query | "a=1&b=2&c=3" |
| input.request.query | map | The current http request query map | {"a":1,"b":2,"c":3} |
| input.request.headers | map | The current http request header map targeted by includedHeaders | {"Content-Type":"application/json"} |
| input.request.scheme | string | The current http request scheme | "https" |
| input.request.realIP | string | The current http request client real IP | "127.0.0.1" |
| input.request.body | string | The current http request body string data | {"data":"xxx"} |
### Configuration
| Name | Type | Description | Required |
|------------------|--------|--------------------------------------------------------------------------------------|----------|
| defaultStatus | int | The default HTTP status code when request is denied by the OPA policy decision | No |
| readBody | bool | Whether to read request body as OPA policy data on condition | No |
| includedHeaders | string | Names of the HTTP headers to be included in `input.request.headers`, comma-separated | No |
| policy | string | The OPA policy written in the Rego declarative language | Yes |
### Results
| Value | Description |
|-----------|-----------------------------------------------|
| opaDenied | The request is denied by OPA policy decision. |
## Redirector
The `Redirector` filter is used to do HTTP redirect. `Redirector` matches request url, do replacement, and return response with status code of `3xx` and put new path in response header with key of `Location`.
Here a simple example:
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirector
filters:
- name: redirector
kind: Redirector
match: "^/users/([0-9]+)"
replacement: "http://example.com/display?user=$1"
```
In this example, request with path `/users/123` will redirect to `http://example.com/display?user=123`.
```
HTTP/1.1 301 Moved Permanently
Location: http://example.com/display?user=123
```
More details about spec:
We use [ReplaceAllString](https://pkg.go.dev/regexp#Regexp.ReplaceAllString) to do match and replace and put output into response header with key `Location`. By default, we use `URI` as input, but you can change input by control parameter of `matchPart`.
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirector
filters:
- name: redirector
kind: Redirector
match: "^/users/([0-9]+)"
# by default, value of matchPart is uri, supported values: uri, path, full.
matchPart: "full"
replacement: "http://example.com/display?user=$1"
```
For request with URL of `https://example.com:8080/apis/v1/user?id=1`, URI part is `/apis/v1/user?id=1`, path part is `/apis/v1/user` and full part is `https://example.com:8080/apis/v1/user?id=1`.
By default, we return status code of `301` "Moved Permanently". To return status code of `302` "Found" or other `3xx`, change `statusCode` in yaml.
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirector
filters:
- name: redirector
kind: Redirector
match: "^/users/([0-9]+)"
# default value of 301, supported values: 301, 302, 303, 304, 307, 308.
statusCode: 302
replacement: "http://example.com/display?user=$1"
```
Following are some common used examples:
1. URI prefix redirect
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirector
filters:
- name: redirector
kind: Redirector
match: "^(.*)$"
matchPart: "uri"
replacement: "/prefix$1"
```
```
input: https://example.com/path/to/api/?key1=123&key2=456
output: /prefix/path/to/api/?key1=123&key2=456
```
URI prefix redirect with schema and host:
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirector
filters:
- name: redirector
kind: Redirector
match: "(^.*\/\/)([^\/]*)(.*)$"
matchPart: "full"
replacement: "${1}${2}/prefix$3"
```
```
input: https://example.com/path/to/api/?key1=123&key2=456
output: https://example.com/prefix/path/to/api/?key1=123&key2=456
```
2. Domain Redirect
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirector
filters:
- name: redirector
kind: Redirector
match: "(^.*\/\/)([^\/]*)(.*$)"
matchPart: "full"
# use ${1} instead of $1 here.
replacement: "${1}my.com${3}"
```
```
input: https://example.com/path/to/api/?key1=123&key2=456
output: https://my.com/path/to/api/?key1=123&key2=456
```
3. Path Redirect
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirector
filters:
- name: redirector
kind: Redirector
match: "/path/to/(user)\.php\?id=(\d*)"
matchPart: "uri"
replacement: "/api/$1/$2"
```
```
input: https://example.com/path/to/user.php?id=123
output: /api/user/123
```
Path redirect with schema and host:
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirector
filters:
- name: redirector
kind: Redirector
match: "(^.*\/\/)([^\/]*)/path/to/(user)\.php\?id=(\d*)"
matchPart: "full"
replacement: "${1}${2}/api/$3/$4"
```
```
input: https://example.com/path/to/user.php?id=123
output: https://example.com/api/user/123
```
### Configuration
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| match | string | Regular expression to match request path. The syntax of the regular expression is [RE2](https://golang.org/s/re2syntax) | Yes |
| matchPart | string | Parameter to decide which part of url used to do match, supported values: uri, full, path. Default value is uri. | No |
| replacement | string | Replacement when the match succeeds. Placeholders like `$1`, `$2` can be used to represent the sub-matches in `regexp` | Yes |
| statusCode | int | Status code of response. Supported values: 301, 302, 303, 304, 307, 308. Default: 301. | No |
### Results
| Value | Description |
| ----- | ----------- |
| redirected | The request has been redirected |
## RedirectorV2
The `RedirectorV2` filter provides advanced HTTP redirection capabilities within the Kubernetes API Gateway. It offers fine-grained control over URL components such as scheme, hostname, and path. The specifications are consistent with the [Kubernetes Gateway API's `HTTPRequestRedirectFilter`](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRequestRedirectFilter).
### Configuration
| Name | Type | Description | Required |
|------|------|-------------|----------|
| scheme | string | The protocol for the redirected request (e.g., `http` or `https`). | No |
| hostname | string | The domain name to which the request should be redirected. To specify a port, include it in the hostname (e.g., `example.com:8080`). Note: Explicit port configurations are currently unsupported due to complexities in specification. | No |
| statusCode | int | The HTTP status code for the redirection response. | Yes |
| path.type | string | Determines the type of redirection. Supported values: `ReplacePrefixMatch`, `ReplaceFullPath`. | Yes |
| path.replacePrefixMatch | string | The new prefix for the redirection. Used only with `ReplacePrefixMatch`. | Conditional |
| path.replaceFullPath | string | The new full path for the redirection. Used only with `ReplaceFullPath`. | Conditional |
### Results
| Value | Description |
|-------|-------------|
| redirected | Indicates that the request has been redirected based on the `RedirectorV2` configuration. |
Commmon Use-Cases:
1. Replace Prefix:
Substitute a prefix with `/account` and return a `302 Found` status code. The prefix was decided in `pathPrefix` in te matchting rule in HTTPServer.
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirectorv2
filters:
- name: redirectorv2
kind: RedirectorV2
path:
type: ReplacePrefixMatch
replacePrefixMatch: /account
statusCode: 302
```
2. Replace Full Path:
Redirect to an absolute path `/full-path`.
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirectorv2
filters:
- name: redirectorv2
kind: RedirectorV2
path:
type: ReplaceFullPath
replaceFullPath: /full-path
statusCode: 302
```
3. Domain and Scheme Redirection:
Redirect to a new domain using the HTTPS protocol.
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: redirectorv2
filters:
- name: redirectorv2
kind: RedirectorV2
scheme: https
hostname: newdomain.com
path:
type: ReplacePrefixMatch
replacePrefixMatch: /account
statusCode: 302
```
## GRPCProxy
The `GRPCProxy` filter is a proxy for gRPC backend service. It supports both unary RPCs and streaming RPCs.
Below is one of the simplest `GRPCProxy` configurations, it forwards incoming gRPC connections to `127.0.0.1:9095`.
```yaml
name: demo-pipeline
kind: Pipeline
flow:
- filter: proxy
filters:
- name: proxy
kind: GRPCProxy
pools:
- servers:
- url: http://127.0.0.1:9095
```
Same as the `Proxy` filter:
- a `filter` can be configured on a pool.
- the servers of a pool can be configured dynamically via service discovery.
- when there are multiple servers in a pool, the pool can do a load balance between them.
Because gRPC does not support the http `Connect` method, it does not support tunneling mode,
we provide a new [load balancer](#proxyloadbalancespec) `policy.forward` to achieve a similar effect.
Note that each gRPC client establishes a connection with Easegress. However,
Easegress may utilize a single connection when forwarding requests from various
clients to a gRPC server, due to its use of HTTP2. This action could potentially
disrupt some client or server applications. For instance, if the client
applications are structured to directly connect to the server, and both the
client and server have the ability to request a connection closure, then
problems may arise once Easegress is installed between them. If the server
wants to close the connection of one client, it closes the shared connection
with Easegress, thus affecting other clients.
### Configuration
| Name | Type | Description | Required |
| ------------ | ------------------------------------------------------ | --------------------------------------------------------------------------- | -------- |
| pools | [grpcproxy.ServerPoolSpec](#grpcproxyserverpoolspec) | The pool without `filter` is considered the main pool, other pools with `filter` are considered candidate pools, and a `GRPCProxy` must contain exactly one main pool. When a `GRPCProxy` gets a request, it first goes through the candidate pools, and if one of the pool's filter matches the request, servers of this pool handle the request, otherwise, the request is passed to the main pool. | Yes |
| timeout | string | The total time from easegress receive request to receive response, default is never timeout, only apply to unary calls. | No |
| borrowTimeout | string | Timeout of borrow a connection from pool. Default is never timeout. | No |
| connectTimeout | string | Timeout until a new connection is fully established. Default is never timeout. | No |
| maxIdleConnsPerHost | int | For a address, the maximum of connections allowed to create. Default value is 1024 | No |
### Results
| Value | Description |
|----------------|------------------------------|
| internalError | Encounters an internal error |
| clientError | Client-side error |
| serverError | Server-side error |
## AIGatewayProxy
The AIGatewayProxy filter handles AI Gateway traffic by routing requests to configured AI providers through the AIGatewayController. It acts as a bridge between incoming requests and AI service providers like OpenAI, DeepSeek and so on.
The AIGatewayProxy requires an AIGatewayController to be configured with the specified provider. The filter will forward requests to the appropriate AI provider based on the providerName configuration.
Example with complete pipeline:
```yaml
name: ai-gateway-pipeline
kind: Pipeline
flow:
- filter: ai-gateway-proxy
filters:
- name: ai-gateway-proxy
kind: AIGatewayProxy
providerName: openai-provider
```
### Configuration
| Name | Type | Description | Required |
|--------------|-----------|------------------------------------------------------------------|----------|
| providerName | string | Name of the AI provider configured in the AIGatewayController | Yes |
| middlewares | []string | List of middleware names to apply during request processing | No |
### Results
| Value | Description |
|-----------------------------|--------------------------------------------------|
| noAIGatewayControllerError | No AIGatewayController found or configured |
| internalError | Encounters an internal error during processing |
| providerNotFound | The specified provider is not configured |
| middlewareError | Error occurred in one of the configured middlewares |
| requestProcessed | Request was successfully processed |
## WAF
Example with complete pipeline:
```yaml
name: waf-pipeline
kind: Pipeline
filters:
- name: waf-filter
kind: WAF
ruleGroup: sqlinjection
- name: proxy
kind: Proxy
pools:
- servers:
- url: http://127.0.0.1:9095
- url: http://127.0.0.1:9096
loadBalance:
policy: roundRobin
```
### Configuration
| Name | Type | Description | Required |
|--------------|-----------|------------------------------------------------------------------|----------|
| ruleGroup | string | Name of the WAF rule configured in the WAFController | Yes |
### Results
| Value | Description |
|-----------------------------|--------------------------------------------------|
| noWAFControllerError | No WAFController found or configured |
| ruleGroupNotFoundError | WAF rule group not found |
| blocked | Request blocked by WAF rule. |
| internalError | Error occurred during processing the request |
## FileServer
Miniuim config example:
```yaml
name: fileserver-pipeline
kind: Pipeline
filters:
- name: fileserver-filter
kind: FileServer
root: "/var/www/example"
```
Complete config example:
```yaml
name: fileserver-pipeline
kind: Pipeline
filters:
- name: fileserver-filter
kind: FileServer
root: "/var/www/example"
index: ["index.html", "index.txt"] # default is index.html and index.txt
hidden: [".git", "/build", "*/*.conf"]
tryFiles: ["{path}", "{path}/", "/index.html", "=404 error message"]
rewrite: "^/users/(\d+)$ /users.php?id=$1"
precompressed: "gzip br"
compress: "gzip"
cache:
bufferPoolSize: 2 * 1024 * 1024 * 1024 # default is 2GB
bufferPoolMaxFileSize: 10 * 1024 * 1024 # default is 10MB
bufferPoolTTL: 600 # default is 600 seconds
cacheFileExtensionFilters:
- pattern: ["*.html", "*.css"]
etagMaxAge: 3600 # default is 3600
- pattern: ["/usr/*.js"]
```
### Configuration
| Name | Type | Description | Required |
| --- | --- | --- | --- |
| root | string | The root directory path from which to serve files. | Yes |
| index | []string | A list of filenames to look for, in order, when a directory is requested. Defaults to `["index.html", "index.txt"]`. | No |
| hidden | []string | A list of glob patterns for files or directories to hide. Requests for these files will be treated as if they do not exist (404 Not Found). | No |
| tryFiles | []string | A sequence of files to try serving in order. If the previous file is not found, the next one is tried. Useful for Single-Page Applications (SPAs) or front-controller patterns. Supports placeholders like `{path}` and can end with an error code like `=404`. | No |
| rewrite | string | A rewrite rule used to internally modify the request URI before file lookups. It uses regular expression matching and capture groups (e.g., `$1`). | No |
| precompressed | string | A space-separated list of precompressed formats (e.g., `gzip br`). For a request to `/file`, it will check for the existence of `/file.gz`, `/file.br`, etc. | No |
| compress | string | The compression method (e.g., `gzip`) to use for on-the-fly compression of responses that are not precompressed. | No |
| cache | [CacheSpec](#fileservercachespec) | A container for configuring caching-related settings. | No |
#### More about hidden rules
##### 1. Component Patterns (rules without a path separator)
These patterns (e.g., ".git", "*.log") are matched against each individual name component of the relative path.
```
- Rule: ".git"
- Hides: "/path/to/project/.git", "/path/to/.git/config"
- Does NOT hide: "/path/to/project/git"
- Rule: "node_modules"
- Hides: "/path/to/project/node_modules", "/path/to/node_modules/express"
```
##### 2. Path Patterns (rules with a path separator):
These patterns are matched against the full absolute path. This matching is done in two ways:
```
a) As a prefix: If the rule is a prefix of the path, followed by a path separator, it's a match.
- Rule: "/build"
- Hides: "/build/app.js", "/build/"
- Does NOT hide: "/builder/app.js"
b) As a glob pattern: The rule is treated as a glob pattern to be matched against the entire absolute path.
- Rule: "/*/*/*.conf"
- Hides: "/etc/nginx/nginx.conf"
- Does NOT hide: "/etc/nginx.conf"
```
### Results
| Value | Description |
| --- | --- |
| internalError | An internal error occurred within the FileServer system |
| serverError | A server-side error occurred |
| clientError | The client's request was blocked |
| notFound | A required resource could not be found |
## Common Types
### pathadaptor.Spec
| Name | Type | Description | Required |
| ------------ | ------------------------------------------------------ | --------------------------------------------------------------------------- | -------- |
| replace | string | Replaces request path with the value of this option when specified | No |
| addPrefix | string | Prepend the value of this option to request path when specified | No |
| trimPrefix | string | Trims the value of this option if request path start with it when specified | No |
| regexpReplace | [pathadaptor.RegexpReplace](#pathadaptorregexpreplace) | Revise request path with regular expression | No |
### pathadaptor.RegexpReplace
| Name | Type | Description | Required |
| ------- | ------ | ----------------------------------------------------------------------------------------------------------------------- | -------- |
| regexp | string | Regular expression to match request path. The syntax of the regular expression is [RE2](https://golang.org/s/re2syntax) | Yes |
| replace | string | Replacement when the match succeeds. Placeholders like `$1`, `$2` can be used to represent the sub-matches in `regexp` | Yes |
### httpheader.AdaptSpec
Rules to revise request header.
| Name | Type | Description | Required |
| ---- | ----------------- | ----------------------------------- | -------- |
| del | []string | Name of the headers to be removed | No |
| set | map[string]string | Name & value of headers to be set | No |
| add | map[string]string | Name & value of headers to be added | No |
### proxy.ServerPoolSpec
| Name | Type | Description | Required |
| --------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------ | -------- |
| spanName | string | Span name for tracing, if not specified, the `url` of the target server is used | No |
| serverTags | []string | Server selector tags, only servers have tags in this array are included in this pool | No |
| servers | [][proxy.Server](#proxyserver) | An array of static servers. If omitted, `serviceName` and `serviceRegistry` must be provided, and vice versa | No |
| serviceName | string | This option and `serviceRegistry` are for dynamic server discovery | No |
| serviceRegistry | string | This option and `serviceName` are for dynamic server discovery | No |
| loadBalance | [proxy.LoadBalance](#proxyloadbalancespec) | Load balance options | Yes |
| memoryCache | [proxy.MemoryCacheSpec](#proxymemorycachespec) | Options for response caching | No |
| filter | [proxy.RequestMatcherSpec](#proxyrequestmatcherspec) | Filter options for candidate pools | No |
| serverMaxBodySize | int64 | Max size of response body, will use the option of the Proxy if not set. Responses with a body larger than this option are discarded. When this option is set to `-1`, Easegress takes the response body as a stream and the body can be any size, but some features are not possible in this case, please refer [Stream](7.05.Stream.md) for more information. | No |
| timeout | string | Request calceled when timeout | No |
| retryPolicy | string | Retry policy name | No |
| circuitBreakerPolicy | string | CircuitBreaker policy name | No |
| failureCodes | []int | Proxy return result of failureCode when backend resposne's status code in failureCodes. The default value is 5xx | No |
| healthCheck | ProxyHealthCheckSpec | Health check. Full example with details in [Proxy Health Check](#health-check) | No |
| setUpstreamHost | bool | Set request host to the host of backend server url if true. Default is false. | No |
### proxy.Server
| Name | Type | Description | Required |
| ------ | -------- | ------------------------------------------------------------------------------------------------------------ | -------- |
| url | string | Address of the server. The address should start with `http://` or `https://` (when used in the `WebSocketProxy`, it can also start with `ws://` and `wss://`), followed by the hostname or IP address of the server, and then optionally followed by `:{port number}`, for example: `https://www.megaease.com`, `http://10.10.10.10:8080`. When host name is used, the `Host` of a request sent to this server is always the hostname of the server, and therefore using a [RequestAdaptor](#requestadaptor) in the pipeline to modify it will not be possible; when IP address is used, the `Host` is the same as the original request, that can be modified by a [RequestAdaptor](#requestadaptor). See also `KeepHost`. | Yes |
| tags | []string | Tags of this server, refer `serverTags` in [proxy.PoolSpec](#proxyPoolSpec) | No |
| weight | int | When load balance policy is `weightedRandom`, this value is used to calculate the possibility of this server | No |
| keepHost | bool | If true, the `Host` is the same as the original request, no matter what is the value of `url`. Default value is `false`. | No |
### proxy.LoadBalanceSpec
| Name | Type | Description | Required |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------- | -------- |
| policy | string | Load balance policy, valid values are `roundRobin`, `random`, `weightedRandom`, `ipHash`, `headerHash`, `cookieHash` and `forward`, the last one is only used in `GRPCProxy` | Yes |
| headerHashKey | string | When `policy` is `headerHash`, this option is the name of a header whose value is used for hash calculation | No |
| stickySession | [proxy.StickySession](#proxystickysessionspec) | Sticky session spec | No |
| healthCheck | [proxy.HealthCheck](#proxyhealthcheckspec) | (Deprecated) Use [Proxy](#health-check) or [WebSocketProxy](#health-check-1) instead. | No |
| forwardKey | string | The value of this field is a header name of the incoming request, the value of this header is address of the target server (host:port), and the request will be sent to this address | No |
### proxy.StickySessionSpec
| Name | Type | Description | Required |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------- | -------- |
| mode | string | Mode of session stickiness, support `CookieConsistentHash`,`DurationBased`,`ApplicationBased` | Yes |
| appCookieName | string | Name of the application cookie, its value will be used as the session identifier for stickiness in `CookieConsistentHash` and `ApplicationBased` mode | No |
| lbCookieName | string | Name of the cookie generated by load balancer, its value will be used as the session identifier for stickiness in `DurationBased` and `ApplicationBased` mode, default is `EG_SESSION` | No |
| lbCookieExpire | string | Expire duration of the cookie generated by load balancer, its value will be used as the session expire time for stickiness in `DurationBased` and `ApplicationBased` mode, default is 2 hours | No |
### proxy.HealthCheckSpec
(Deprecated) Use [Proxy](#health-check) or [WebSocketProxy](#health-check-1) instead.
| Name | Type | Description | Required |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------- | -------- |
| interval | string | Interval duration for health check, default is 60s | Yes |
| path | string | Path URL for server health check | No |
| timeout | string | Timeout duration for health check, default is 3s | No |
| fails | int | Consecutive fails count for assert fail, default is 1 | No |
| passes | int | Consecutive passes count for assert pass , default is 1 | No |
### proxy.MemoryCacheSpec
| Name | Type | Description | Required |
| ------------- | -------- | ------------------------------------------------------------------------------ | -------- |
| codes | []int | HTTP status codes to be cached | Yes |
| expiration | string | Expiration duration of cache entries | Yes |
| maxEntryBytes | uint32 | Maximum size of the response body, response with a larger body is never cached | Yes |
| methods | []string | HTTP request methods to be cached | Yes |
### proxy.RequestMatcherSpec
Polices:
- If the policy is empty or `general`, matcher match requests with `headers` and `urls`.
- If the policy is `ipHash`, the matcher match requests if their IP hash value is less than `permil``.
- If the policy is `headerHash`, the matcher match requests if their header hash value is less than `permil`, use the key of `headerHashKey`.
- If the policy is `random`, the matcher matches requests with probability `permil`/1000.
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| policy | string | Policy used to match requests, support `general`, `ipHash`, `headerHash`, `random` | No |
| headers | map[string][StringMatcher](#stringmatcher) | Request header filter options. The key of this map is header name, and the value of this map is header value match criteria | No |
| urls | [][proxy.MethodAndURLMatcher](#proxymethodandurlmatcher) | Request URL match criteria | No |
| permil | uint32 | the probability of requests been matched. Value between 0 to 1000 | No |
| matchAllHeaders | bool | All rules in headers should be match | No |
| headerHashKey | string | Used by policy `headerHash`. | No |
### grpcproxy.ServerPoolSpec
| Name | Type | Description | Required |
| --------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------ | -------- |
| spanName | string | Span name for tracing, if not specified, the `url` of the target server is used | No |
| serverTags | []string | Server selector tags, only servers have tags in this array are included in this pool | No |
| servers | [][proxy.Server](#proxyserver) | An array of static servers. If omitted, `serviceName` and `serviceRegistry` must be provided, and vice versa | No |
| serviceName | string | This option and `serviceRegistry` are for dynamic server discovery | No |
| serviceRegistry | string | This option and `serviceName` are for dynamic server discovery | No |
| loadBalance | [proxy.LoadBalance](#proxyloadbalancespec) | Load balance options | Yes |
| filter | [grpcproxy.RequestMatcherSpec](#grpcproxyrequestmatcherspec) | Filter options for candidate pools | No |
| circuitBreakerPolicy | string | CircuitBreaker policy name | No |
### grpcproxy.RequestMatcherSpec
Polices:
- If the policy is empty or `general`, matcher match requests with `headers`, `urls` and `methods`.
- If the policy is `ipHash`, the matcher match requests if their IP hash value is less than `permil``.
- If the policy is `headerHash`, the matcher match requests if their header hash value is less than `permil`, use the key of `headerHashKey`.
- If the policy is `random`, the matcher matches requests with probability `permil`/1000.
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| policy | string | Policy used to match requests, support `general`, `ipHash`, `headerHash`, `random` | No |
| headers | map[string][StringMatcher](#stringmatcher) | Request header filter options. The key of this map is header name, and the value of this map is header value match criteria | No |
| urls | [][proxy.MethodAndURLMatcher](#proxymethodandurlmatcher) | Request URL match criteria | No |
| permil | uint32 | the probability of requests been matched. Value between 0 to 1000 | No |
| matchAllHeaders | bool | All rules in headers should be match | No |
| headerHashKey | string | Used by policy `headerHash`. | No |
| methods | [][StringMatcher](#stringmatcher) | Method name filter options. | No |
### StringMatcher
The relationship between `exact`, `prefix`, and `regex` is `OR`.
| Name | Type | Description | Required |
| ------ | ------ | --------------------------------------------------------------------------- | -------- |
| exact | string | The string must be identical to the value of this field. | No |
| prefix | string | The string must begin with the value of this field | No |
| regex | string | The string must the regular expression specified by the value of this field | No |
| empty | bool | The string must be empty | No |
### proxy.MethodAndURLMatcher
The relationship between `methods` and `url` is `AND`.
| Name | Type | Description | Required |
| ------- | ------------------------------------------ | ---------------------------------------------------------------- | -------- |
| methods | []string | HTTP method criteria, Default is an empty list means all methods | No |
| url | [StringMatcher](#stringmatcher) | Criteria to match a URL | Yes |
### urlrule.URLRule
The relationship between `methods` and `url` is `AND`.
| Name | Type | Description | Required |
| --------- | ------------------------------------------ | ---------------------------------------------------------------- | -------- |
| methods | []string | HTTP method criteria, Default is an empty list means all methods | No |
| url | [StringMatcher](#stringmatcher) | Criteria to match a URL | Yes |
| policyRef | string | Name of resilience policy for matched requests | No |
### proxy.Compression
| Name | Type | Description | Required |
| --------- | ---- | --------------------------------------------------------------------------------------------- | -------- |
| minLength | int | Minimum response body size to be compressed, response with a smaller body is never compressed | Yes |
### proxy.MTLS
| Name | Type | Description | Required |
| -------------- | ------ | ------------------------------ | -------- |
| certBase64 | string | Base64 encoded certificate | Yes |
| keyBase64 | string | Base64 encoded key | Yes |
| rootCertBase64 | string | Base64 encoded root certificate | Yes |
| insecureSkipVerify| bool | insecureSkipVerify controls whether a client verifies the server's certificate chain and host name. If insecureSkipVerify is true, crypto/tls accepts any certificate presented by the server and any host name in that certificate. In this mode, TLS is susceptible to machine-in-the-middle attacks unless custom verification is used. This should be used only for testing or in combination with VerifyConnection or VerifyPeerCertificate. | No |
### websocketproxy.WebSocketServerPoolSpec
| Name | Type | Description | Required |
| --------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------ | -------- |
| serverTags | []string | Server selector tags, only servers have tags in this array are included in this pool | No |
| servers | [][proxy.Server](#proxyserver) | An array of static servers. If omitted, `serviceName` and `serviceRegistry` must be provided, and vice versa | No |
| serviceName | string | This option and `serviceRegistry` are for dynamic server discovery | No |
| serviceRegistry | string | This option and `serviceName` are for dynamic server discovery | No |
| serverMaxMsgSize | int | Max server message size, default is 32768. | No |
| clientMaxMsgSize | int | Max client message size, default is 32768. | No |
| loadBalance | [proxy.LoadBalance](#proxyloadbalancespec) | Load balance options | Yes |
| filter | [proxy.RequestMatcherSpec](#proxyrequestmatcherspec) | Filter options for candidate pools | No |
| insecureSkipVerify | bool | Disable origin verification when accepting client connections, default is `false`. | No |
| originPatterns | []string | Host patterns for authorized origins, used to enable cross origin WebSockets. | No |
| healthCheck | WSProxyHealthCheckSpec | Health check for Websocket. Full example with details in [WebSocketProxy Health Check](#health-check-1) | No |
### mock.Rule
| Name | Type | Description | Required |
| ---------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| code | int | HTTP status code of the mocked response | Yes |
| match | [MatchRule](#mock.MatchRule) | Rule to match a request | Yes |
| delay | string | Delay duration, for the request processing time mocking | No |
| headers | map[string]string | Headers of the mocked response | No |
| body | string | Body of the mocked response, default is an empty string | No |
### mock.MatchRule
| Name | Type | Description | Required |
| ---------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| path | string | Path match criteria, if request path is the value of this option, then the response of the request is mocked according to this rule | No |
| pathPrefix | string | Path prefix match criteria, if request path begins with the value of this option, then the response of the request is mocked according to this rule | No |
| matchAllHeaders | bool | Whether to match all headers | No |
| headers | map[string][StringMatcher](#stringmatcher) | Headers to match, key is a header name, value is the rule to match the header value | No |
### ratelimiter.Policy
| Name | Type | Description | Required |
| ------------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| name | string | Name of the policy. Must be unique in one RateLimiter configuration | Yes |
| timeoutDuration | string | Maximum duration a request waits for permission to pass through the RateLimiter. The request fails if it cannot get permission in this duration. Default is 100ms | No |
| limitRefreshPeriod | string | The period of a limit refresh. After each period the RateLimiter sets its permissions count back to the `limitForPeriod` value. Default is 10ms | No |
| limitForPeriod | int | The number of permissions available in one `limitRefreshPeriod`. Default is 50 | No |
### httpheader.ValueValidator
| Name | Type | Description | Required |
| ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| values | []string | An array of strings, if one of the header values of any header of the request is found in the array, the request is considered to pass the validation of current rule | No |
| regexp | string | A regular expression, if one of the header values of any header of the request matches this regular expression, the request is considered to pass the validation of current rule | No |
### validator.JWTValidatorSpec
| Name | Type | Description | Required |
|------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
| cookieName | string | The name of a cookie, if this option is set and the cookie exists, its value is used as the token string, otherwise, the `Authorization` header is used | No |
| algorithm | string | The algorithm for validation:`HS256`,`HS384`,`HS512`,`RS256`,`RS384`,`RS512`,`ES256`,`ES384`,`ES512`,`EdDSA` are supported | Yes |
| publicKey | string | The public key is used for `RS256`,`RS384`,`RS512`,`ES256`,`ES384`,`ES512` or `EdDSA` validation in hex encoding | Yes |
| secret | string | The secret is for `HS256`,`HS384`,`HS512` validation in hex encoding | Yes |
### validator.BasicAuthValidatorSpec
| Name | Type | Description | Required |
|--------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
| mode | string | The mode of basic authentication, valid values are `FILE`, `ETCD` and `LDAP` | Yes |
| userFile | string | The user file used for `FILE` mode | No |
| etcdPrefix | string | The etcd prefix used for `ETCD` mode | No |
| ldap | [basicAuth.LDAPSpec](#basicauthldapspec) | The LDAP configuration used for `LDAP` mode | No |
### basicAuth.LDAPSpec
| Name | Type | Description | Required |
|--------------|--------|-------------------------------------------------------------------------|----------|
| host | string | The host of the LDAP server | Yes |
| port | int | The port of the LDAP server | Yes |
| baseDN | string | The base dn of the LDAP server, e.g. `ou=users,dc=example,dc=org` | Yes |
| uid | string | The user attribute used to bind user, e.g. `cn` | Yes |
| useSSL | bool | Whether to use SSL | No |
| skipTLS | bool | Whether to skip `StartTLS` | No |
| insecure | bool | Whether to skip verifying LDAP server's certificate chain and host name | No |
| serverName | string | Server name used to verify certificate when `insecure` is `false` | No |
| certBase64 | string | Base64 encoded certificate | No |
| keyBase64 | string | Base64 encoded key | No |
### signer.Spec
| Name | Type | Description | Required |
| ----------- | -------------------------------- | ------------------------------------------------------------------------- | -------- |
| literal | [signer.Literal](#signerliteral) | Literal strings for customization, default value is used if omitted | No |
| excludeBody | bool | Exclude request body from the signature calculation, default is `false` | No |
| ttl | string | Time to live of a signature, default is 0 means a signature never expires | No |
| accessKeys | map[string]string | A map of access key id to access key secret | Yes |
| accessKeyId | string | ID used to set credential | No |
| accessKeySecret | string | Value usd to set credential | No |
| ignoredHeaders | []string | Headers to be ignored | No |
| headerHoisting | signer.HeaderHoisting | HeaderHoisting defines which headers are allowed to be moved from header to query in presign: header with name has one of the allowed prefixes, but hasn't any disallowed prefixes and doesn't match any of disallowed names are allowed to be hoisted | No |
### signer.HeaderHoisting
| Name | Type | Description | Required |
|------------------|----------|-------------------------------|----------|
| allowedPrefix | []string | Allowed prefix for headers | No |
| disallowedPrefix | []string | Disallowed prefix for headers | No |
| disallowed | []string | Disallowed headers | No |
### signer.Literal
| Name | Type | Description | Required |
| ---------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| scopeSuffix | string | The last part to build credential scope, default is `request`, in `Amazon Signature V4`, it is `aws4_request` | No |
| algorithmName | string | The query name of the signature algorithm in the request, default is `X-Algorithm`, in `Amazon Signature V4`, it is `X-Amz-Algorithm` | No |
| algorithmValue | string | The header/query value of the signature algorithm for the request, default is "HMAC-SHA256", in `Amazon Signature V4`, it is `AWS4-HMAC-SHA256` | No |
| signedHeaders | string | The header/query headers of the signed headers, default is `X-SignedHeaders`, in `Amazon Signature V4`, it is `X-Amz-SignedHeaders` | No |
| signature | string | The query name of the signature, default is `X-Signature`, in `Amazon Signature V4`, it is `X-Amz-Signature` | No |
| date | string | The header/query name of the request time, default is `X-Date`, in `Amazon Signature V4`, it is `X-Amz-Date` | No |
| expires | string | The query name of expire duration, default is `X-Expires`, in `Amazon Signature V4`, it is `X-Amz-Date` | No |
| credential | string | The query name of credential, default is `X-Credential`, in `Amazon Signature V4`, it is `X-Amz-Credential` | No |
| contentSha256 | string | The header name of body/payload hash, default is `X-Content-Sha256`, in `Amazon Signature V4`, it is `X-Amz-Content-Sha256` | No |
| signingKeyPrefix | string | The prefix is prepended to access key secret when deriving the signing key, default is an empty string, in `Amazon Signature V4`, it is `AWS4` | No |
### validator.OAuth2ValidatorSpec
| Name | Type | Description | Required |
| --------------- | ------------------------------------------------------------------ | ------------------------------------------------- | -------- |
| tokenIntrospect | [validator.OAuth2TokenIntrospect](#validatoroauth2tokenintrospect) | Configuration for Token Introspection mode | No |
| jwt | [validator.OAuth2JWT](#validatoroauth2jwt) | Configuration for Self-Encoded Access Tokens mode | No |
### validator.OAuth2TokenIntrospect
| Name | Type | Description | Required |
| ------------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| endPoint | string | The endpoint of the token introspection server | Yes |
| clientId | string | Client id of Easegress in the token introspection server | No |
| clientSecret | string | Client secret of Easegress | No |
| basicAuth | string | If `clientId` not specified and this option is specified, its value is used for basic authorization with the token introspection server | No |
| insecureTls | bool | Whether the connection between Easegress and the token introspection server need to be secure or not, default is `false` means the connection need to be a secure one | No |
### validator.OAuth2JWT
| Name | Type | Description | Required |
| --------- | ------ | ------------------------------------------------------------------------ | -------- |
| algorithm | string | The algorithm for validation, `HS256`, `HS384` and `HS512` are supported | Yes |
| secret | string | The secret for validation, in hex encoding | Yes |
### kafka.Topic
| Name | Type | Description | Required |
| --------- | ------ | ------------------------------------------------------------------------ | -------- |
| default | string | Default topic for Kafka backend | Yes |
| dynamic.header | string | The HTTP header that contains Kafka topic | Yes |
### kafka.Key
| Name | Type | Description | Required |
| --------- | ------ | ------------------------------------------------------------------------ | -------- |
| default | string | Default key for Kafka message | Yes |
| dynamic.header | string | The HTTP header that contains Kafka key | No |
### headertojson.HeaderMap
| Name | Type | Description | Required |
| --------- | ------ | ------------------------------------------------------------------------ | -------- |
| header | string | The HTTP header that contains JSON value | Yes |
| json | string | The field name to put JSON value into HTTP body | Yes |
### headerlookup.HeaderSetterSpec
| Name | Type | Description | Required |
|------|------|-------------|----------|
| etcdKey | string | Key used to get data | No |
| headerKey | string | Key used to set data into http header | No |
### requestadaptor.SignerSpec
This type is derived from [signer.Spec](#signerspec), with the following
two more fields.
| Name | Type | Description | Required |
|------|------|-------------|----------|
| apiProvider | string | The RequestAdaptor pre-defines the [Literal](#signerliteral) and [HeaderHoisting](#signerheaderhoisting) configuration for some API providers, specify the provider name in this field to use one of them, only `aws4` is supported at present. | No |
| scopes | []string | Scopes of the input request | No |
### Template Of Builder Filters
The content of the `template` field in the builder filters' spec is a
a template defined in Golang [text/template](https://pkg.go.dev/text/template),
with extra functions from the [sprig](https://go-task.github.io/slim-sprig/)
package, and extra functions defined by Easegress:
- **addf**: calculate the sum of the input two numbers.
- **subf**: calculate the difference of the two input numbers.
- **mulf**: calculate the product of the two input numbers.
- **divf**: calculate the quotient of the two input numbers.
- **log**: write a log message to Easegress log, the first argument must be
`debug`, `info`, `warn` or `error`, and the second argument is the message.
- **mergeObject**: merge two or more objects into one, the type of the input
objects must be `map[string]interface{}`, and if one of their field is
also an object, its type must also be `map[string]interface{}`.
- **jsonEscape**: escape a string so that it can be used as the key or value
in JSON text.
- **urlQueryEscape**: escapes the string so that it can be safely placed inside
a URL query, equivalent to the `urlquery` template function.
- **urlQueryUnescape**: performs the inverse transformation of `urlQueryEscape`,
decoding a URL-encoded string back to its origin form.
- **host**: host splits a network address of the form "host:port" and return host part by using `net.SplitHostPort`.
- **port**: port splits a network address of the form "host:port" and return port part by using `net.SplitHostPort`.
Easegress injects existing requests/responses of the current context into
the template engine at runtime, so we can use `.requests..`
or `.responses..` to read the information out (the
available fields vary from the protocol of the request or response,
and please refer [Pipeline](7.01.Controllers.md#pipeline) for what is `namespace`).
For example, if the request of the `DEFAULT` namespace is an HTTP one, we
can access its method via `.requests.DEFAULT.Method`.
For convenience, shorthand notations are used to simplify the access of default request and response properties. In this notation:
- `.req.Host` is equal to `.requests.DEFAULT.Host`
- `.resp.Body` is equal to `.responses.DEFAULT.Body`
Here, `.req` is a shorthand for `.requests.DEFAULT`, and similarly, `.resp` is shorthand for `.requests.DEFAULT`.
Easegress also injects other data into the template engine, which can be
accessed with `.data.`, for example, we can use `.data.PIPELINE` to
read the data defined in the pipeline spec.
The `template` should generate a string in YAML format, the schema of the
result YAML varies from filters and protocols.
Use `RequestAdaptor` as an example:
```yaml
kind: RequestAdaptor
name: request-adaptor
template: |
header:
set:
Content: '{{ header .req.Header "Content-Length" }}'
Content-Type: '{{ header .req.Header "Content-Type" }}'
Host: '{{ .req.Host }}'
Method: '{{ .req.Method }}'
Remote-Addr: '{{ .req.RemoteAddr }}'
Remote-User: '{{ username .req }}'
Request-Body: '{{ .req.Body }}'
Request-URI: '{{ .req.RequestURI }}'
Scheme: '{{ .req.URL.Scheme }}'
```
#### HTTP Specific
- **Available fields of existing requests**
All exported fields of the [http.Request](https://pkg.go.dev/net/http#Request).
And `RawBody` is the body as bytes; `Body` is the body as string; `JSONBody`
is the body as a JSON object; `YAMLBody` is the body as a YAML object.
- **Available fields of existing responses**
All exported fields of the [http.Response](https://pkg.go.dev/net/http#Response).
And `RawBody` is the body as bytes; `Body` is the body as string; `JSONBody`
is the body as a JSON object; `YAMLBody` is the body as a YAML object.
- **Schema of result request**
| Name | Type | Description | Required |
|------|------|-------------|----------|
| method | string | HTTP Method of the result request, default is `GET`. | No |
| url | string | URL of the result request, default is `/`. | No |
| headers | map[string][]string | Headers of the result request. | No |
| body | string | Body of the result request. | No |
| formData | map[string]field | Body of the result request, in form data pattern. | No |
Please note `body` takes higher priority than `formData`, and the schema of
`field` in `formData` is:
| Name | Type | Description | Required |
|----------|--------|---------------------|----------|
| value | string | value of the field. | No |
| fileName | string | the file name, if value is the content of a file. | No |
- **Schema of result response**
| Name | Type | Description | Required |
|------|------|-------------|----------|
| statusCode | int | HTTP status code, default is 200. | No |
| headers | map[string][]string | Headers of the result request. | No |
| body | string | Body of the result request. | No |
- **Schema of RequestAdaptor**
| Name | Type | Description | Required |
|------|------|-------------|----------|
| method | string | If provided, the method of the original request is replaced by the value of this option | No |
| path | [pathadaptor.Spec](#pathadaptorspec) | Rules to revise request path | No |
| header | [httpheader.AdaptSpec](#httpheaderadaptspec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
| host | string | If provided the host of the original request is replaced by the value of this option. | No |
- **Schema of ResponseAdaptor**
| Name | Type | Description | Required |
|------|------|-------------|----------|
| header | [httpheader.AdaptSpec](#httpheaderadaptspec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
### fileserver.CacheSpec
This configuration is nested under the `cache` field.
| Name | Type | Description | Required |
| --- | --- | --- | --- |
| bufferPoolSize | integer | The maximum size of the in-memory cache pool in bytes. Defaults to `2147483648` (2 GB). | No |
| bufferPoolMaxFileSize | integer | The maximum size in bytes that a single file can be to be cached in the buffer pool. Defaults to `10485760` (10 MB). | No |
| bufferPoolTTL | integer | The time-to-live (TTL) for items in the cache pool, in seconds. Defaults to `600`. | No |
| cacheFileExtensionFilters | [][FileExtensionFilter](#fileserverfileextensionfilter) | A list of rules to control `ETag` cache headers based on file patterns. | No |
### fileserver.FileExtensionFilter
This configuration is for each object within the `cacheFileExtensionFilters` array.
| Name | Type | Description | Required |
| --- | --- | --- | --- |
| pattern | []string | A list of glob patterns to match files against (e.g., `["*.html", "*.css"]`). | Yes |
| etagMaxAge | integer | The `max-age` value, in seconds, to set for the `ETag` response header for files matching this pattern. Defaults to `3600`. | No |
---
## File: docs/07.Reference/7.03.Ingress-Controller.md
# IngressController
- [Prerequisites](#prerequisites)
- [Configuration](#configuration)
- [Controller spec](#controller-spec)
- [Getting Started](#getting-started)
- [Role Based Access Control configuration](#role-based-access-control-configuration)
- [Configurations to ConfigMap](#configurations-to-configmap)
- [Deploy Easegress IngressController](#deploy-easegress-ingresscontroller)
- [Create backend service \& Kubernetes ingress](#create-backend-service--kubernetes-ingress)
- [Multi-instance IngressController](#multi-instance-ingresscontroller)
The IngressController is an implementation of [Kubernetes ingress controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/), it watches Kubernetes Ingress, Service, Endpoints, and Secrets then translates them to Easegress HTTP server and pipelines.
## Prerequisites
1. K8s cluster : **v1.18+**
## Configuration
### Controller spec
```yaml
kind: IngressController
name: ingress-controller-example
kubeConfig:
masterURL:
namespaces: ["default"]
ingressClass: easegress
httpServer:
port: 8080
https: false
keepAlive: true
keepAliveTimeout: 60s
maxConnections: 10240
```
- IngressController uses `kubeConfig` and `masterURL` to connect to Kubernetes, at least one of them must be specified when deployed outside of a Kubernetes cluster, and both are optional when deployed inside a cluster.
- The `namespaces` is an array of Kubernetes namespaces which the IngressController needs to watch, all namespaces are watched if left empty.
- IngressController only handles `Ingresses` with `ingressClassName` set to `ingressClass`, the default value of `ingressClass` is `easegress`.
- One IngressController manages a shared HTTP traffic gate and multiple pipelines according to the Kubernetes ingress. The `httpServer` section in the spec is the basic configuration for the shared HTTP traffic gate. The routing part of the HTTP server and pipeline configurations will be generated dynamically according to Kubernetes ingresses.
## Getting Started
### Role Based Access Control configuration
If your cluster is configured with RBAC, first you will need to authorize Easegress IngressController for using the Kubernetes API. Below is an example configuration:
```yaml
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: easegress-ingress-controller
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["services", "endpoints", "secrets"]
verbs: ["get", "watch", "list"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "watch", "list"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: easegress-ingress-controller
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: easegress-ingress-controller
subjects:
- kind: ServiceAccount
name: easegress-ingress-controller
namespace: default
roleRef:
kind: ClusterRole
name: easegress-ingress-controller
apiGroup: rbac.authorization.k8s.io
```
Note the name of the ServiceAccount we just created is `easegress-ingress-controller`, it will be used later.
### Configurations to ConfigMap
Let's use ConfigMap to store Easegress server configuration and Easegress ingress configuration. This ConfigMap is used later in Deployment.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: easegress-cm
namespace: default
data:
easegress-server.yaml: |
name: ingress-easegress
cluster-name: easegress-ingress-controller
cluster-role: primary
api-addr: 0.0.0.0:2381
data-dir: /opt/easegress/data
log-dir: /opt/easegress/log
debug: false
controller.yaml: |
kind: IngressController
name: ingress-controller-example
kubeConfig:
masterURL:
namespaces: ["default"]
ingressClass: easegress
httpServer:
port: 8080
https: false
keepAlive: true
keepAliveTimeout: 60s
maxConnections: 10240
```
The `easegress-server.yaml` creates Easegress instance named *easegress-ingress-controller* and `controller.yaml` defines IngressController object for Easegress.
### Deploy Easegress IngressController
To deploy the IngressController, we will create a Deployment and a Service as below:
```
/* Detailed source-code truncated for AI context efficiency. */
```
The IngressController is created via the command line argument `initial-object-config-files` of `easegress-server`. Notice how Easegress logs and data are stored to *emptyDir* called `ingress-data-volume` inside the pod. IngressController is stateless so we can restart new pods without preserving previous state.
Last but not least let's create service for forwarding the Ingress traffic to Easegress.
```yaml
apiVersion: v1
kind: Service
metadata:
name: easegress-public
namespace: default
spec:
ports:
- name: web
protocol: TCP
port: 8080
nodePort: 30080
selector:
app: easegress-ingress
type: NodePort
```
The port `web` is to receive external HTTP requests from port 30080 and forward them to the HTTP server in Easegress.
### Create backend service & Kubernetes ingress
Apply below YAML configuration to Kubernetes:
```yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deployment
spec:
selector:
matchLabels:
app: products
department: sales
replicas: 2
template:
metadata:
labels:
app: products
department: sales
spec:
containers:
- name: hello-v1
image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0"
env:
- name: "PORT"
value: "50001"
- name: hello-v2
image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
env:
- name: "PORT"
value: "50002"
---
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
type: NodePort
selector:
app: products
department: sales
ports:
- name: port-v1
protocol: TCP
port: 60001
targetPort: 50001
- name: port-v2
protocol: TCP
port: 60002
targetPort: 50002
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-example
spec:
ingressClassName: easegress
rules:
- host: "www.example.com"
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: hello-service
port:
number: 60001
- host: "*.megaease.com"
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: hello-service
port:
number: 60002
```
Once all pods are up and running, we can leverage the command below to access both versions of the `hello` application:
```bash
$ curl http://{NODE_IP}:30080/ -HHost:www.megaease.com
Hello, world!
Version: 2.0.0
Hostname: hello-deployment-6cbf765985-r6242
$ curl http://{NODE_IP}:30080/ -HHost:www.example.com
Hello, world!
Version: 1.0.0
Hostname: hello-deployment-6cbf765985-r6242
```
And we can see Easegress IngressController has forwarded requests to the correct application version according to Kubernetes ingress.
## Multi-instance IngressController
In previous chapters we created IngressController with one instance running. To support high-availability scenarios, you can increase the number of replicas in the Deployment:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: easegress-ingress
name: easegress
namespace: default
spec:
replicas: 2 # number of IngressController instances running
...
```
---
## File: docs/07.Reference/7.04.FaaSController.md
# FaaSController
- [Prerequisites](#prerequisites)
- [Configuration](#configuration)
- [Controller spec](#controller-spec)
- [FaaSFunction spec](#faasfunction-spec)
- [Lifecycle](#lifecycle)
- [RESTful APIs](#restful-apis)
- [Demoing](#demoing)
- [Reference](#reference)
* A FaaSController is a business controller for handling Easegress and FaaS products integration purposes. It abstracts `FaasFunction`, `FaaSStore` and, `FaasProvider`. Currently, we only support `Knative` type `FaaSProvider`. The `FaaSFunction` describes the name, image URL, the resource, and autoscaling type of this FaaS function instance. The `FaaSStore` is covered by Easegress' embed Etcd already.
* FaaSController works closely with local `FaaSProvider`. Please make sure they are running in a communicable environment. Follow this [knative doc](https://knative.dev/docs/install/yaml-install/serving/install-serving-with-yaml/) to install `Knative`[1]'s serving component in K8s. It's better to have Easegress run in the same VM instances with K8s for saving communication costs.
## Prerequisites
1. K8s cluster : **v1.23+**
2. `Knative` Serving : **v1.3+** (with kourier type of network layer)
## Configuration
### Controller spec
* One FaaSController will manage one shared HTTP traffic gate and multiple pipelines according to the functions it has.
* The `httpserver` section in spec is the configuration for the shared HTTP traffic gate.
* The `Knative` section is for `Knative` type of `FaaSProvider`. Depending your Kubernetes cluster, you can use either Magic DNS or Temporary DNS, see [here](https://knative.dev/docs/install/yaml-install/serving/install-serving-with-yaml/#configure-dns). Here's how you fill the `Knative` section for each one of them:
* **Temporary DNS**: The value of `networkLayerURL` can be found using the following command
``` bash
$ kubectl get svc -n kourier-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kourier LoadBalancer 10.109.159.129 80:31731/TCP,443:30571/TCP 250dk
```
The `CLUSTER-IP` with value `10.109.159.129` is your kourier's K8s service's address. Use it as the value for `networkLayerURL` in the YAML below.
* `hostSuffix`'s value should be `example.com` [2], like described in `Knative` serving's `Temporary DNS`.
* **Magic DNS**: For `networkLayerURL`, use the `EXTERNAL-IP` of the loadbalancer:
```bash
$ kubectl get svc -n kourier-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kourier LoadBalancer 1.2.3.4 some-external-ip-of-my-cloud-provider.com 80:31060/TCP,443:30384/TCP 12m
```
* For `hostSuffix`, use `kn service list` to see the suffix of your functions: For url `http://demo.default.4.5.6.7.sslip.io` the `hostSuffix` is `4.5.6.7.sslip.io` (basically the IP `x.x.x.x` + `sslip.io`). **Note:** If you don't have any functions yet deployed, you first use any value for `hostSuffix` (for example `example.com`), then deploy a function and use `kn service list` to find out the value of `hostSuffix`. Update it to your configuration and re-create FaaSController.
```yaml
name: faascontroller
kind: FaaSController
provider: knative # FaaS provider kind, currently we only support Knative
syncInterval: 10s
httpServer:
http3: false
port: 10083
keepAlive: true
keepAliveTimeout: 60s
https: false
certBase64:
keyBase64:
maxConnections: 10240
knative:
networkLayerURL: http://{knative_kourier_clusterIP} # or http://{knative_kourier_externalIP}
hostSuffix: example.com # or x.x.x.x.sslip.com for Magic DNS
```
### FaaSFunction spec
* The FaaSFunction spec including `name`, `image`, and other resource-related configurations.
* The `image` is the HTTP microservice's image URL. When upgrading the FaaSfFunction's business logic. this field can be helpful.
* The `resource` and `autoscaling` fields are similar to K8s or `Knative`'s resource management configuration.[3]
* The `requestAdaptor` is for customizing the way how HTTP request content will be routed to `Knative`'s `kourier` gateway.
```yaml
name: "demo10"
image: "dev.local/colordeploy:17.0"
port: 8089
autoScaleType: "rps"
autoScaleValue: "111"
minReplica: 1
maxReplica: 3
limitCPU: "180m"
limitMemory: "100Mi"
requestCPU: "80m"
requestMemory: "20Mi"
requestAdaptor:
header:
set:
X-Func1: func-demo-10 # add one HTTP header
```
### Lifecycle
There four types of function state: Initial, Active, InActive, and Failed[4]. Basically, they come from AWS Lambda's status.
* `Initial`: Once the function has been created in Easegress, its original state is `initial`. After checking FaaSProvider(Knative)'s status successfully, it will become `active` automatically. And the function is ready for handling traffic.
* `Active`: Easegress's FaaSFunction will be `active` not matter there are requests or not. **Easegress will only route ingress traffic to FaaSProvider when the function is in the `active` state.**
* `Inactive`: Stopping function execution by calling FaaSController's `stop` RESTful API and it will run into `inactive`. Updating function's spec for image URL or other fields, or deleting function also need to stop it first.
* `Failed`: The function will be turned into `failed` states during the runtime checking. If it's about some configuration error, e.g., wrong docker image URL, we can detect this failure by function's `status` message and then update the function's spec by calling RESTful API. If it's about some temporal failure caused by FaaSProvider, the function will turn into the `initial` state after FaaSProvider is recovered.
```
Provision
│
│
│
┌─────▼──────┐ Start ┌────────────┐
│ │ Success │ │
┌────────┤ Initial ├────────────────► Active │
│ │ │ │ ├──────┐
│ └───┬───▲────┘ └────┬───▲───┘ │
│ │ │ │ │ │
│ │ │ │ │ │
│ Errors│ │ Update Stop │ │ Start │
│ │ ├───────────┐ │ │Success │
│ │ │ │ │ │ │
│ ┌───▼───┴────┐ │ ┌────▼───┴───┐ │
│ │ │ └─────────┤ │ │
Delete │ │ Failed │ │ Inactive │ │
│ │ ◄────────────────┤ │ │
│ └───┬───▲────┘ Start Failed └──────┬─────┘ │
│ │ │ │ │
│ │ │ Errors │ │
│ Delete │ └────────────────────────────┼────────────┘
│ │ │
│ │ │
│ ┌───▼────────┐ │
│ │ │ Delete │
└────────► Destory ◄───────────────────────┘
│ │
└────────────┘
```
| Original State | Event | New State |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| initial | Checking the status in FaaSProvider by FaaSController automatically, and it's ready | active |
| initial | Checking the status in FaaSProvider by FaaSController automatically, and it's has some faults | failed |
| initial | Checking the status in FaaSProvider by FaaSController automatically, and it's waiting on all resources to become ready | initial |
| initial | Deleting the function by RESTful API | destroyed |
| active | Checking the status of instance in FaaSProvider by FaaSController automatically, and it has some faults | failed |
| active | Checking the status of instance in FaaSProvider by FaaSController automatically, and for something reason, some resources are missing or pending | failed |
| active | Stoping the function by RESTful API | inactive |
| active | Checking the status of instance in FaaSProvider by FaaSController automatically, and it's healthy | active |
| inactive | Updating the function by RESTful API | initial |
| inactive | Deleting the function by RESTful API | destroyed |
| inactive | Staring the function by RESTful API and after successfully checking the status in FaaSProvider by FaaSController automatically | active |
| inactive | Staring the function by RESTful API but failing at checking status in FaaSProvider by FaaSController automatically | failed |
| inactive | Staring the function by RESTful API, Checking the status of instance in FaaSProvider by FaaSController automatically, and for something reason, some resources are missing or pending | failed |
| failed | Updating the function by RESTful API | initial |
| failed | Deleting the function by RESTful API | destroyed |
| failed | Checking the status in FaaSProvider by FaaSController automatically, and it's ready again | initial |
| failed | Checking the status of instance in FaaSProvider by FaaSController automatically, and for something reason, some resources are missing or pending | failed |
| failed | Checking the status in FaaSProvider by FaaSController automatically, and it has some faults | failed |
### RESTful APIs
The RESTful API path obey this design `http://host/{version}/{namespace}/{scope}(optional)/{resource}/{action}`,
| Operation | URL | Method | Body | Description |
| ----------------- | ------------------------------------------------------------------- | ------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Create a function | http://eg-host/apis/v2/faas/{controller_name} | POST | function spec | When there is not such a function in Easegress |
| Start a function | http://eg-host/apis/v2/faas/{controller_name}/{function_name}/start | PUT | empty | When function is in `inactive` state only, it will turn-on accepting traffic for this function |
| Stop a function | http://eg-host/apis/v2/faas/{controller_name}/demo1/stop | PUT | empty | When function is in `active` state only, it will turn-off accpeting traffic for this function |
| Update a function | http://eg-host/apis/v2/faas/{controller_name}/{function_name} | PUT | function spec | When function is in `initial`, `inactive` or `failed` state. It can used to update your function or fix your function's deployment problem. |
| Delete a function | http://eg-host/apis/v2/faas/{controller_name}/{function_name} | DELETE | empty | When function is in `initial`, `inactive` or `failed` states. |
| Get a function | http://eg-host/apis/v2/faas/{controller_name}/{function_name} | GET | empty | No timing limitation. |
| Get function list | http://eg-host/apis/v2/faas/{controller_name} | GET | empty | No timing limitation. |
## Demoing
1. Creating the FaasController in Easegress
```bash
$ cd ./easegress/example/primary-001 && ./start.sh
$ ./egctl.sh create -f ./faascontroller.yaml
$ ./egctl.sh get faas faascontroller
name: faascontroller
kind: FaaSController
provider: knative # FaaS provider kind, currently we only support Knative
syncInterval: 10s
httpServer:
http3: false
port: 10083
keepAlive: true
keepAliveTimeout: 60s
https: false
certBase64:
keyBase64:
maxConnections: 10240
knative:
networkLayerURL: http://10.109.159.129
hostSuffix: example.com
```
2. Creating the function
```bash
$ curl --data-binary @./function.yaml -X POST -H 'Content-Type: text/vnd.yaml' http://127.0.0.1:12381/apis/v2/faas/faascontroller
```
3. Waiting for the function provisioned successfully. Confirmed by using `Get` API for checking the `state` field
```bash
$ curl http://127.0.0.1:12381/apis/v2/faas/faascontroller/demo10
spec:
name: demo10
image: dev.local/colordeploy:17.0
port: 8089
autoScaleType: rps
autoScaleValue: "111"
minReplica: 1
maxReplica: 3
limitCPU: 180m
limitMemory: 100Mi
requestCPU: 80m
requestMemory: 20Mi
requestAdaptor:
host: ""
method: ""
header:
del: []
set:
X-Func: func-demo
X-Func1: func-demo-10
add: {}
body: ""
status:
name: demo10
state: active
event: ready
extData: {}
fsm: null
```
4. Visiting function by HTTP traffic gate with `X-FaaS-Func-Name: demo10` in HTTP header.
```bash
$ curl http://127.0.0.1:10083/tomcat/job/api -H "X-FaaS-Func-Name: demo10" -X POST -d ‘{"megaease":"Hello Easegress+Knative"}’
V3 Body is
‘{megaease:Hello Easegress+Knative}’%
$ curl http://127.0.0.1:10083/tomcat/job/api -H "X-FaaS-Func-Name: demo10" -X POST -d ‘{"FaaS":"Cool"}’
V3 Body is
‘{FaaS:Cool}’%
```
The function's API is serving in `/tomcat/job/api` path and its logic is displaying "V3 body is" with the contents u post.
## Reference
1. knative website http://knative.dev
2. Install knative serving via YAML https://knative.dev/docs/install/yaml-install/serving/install-serving-with-yaml/
3. resource quota https://kubernetes.io/docs/concepts/policy/resource-quotas/
4. AWS Lambda state https://aws.amazon.com/blogs/compute/tracking-the-state-of-lambda-functions/
---
## File: docs/07.Reference/7.05.Stream.md
# Stream
Most Easegress traffic is message-based, but Easegress v2 pipeline is
protocol independent, that's it supports stream-based traffic like TCP, and
there's stream traffic even in HTTP.
Another new feature in Easegress v2 is multiple requests/responses support,
this requires the payload of a request/response can be read more than once,
for message-based traffic, this is simple and easy to do, as Easegress can
read the full message payload into memory. But for stream-based traffic,
this is impossible, as the payload may require too much memory, and/or take
too much time to read it into memory.
To resolve the above issue, Easegress allow user or developer to configure
whether a request/response is a stream, for example:
* We can set `clientMaxBodySize` of an HTTP server to a negative value to
tell Easegress the request is a stream, and not a stream otherwise. Please
refer [HTTPServer](7.01.Controllers.md#httpserver) for more information.
* We can set `serverMaxBodySize` of a `Proxy` filter to a negative value to
tell Easegress the response is a stream, and not a stream otherwise. Please
refer [Proxy](7.02.Filters.md#proxy) for more information.
As we have mentioned above, the payload of a stream-based request/response
can only be read once, so some features are not possible for these
requests/responses, including:
* In the `template` of `RequestBuilder` or `ResponseBuilder`, you cannot
access the payload(in HTTP, the body) of an existing stream-based
request/response, while it is fine to access other information of the
request/response.
* Stream-based request/response cannot be cached by `Proxy`.
* The `HeaderToJSON` filter does not support stream-based requests/responses.
* You cannot access the payload of stream-based request/response in a
`WasmHost` filter.