Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/integralist/go-reverse-proxy
Reverse proxy with simple routing configuration and override behaviour
https://github.com/integralist/go-reverse-proxy
go golang gorilla-mux makefile proxy-server reverse-proxy routing vegeta
Last synced: 3 months ago
JSON representation
Reverse proxy with simple routing configuration and override behaviour
- Host: GitHub
- URL: https://github.com/integralist/go-reverse-proxy
- Owner: Integralist
- License: mit
- Created: 2018-07-26T18:37:49.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2018-11-30T16:46:17.000Z (about 6 years ago)
- Last Synced: 2024-10-18T06:15:17.340Z (4 months ago)
- Topics: go, golang, gorilla-mux, makefile, proxy-server, reverse-proxy, routing, vegeta
- Language: Go
- Homepage: https://www.integralist.co.uk/
- Size: 13.7 KB
- Stars: 27
- Watchers: 4
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Go Reverse Proxy
A simple configuration-driven reverse proxy written in Go.
It has zero dependencies outside of the Go standard library.
## Configuration
Define a slice of type `Config`, with the minimum set of fields being: `Path` and `Upstream`.
Configuration is defined in the [routing/configuration](./routing/configuration.go) file.
Upstreams are defined in the [upstreams](./upstreams/upstreams.go) file.
## Example Config
Below we explain the actual [routing configuration](./routing/configuration.go) committed into this repo...
- [Proxy Request](#proxy-request)
- [Proxy Request using Regular Expression](#proxy-request-using-regular-expression)
- [Proxy Request with Modified Path](#proxy-request-with-modified-path)
- [Override with Modified Path](#override-with-modified-path)
- [Modified Path + Override with Modified Path](#modified-path--override-with-modified-path)
- [Override to Different Upstream](#override-to-different-upstream)
- [Query String Override](#query-string-override)
- [Query String Override with Regular Expression](#query-string-override-with-regular-expression)### Proxy Request
```go
Config{
Path: "/anything/standard",
Upstream: upstreams.HTTPBin,
}
```### Requests
- `/anything/standard`
### Result
The request will be proxied straight through to the specified upstream without any modifications.
---
### Proxy Request using Regular Expression
```go
Config{
Path: "/anything/(?:foo|bar)$",
Upstream: upstreams.HTTPBin,
}
```### Requests
- `/anything/foo`
- `/anything/bar`### Result
Both requests will be proxied straight through to the specified upstream without any modifications.
---
### Proxy Request with Modified Path
```go
Config{
Path: `/(?Pfoo\w{3})`,
Upstream: upstreams.HTTPBin,
ModifyPath: "/anything/${cap}",
}
```### Requests
- `/fooabc`
- `/fooxyz`### Result
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`.
---
### Override with Modified Path
```go
Config{
Path: "/(?Panything)/(?Pfoobar)$",
Upstream: upstreams.HTTPBin,
Override: Override{
Header: "X-BF-Testing",
Match: "integralist",
ModifyPath: "/anything/newthing${cap}",
},
}
```### Requests
- `/anything/foobar`
- `/anything/foobar` (+ HTTP Request Header `X-BF-Testing: integralist`)### Result
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`.
---
### Modified Path + Override with Modified Path
```go
Config{
Path: "/(?Pdouble-checks)$",
Upstream: upstreams.HTTPBin,
ModifyPath: "/anything/toplevel-modified-${cap}",
Override: Override{
Header: "X-BF-Testing",
Match: "integralist",
ModifyPath: "/anything/override-modified-${cap}",
},
}
```### Requests
- `/double-checks`
- `/double-checks` (+ HTTP Request Header `X-BF-Testing: integralist`)### Result
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`.
---
### Override to Different Upstream
```go
Config{
Path: "/anything/(?Pintegralist)",
Upstream: upstreams.HTTPBin,
Override: Override{
Header: "X-BF-Testing",
Match: "integralist",
ModifyPath: "/about",
Upstream: upstreams.Integralist,
},
}
```### Requests
- `/anything/integralist`
- `/anything/integralist` (+ HTTP Request Header `X-BF-Testing: integralist`)### Result
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.
---
### Query String Override
```go
Config{
Path: "/about",
Upstream: upstreams.HTTPBin,
Override: Override{
Query: "s",
Match: "integralist",
Upstream: upstreams.Integralist,
},
}
```### Requests
- `/about`
- `/about?s=integralist`### Result
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.
---
### Query String Override with Regular Expression
```go
Config{
Path: "/anything/querytest",
Upstream: upstreams.HTTPBin,
Override: Override{
Query: "s",
Match: `integralist(?P\d{1,3})$`,
MatchType: "regex",
ModifyPath: "/anything/newthing${cap}",
},
}
```### Requests
- `/anything/querytest`
- `/anything/querytest?s=integralist123`
- `/anything/querytest?s=integralist456`### Result
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`.
## Response Headers
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
```## Usage
```
make run
```> Note: the application listens on port `9001`.
```
curl -v http://localhost:9001/some/path/you/configured
```## Tests
```
make test
```## Load Test
We use [`vegeta`](https://github.com/tsenart/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:
```## TODO
- Look at implementing thread pool processing on a host or server basis.
- Verify if DNS caching (or request memoization) would affect latency results?
- Review 301 redirect behaviour to be sure we don't need to handle that differently.
- Flesh out some unit tests (not just integration testing)