ReverseProxyHandler (HTTP Proxy)

Overview

ReverseProxyHandler is a HTTP proxy handler. It is the very basic resources for AILERON Gateway to work as a gateway.

It works as:

  • HTTP Handler

Config yaml format becomes like below. And the resource specific spec is defined in in the proto format shown in the Resource Definition.

apiVersion: core/v1
kind: ReverseProxyHandler
metadata:
  name: "default"
  namespace: "default"
spec: {}

Features

1. Proxy request

ReverseProxyHandler proxies following types of requests.

2. Load Balancing

The ReverseProxyHandler supports following load balancing algorithm.

LB AlgorithmHash basedConsistentWhen assigned upstream inactive
(Weighted) Round RobinNo-Skip inactive upstream.
(Weighted) RandomNo-Skip inactive upstream.
(Weighted) Direct HashYesNoError.
(Weighted) Ring HashYesYesSkip inactive upstream.
(Weighted) MaglevYesYesRecalculate hash table.

Following hash sources are available for hash based load balancing.

Hash Source Limitations:

  • Only 1 value is randomly used if there were multiple header values bounded to a single key.
  • Only 1 value is randomly used if there were multiple query values bounded to a single key.
  • ReverseProxyHandler must be registered to a server with path parameter pattern. See http#ServeMux.
Hashing MethodsHash Source
HeaderA header value.
Multiple HeaderA joined string of header values.
Header PatternA string extracted from header value by regular expression.
CookieA cookie value.
QueryA URL query value.
Path ParamA URL path parameter.
Client AddrClient ip and port.

3. Rremove Hop-by-hop headers

Hop-by-Hop headers are removed when proxying requests. Headers to be removed are described in RFC 7230 and RFC 2616. One of the reference implementations would be httputil/reverseproxy.go.

AILERON Gateway removes following headers from requests to be proxied.

  • Connection
  • Keep-Alive
  • Proxy-Connection
  • Proxy-Authenticate
  • Proxy-Authorization
  • Te
  • Trailer
  • Transfer-Encoding
  • Upgrade
  • Headers listed in Connection

4. Adding forwarded headers

Forwarded related headers are added to the proxy headers. X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Port and X-Forwarded-Proto are added. But Forwarded header is not added itself. This is because the X-Forwarded-* header is more generally used than Forwarded itself.

Following table shows the forwarded headers and the example values.

HeaderAddedPrior valuesValueExample
X-Forwarded-ForYesKeepClient IP address192.167.0.1, 127.0.0.1
X-Forwarded-PortYesDiscardClient port number12345
X-Forwarded-HostYesDiscardRequested host nameexample.com
X-Forwarded-ProtoYesDiscardRequested schemehttp or https
ForwardedNo-All of above-

Resource Definition

ReverseProxyHandler is defined in the proto/core/v1/httpproxy.proto

  1syntax = "proto3";
  2package core.v1;
  3
  4import "buf/validate/validate.proto";
  5import "core/v1/http.proto";
  6import "core/v1/resilience.proto";
  7import "kernel/matcher.proto";
  8import "kernel/network.proto";
  9import "kernel/resource.proto";
 10
 11option go_package = "github.com/aileron-gateway/aileron-gateway/apis/core/v1";
 12
 13// ReverseProxyHandler resource definition.
 14// apiVersion="core/v1", kind="ReverseProxyHandler".
 15message ReverseProxyHandler {
 16    string                  APIVersion = 1 [json_name = "apiVersion"];
 17    string                  Kind       = 2 [json_name = "kind"];
 18    kernel.Metadata         Metadata   = 3 [json_name = "metadata"];
 19    ReverseProxyHandlerSpec Spec       = 4 [json_name = "spec"];
 20}
 21
 22// ReverseProxyHandlerSpec is the specifications for the ReverseProxyHandler object.
 23message ReverseProxyHandlerSpec {
 24    // [OPTIONAL]
 25    // ErrorHandler is the reference to a ErrorHandler object.
 26    // Referred object must implement ErrorHandler interface.
 27    // Default error handler is used when not set.
 28    kernel.Reference ErrorHandler = 1 [json_name = "errorHandler"];
 29
 30    // [OPTIONAL]
 31    // Patterns is path patterns that this handler is registered to a server.
 32    // Default is not set.
 33    repeated string Patterns = 2 [json_name = "patterns", (buf.validate.field).repeated.unique = true];
 34
 35    // [OPTIONA]
 36    // Methods is the list of HTTP method this handler can handle.
 37    // Note that it depends on the multiplexer, or HTTP router
 38    // if this field can be used.
 39    // If not set, all methods are accepted.
 40    // Default is not set.
 41    repeated HTTPMethod Methods = 3 [json_name = "methods", (buf.validate.field).repeated.unique = true];
 42
 43    // [OPTIONAL]
 44    // Tripperwares is the list of references to Tripperwares  object.
 45    // Referred object must implement Tripperware interface.
 46    // Default is not set.
 47    repeated kernel.Reference Tripperwares = 4 [json_name = "tripperwares"];
 48
 49    // [OPTIONAL]
 50    // RoundTripper is the references to a roundTripper  object.
 51    // Referred object must implement RoundTripper interface.
 52    // Default roundTripper is used when not set.
 53    kernel.Reference RoundTripper = 5 [json_name = "roundTripper"];
 54
 55    // [OPTIONAL]
 56    // LoadBalancers is the list of load balancers.
 57    // Proxy upstreams are specified in this field.
 58    // Requests will be proxied to the first matched upstream
 59    // by matching with the load balancers defined order.
 60    // Default is not set.
 61    repeated LoadBalancerSpec LoadBalancers = 6 [json_name = "loadBalancers"];
 62}
 63
 64// LoadBalancerSpec is the specification of LoadBalancer objects.
 65message LoadBalancerSpec {
 66    // [OPTIONAL]
 67    // LBAlgorithm specifies the load balancing algorithm.
 68    // Default RoundRobin will be used if not set.
 69    // Default is not set.
 70    LBAlgorithm LBAlgorithm = 1 [json_name = "lbAlgorithm"];
 71
 72    // [REQUIRED]
 73    // Upstreams is the list of upstream server of proxy target.
 74    // An internal server error will be returned when no upstreams are defined.
 75    // Default is not set.
 76    repeated UpstreamSpec Upstreams = 2 [json_name = "upstreams"];
 77
 78    // [OPTIONAL]
 79    // PathMatcher is the path matching algorithm to be used.
 80    // If need multiple path matchers, use PathMatchers field instead.
 81    // If both PathMatcher and PathMatchers are set, the PathMatcher
 82    // is appended as the first matcher of PathMatchers.
 83    // If both PathMatcher and PathMatchers are not set,
 84    // HTTP error responses are returned to all requests.
 85    // Default is not set.
 86    PathMatcherSpec PathMatcher = 3 [json_name = "pathMatcher"];
 87
 88    // [OPTIONAL]
 89    // PathMatchers is the list of path matching algorithm to be used.
 90    // A prefix matcher with "/" prefix will be used which matches all
 91    // requests if not set.
 92    // If need only 1 path matcher, PathMatcher field can be used instead.
 93    // If both PathMatcher and PathMatchers are set, the PathMatcher
 94    // is appended as the first matcher of PathMatchers.
 95    // HTTP error responses are returned to all requests.
 96    // Matchers are OR condition and the first matched one is used.
 97    // Default is not set.
 98    repeated PathMatcherSpec PathMatchers = 4 [json_name = "pathMatchers"];
 99
100    // [OPTIONAL]
101    // Methods is the list of HTTP method this loadbalancer can accept.
102    // If not set, all methods are accepted.
103    // Default is not set.
104    repeated HTTPMethod Methods = 5 [json_name = "methods", (buf.validate.field).repeated.unique = true];
105
106    // [OPTIONAL]
107    // Hosts is the list of hosts to allow.
108    // If not set, all hosts are allowed.
109    // List all host names because the value are matched by exact matching algorithm.
110    // Wildcard characters such as "*" are not available.
111    // Default is not set.
112    repeated string Hosts = 6 [json_name = "hosts", (buf.validate.field).repeated.unique = true];
113
114    // [OPTIONAL]
115    // PathParamMatcher is the path parameter value matcher to check
116    // if this loadbalancer can accept the target request.
117    // Path parameter is only available when the handler was registered
118    // to a server with patterns containing path parameters
119    // described at https://pkg.go.dev/net/http#hdr-Patterns.
120    // Listed matchers are evaluated by AND condition.
121    // If OR matching condition is necessary, set the condition within a single matcher.
122    // Default is not set.
123    repeated ParamMatcherSpec PathParamMatchers = 7 [json_name = "pathParamMatchers"];
124
125    // [OPTIONAL]
126    // HeaderMatcher is the header value matcher to check
127    // if this loadbalancer can accept the target request.
128    // If multiple header values were found, they are joined
129    // with a comma "," and agggregated to a singled string.
130    // For example ["foo", "bar"] will be "foo,bar" and the matcher
131    // is applied to the joined value "foo,bar".
132    // Listed matchers are evaluated by AND condition.
133    // If OR matching condition is necessary, set the condition within a single matcher.
134    // Default is not set.
135    repeated ParamMatcherSpec HeaderMatchers = 8 [json_name = "headerMatchers"];
136
137    // [OPTIONAL]
138    // QueryMatcher is the URL query value matcher to check
139    // this loadbalancer can accept the target request.
140    // If multiple query values were found, they are joined
141    // with a comma "," and agggregated to a singled string.
142    // For example ["foo", "bar"] will be "foo,bar" and the matcher
143    // is applied to the joined value "foo,bar".
144    // Listed matchers are evaluated by AND condition.
145    // If OR matching condition is necessary, set the condition within a single matcher.
146    // Default is not set.
147    repeated ParamMatcherSpec QueryMatchers = 9 [json_name = "queryMatchers"];
148
149    // [OPTIONAL]
150    // HashTableSize is the size of hash tables for hash-based load balancers.
151    // This field is used by Maglev and RingHash load balancers.
152    // If not set, default value is used.
153    // Default value depends on the load balancer.
154    int32 HashTableSize = 10 [json_name = "hashTableSize"];
155
156    // [OPTIONAL]
157    // Hashers is the hashing methods for hash-based load balancers.
158    // This field is optional but should be set at least 1
159    // for hash-based load balancers.
160    // Default is not set.
161    repeated HTTPHasherSpec Hashers = 11 [json_name = "hashers"];
162}
163
164// PathMatcherSpec is the specification of PathMatcher object
165// used for path matching of incoming HTTP requests.
166message PathMatcherSpec {
167    // [OPTIONAL]
168    // Match is the url path pattern to be matched to this matcher.
169    // The grammar of the pattern depends on the MatchType.
170    // This pattern should not contain prefix set by TrimPrefix or AppendPrefix.
171    // Currently, only 1 prefix string can be set here.
172    // Use Regex or RegexPOSIX match type and ser Rewrite field
173    // if you need trim multiple prefix.
174    // It can also trim or rewrite specific patterns.
175    // Default is not set.
176    string Match = 1 [json_name = "match"];
177
178    // [OPTIONAL]
179    // MatchType is the type of pattern matching algorithm.
180    // The path pattern specified at the Match field should follow the
181    // grammar of this match type.
182    // Default is [Prefix].
183    kernel.MatchType MatchType = 2 [json_name = "matchType"];
184
185    // [OPTIONAL]
186    // Rewrite is the path rewrite expression.
187    // This field is used when the MatchType is Regex or RegexPOSIX.
188    // Checkout https://pkg.go.dev/regexp#Regexp.ExpandString
189    // Default is not set.
190    string Rewrite = 3 [json_name = "rewrite"];
191
192    // [OPTIONAL]
193    // TrimPrefix is the prefix string to be removed from the URL path.
194    // For example, "/trim/me", "/prefix", "/api".
195    // This prefix is removed before checking the match.
196    // So the Match filed should not contain this value.
197    // Default is not set.
198    string TrimPrefix = 4 [json_name = "trimPrefix"];
199
200    // [OPTIONAL]
201    // AppendPrefix is the prefix string to be added to the URL path.
202    // For example, "/append/me", "/prefix", "/api".
203    // This prefix is added after checking the match.
204    // So the Match filed should not contain this value.
205    // Default is not set.
206    string AppendPrefix = 5 [json_name = "appendPrefix"];
207}
208
209// ParamMatcherSpec is the specification of ParamMatcherParamMatcherSpec object
210// used for header or query value matching.
211message ParamMatcherSpec {
212    // [REQUIRED]
213    // Key is the key name to check.
214    // If the specified key were not found in header, query or path params,
215    // this matcher fails without calling the match function specified at MatchType.
216    // Default is not set.
217    string Key = 1 [json_name = "key", (buf.validate.field).string.min_len = 1];
218
219    // [OPTIONAL]
220    // Patterns is the value pattern list.
221    // The grammar of the pattern depends on the MatchType.
222    // Patterns are evaluated by OR condition.
223    // It will be considered that at least 1 pattern matched to a target,
224    // this macher object returns true.
225    // Default is not set, which means an empty string.
226    repeated string Patterns = 2 [json_name = "patterns"];
227
228    // [OPTIONAL]
229    // MatchType is the type of pattern matching algorithm.
230    // The pattern specified at the Pattern field should follow the
231    // grammar of this match type.
232    // Default is [Exact].
233    kernel.MatchType MatchType = 3 [json_name = "matchType"];
234}
235
236// UpstreamSpec is the specification of Upstream object.
237message UpstreamSpec {
238    // [REQUIRED]
239    // URL is the base url for for proxy.
240    // This field can contain URL path.
241    // For example "http://localhost:8080/api/"
242    // Default is not set.
243    string URL = 1 [json_name = "url", (buf.validate.field).string.pattern = "(http://|https://).*"];
244
245    // [OPTIONAL]
246    // Weight is the weight, or priority of this target.
247    // Set -1 to disable this upstream.
248    // 0 is the same as default value 1.
249    // Default is [1].
250    int32 Weight = 2 [json_name = "weight", (buf.validate.field).int32 = {gte : -1, lte : 1000}];
251
252    // [OPTIONAL]
253    // EnablePassive enables passive health check.
254    // Default is [false].
255    // NOTE: This fiels is not used for now.
256    bool EnablePassive = 3 [json_name = "enablePassive"];
257
258    // [OPTIONAL]
259    // EnableActive enables active health check.
260    // Default is [false].
261    // NOTE: This fiels is not used for now.
262    bool EnableActive = 4 [json_name = "enableActive"];
263
264    // [OPTIONAL]
265    // InitialDelay is the wait time in seconds until to start active health checking after starts.
266    // Note that this field is used only when the active health checking is configured.
267    // Default is [0].
268    // NOTE: This fiels is not used for now.
269    int32 InitialDelay = 7 [json_name = "initialDelay"];
270
271    // [OPTIONAL]
272    // HealthCheckInterval is the interval of active health check in seconds.
273    // Note that this field is used only when the active health checking is configured.
274    // Default is [1].
275    // NOTE: This fiels is not used for now.
276    int32 HealthCheckInterval = 8 [json_name = "healthCheckInterval"];
277
278    // [OPTIONAL]
279    // Address is the active health check target URL or address.
280    // For example, specify a url "http://example.com/healthy" for HTTP network type
281    // and "tcp://127.0.0.1:8080" for TCP.
282    // Default is not set.
283    // NOTE: This fiels is not used for now.
284    string HealthCheckAddr = 9 [json_name = "healthCheckAddr"];
285}

References


最終更新 June 7, 2025: add japanese (f2a41f1)