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.
- Proxy known size request such as json or xml
- Proxy WebSocket
- Proxy SSE: Server-sent event
- Proxy chunked requests
2. Load Balancing
The ReverseProxyHandler supports following load balancing algorithm.
LB Algorithm | Hash based | Consistent | When assigned upstream inactive |
---|---|---|---|
(Weighted) Round Robin | No | - | Skip inactive upstream. |
(Weighted) Random | No | - | Skip inactive upstream. |
(Weighted) Direct Hash | Yes | No | Error. |
(Weighted) Ring Hash | Yes | Yes | Skip inactive upstream. |
(Weighted) Maglev | Yes | Yes | Recalculate 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 Methods | Hash Source |
---|---|
Header | A header value. |
Multiple Header | A joined string of header values. |
Header Pattern | A string extracted from header value by regular expression. |
Cookie | A cookie value. |
Query | A URL query value. |
Path Param | A URL path parameter. |
Client Addr | Client 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.
Header | Added | Prior values | Value | Example |
---|---|---|---|---|
X-Forwarded-For | Yes | Keep | Client IP address | 192.167.0.1, 127.0.0.1 |
X-Forwarded-Port | Yes | Discard | Client port number | 12345 |
X-Forwarded-Host | Yes | Discard | Requested host name | example.com |
X-Forwarded-Proto | Yes | Discard | Requested scheme | http or https |
Forwarded | No | - | 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
- Circuit Breaker pattern
- Load Balancing -Envoy
- HTTP Load Balancing - Nginx
- Load Balancing Reference - Kong Gateway
- HAPROXY documentation
- ApisixUpstream
- Load Balancing - API7.ai
- Maglev: A Fast and Reliable Software Network Load Balancer
- Maglev A Fast and Reliable Network Load Balancer
- Weighted round robin - Wikipedia
- Consistent hashing - Wikipedia
- HTTP headers and Application Load Balancers - AWS
- HTTP headers and Classic Load Balancers- AWS
フィードバック
このページは役に立ちましたか?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.