A simple configuration-driven reverse proxy written in Go.
It has zero dependencies outside of the Go standard library.
Define a slice of type Config
, with the minimum set of fields being: Path
and Upstream
.
Configuration is defined in the routing/configuration file.
Upstreams are defined in the upstreams file.
Below we explain the actual routing configuration committed into this repo...
Config{
Path: "/anything/standard",
Upstream: upstreams.HTTPBin,
}
/anything/standard
The request will be proxied straight through to the specified upstream without any modifications.
Config{
Path: "/anything/(?:foo|bar)$",
Upstream: upstreams.HTTPBin,
}
/anything/foo
/anything/bar
Both requests will be proxied straight through to the specified upstream without any modifications.
Config{
Path: `/(?P<cap>foo\w{3})`,
Upstream: upstreams.HTTPBin,
ModifyPath: "/anything/${cap}",
}
/fooabc
/fooxyz
Both requests will be proxied through to the specified upstream but the path will be modified to include the captured information: /anything/abc
and /anything/xyz
.
Config{
Path: "/(?P<start>anything)/(?P<cap>foobar)$",
Upstream: upstreams.HTTPBin,
Override: Override{
Header: "X-BF-Testing",
Match: "integralist",
ModifyPath: "/anything/newthing${cap}",
},
}
/anything/foobar
/anything/foobar
(+ HTTP Request Header X-BF-Testing: integralist
)The request will be proxied straight through to the specified upstream without any modifications.
If the relevant request header is specified, then the request will be proxied through to the specified upstream but the path will be modified to include the captured information: /anything/newthingfoobar
.
Config{
Path: "/(?P<cap>double-checks)$",
Upstream: upstreams.HTTPBin,
ModifyPath: "/anything/toplevel-modified-${cap}",
Override: Override{
Header: "X-BF-Testing",
Match: "integralist",
ModifyPath: "/anything/override-modified-${cap}",
},
}
/double-checks
/double-checks
(+ HTTP Request Header X-BF-Testing: integralist
)The request will be proxied through to the specified upstream but the path will be modified to include the captured information: /anything/toplevel-modified-double-checks
.
If the relevant request header is specified, then the request will be proxied through to the specified upstream but the path will be modified to include the captured information: /anything/override-modified-double-checks
.
Config{
Path: "/anything/(?P<cap>integralist)",
Upstream: upstreams.HTTPBin,
Override: Override{
Header: "X-BF-Testing",
Match: "integralist",
ModifyPath: "/about",
Upstream: upstreams.Integralist,
},
}
/anything/integralist
/anything/integralist
(+ HTTP Request Header X-BF-Testing: integralist
)The request will be proxied straight through to the specified upstream without any modifications.
If the relevant request header is specified, then the request will be proxied through to a different specified upstream and the path will also be modified.
Note: although we use a named capture group, we don't actually utilise it anywhere in the rest of the configuration, so it's effectively a no-op.
Config{
Path: "/about",
Upstream: upstreams.HTTPBin,
Override: Override{
Query: "s",
Match: "integralist",
Upstream: upstreams.Integralist,
},
}
/about
/about?s=integralist
The request will be proxied straight through to the specified upstream without any modifications.
If the relevant query parameter is specified, then the request will be proxied through to a different specified upstream.
Config{
Path: "/anything/querytest",
Upstream: upstreams.HTTPBin,
Override: Override{
Query: "s",
Match: `integralist(?P<cap>\d{1,3})$`,
MatchType: "regex",
ModifyPath: "/anything/newthing${cap}",
},
}
/anything/querytest
/anything/querytest?s=integralist123
/anything/querytest?s=integralist456
The first request will be proxied straight through to the specified upstream without any modifications.
If the relevant query parameter is specified, then the second and third requests will have their path modified to include the captured information: /anything/newthing123
and /anything/newthing456
.
We set the following response headers (not all will be set depending on the configuration):
X-Forwarded-Host
X-Origin-Host
X-Router-Upstream
X-Router-Upstream-OriginalHost
X-Router-Upstream-OriginalPath
X-Router-Upstream-OriginalPathModified
X-Router-Upstream-Override
X-Router-Upstream-OverrideHost
X-Router-Upstream-OverridePath
make run
Note: the application listens on port
9001
.
curl -v http://localhost:9001/some/path/you/configured
make test
We use vegeta
for load testing, so make sure you have that installed.
make stress
Example output:
Requests [total, rate] 1500, 50.03
Duration [total, attack, wait] 30.11237994s, 29.982166788s, 130.213152ms
Latencies [mean, 50, 95, 99, max] 154.522948ms, 96.76258ms, 358.770472ms, 1.076826656s, 2.954136535s
Bytes In [total, mean] 2039772, 1359.85
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:1500
Error Set: