Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/adaptant-labs/go-region-router
A simple router and middleware for region endpoint redirection written in Go.
https://github.com/adaptant-labs/go-region-router
consul geocoding geoip golang-router iso3166-2 middleware region-detection region-router region-selector router routing
Last synced: 21 days ago
JSON representation
A simple router and middleware for region endpoint redirection written in Go.
- Host: GitHub
- URL: https://github.com/adaptant-labs/go-region-router
- Owner: adaptant-labs
- License: apache-2.0
- Created: 2019-07-05T19:26:50.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2020-01-21T11:31:05.000Z (almost 5 years ago)
- Last Synced: 2024-06-19T04:27:15.214Z (6 months ago)
- Topics: consul, geocoding, geoip, golang-router, iso3166-2, middleware, region-detection, region-router, region-selector, router, routing
- Language: Go
- Size: 238 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Authors: AUTHORS
Awesome Lists containing this project
README
# go-region-router
[![godoc](https://godoc.org/github.com/adaptant-labs/go-region-router/middleware?status.svg)](http://godoc.org/github.com/adaptant-labs/go-region-router/middleware)
[![Build Status](https://travis-ci.com/adaptant-labs/go-region-router.svg?branch=master)](https://travis-ci.com/adaptant-labs/go-region-router#)A simple router and middleware for region endpoint redirection written in Go.
The motivation for this work is that many DNS-based approaches to region routing rely on GeoIP lookups - operating under
the assumption that the requesting IP will provide a sufficiently robust data point in order to ascertain physical
location. This approach falls short in a number of areas, and further fails to take into account a far more robust
mechanism available to most Edge devices and mobile applications - GPS telemetry. Rather than placing emphasis on the
backend to work out the requesting party's location, we instead take the approach of having the requesting party encode
this information directly in the request headers.To this extent, `go-region-router` expects to find a [ISO 3166-1 alpha-2] 2-character country code
included on any in-bound request headers that wish to be redirected - accomplished through the addition of a
custom `X-Country-Code` header which specifies the country code denoting where the request originated:```http request
X-Country-Code: de
```The extraction of the country code from GPS coordinates on the requesting client side is not handled by this router, but
is possible by any number of reverse geocoding services, including, but not limited to, our [reverse-geocoding-service]
microservice.The router should also be trivially extendable for [HTML5 Geolocation] support, but as the initial focus of this router
has been for backend routing in response to a moving mobile frontend, this remains to be implemented.[ISO 3166-1 alpha-2]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
[reverse-geocoding-service]: https://github.com/adaptant-labs/reverse-geocoding-service
[HTML5 Geolocation]: https://github.com/w3c/geolocation-api## Installation
```sh
go get github.com/adaptant-labs/go-region-router
```## Quick Start
A Docker Compose file is provided in order to demonstrate the basic operation:
```sh
$ docker-compose up -d
```Once this is up and running, it can be tested as:
```sh
$ curl -L -H 'X-Country-Code: at' -X GET http://localhost:7000
hello from the AT endpoint
$ curl -L -H 'X-Country-Code: de' -X GET http://localhost:7000
hello from the DE endpoint
```If the `default` tag has been set for a server, as in the example, a country
mismatch will redirect to the default server:```sh
$ curl -L -H 'X-Country-Code: it' -X GET http://localhost:7000
hello from the DE endpoint
```if not provided in the service definition, a mismatch will result in a 503
response:```sh
$ curl -L -H 'X-Country-Code: it' -X GET http://localhost:7000
Service is unavailable in your region (it)
```## Usage
### Consul Configuration
Mappings between regions and servers can either be done statically, or dynamically through Consul. In order for the
discovery to work, each server must be tagged with a region identifier (denoted by `region-`), and optionally with
a connection protocol (when the protocol is anything other than HTTPS).An example service configuration is provided in `docs/consul.d`:
```json
{
"services": [
{
"id": "apigw0",
"name": "api",
"tags": [
"v1",
"region-de"
],
"meta": {
"protocol": "http"
},
"port": 80
},
{
"id": "apigw1",
"name": "api",
"tags": [
"v1",
"region-at"
],
"port": 443
}
]
}
```This can be registered with the Consul Agent directly via:
```
$ consul services register docs/consul.d/consul-service.json
Registered service: api
Registered service: api
```
### Starting the RouterOnce Consul is up and running and the service definitions are amended with the appropriate data, the router can be
started directly:```sh
$ go-region-router
2019/07/05 19:20:09 Setting up region routing for [DE] -> http://127.0.0.1:80
2019/07/05 19:20:09 Setting up region routing for [AT] -> https://127.0.0.1:443
2019/07/05 19:20:09 Listening on :7000 ...
```The following options can be set at run-time:
```sh
$ go-region-router --help
NAME:
go-region-router - A simple routing service for region endpointsUSAGE:
go-region-router [global options] command [command options] [arguments...]VERSION:
0.0.1AUTHOR:
Adaptant LabsCOMMANDS:
help, h Shows a list of commands or help for one commandGLOBAL OPTIONS:
--consul-agent value Consul agent to connect to
--consul-service value Name of Consul Service to look up (default: "api")
--consul-tag value Name of Consul tag to filter on (default: "v1")
--host value Host address to bind to
--port value Port to bind to (default: 7000)
--help, -h show help
--version, -v print the versionCOPYRIGHT:
(c) 2019 Adaptant Solutions AG```
### Middlewares
#### Region Routing Middleware
Region Routing middleware is provided in the `github.com/adaptant-labs/go-region-router/middleware` package. While the
Consul-backed router provides a more elaborate usage example, direct usage of the middleware for establishing static
routes is rather straightforward:```go
import (
"github.com/adaptant-labs/go-region-router/middleware"
"github.com/gorilla/mux"
"net/http"
)func main() {
m := mux.NewRouter()
r := region.NewRegionRouter()r.SetDefaultServer("https://default.api.xxx.com")
r.SetRegionServer("de", "https://de.api.xxx.com")
r.SetRegionServer("at", "https://at.api.xxx.com")// Apply the region routing middleware with default settings
http.ListenAndServer(":8080", r.RegionHandler()(m))
}
```Note that as above, the middleware expects to find the country code in the custom `X-Country-Code` header on in-bound
requests. Requests that do not have this header defined (or for where no matching route is available) will pass through
to the `default` tagged service. If no default handler is specified, a 503 response will be returned informing the
user of the unavailability of a server for their specific region. This response may be trapped for e.g. spinning up a
new instance in a new region and having the client periodically retry the connection.#### GeoIP Reverse Lookup Middleware
Routers may also enable a GeoIP-based lookup from the client IP address in order to identify the country code and
automatically insert the `X-Country-Code` header on in-bound requests. This, however, requires the availability of the
[reverse-geocoding-service] - the host:port of which must be set in the `REVERSE_GEOCODING_SERVICE` environment
variable. Furthermore, if the router is placed behind other loadbalancers and routers, it will also look at the
`X-Forwarded-For` header in order to determine the originating client IP.If used, this should wrap the RegionHandler above:
```
http.ListenAndServe(":8080", region.CountryCodeHandler(r.RegionHandler()(m)))
```## Online Documentation
Online API documentation is provided through godoc, this can be accessed
directly on the [package entry](https://godoc.org/github.com/adaptant-labs/go-region-router/middleware)
in the godoc package repository.## Deployment
Docker images are provided under [adaptant/go-region-router][docker-regionrouter], and should be deployed together with
a Consul agent and reverse geocoding service (optionally) - as provided in the sample `docker-compose.yml`. Information
on obtaining and deploying a Consul image can be found on the [Consul Docker page][consul-docker], while information
about the reverse geocoding service images can be found under [adaptant/reverse-geocoding-service][docker-geocoder].[docker-regionrouter]: https://hub.docker.com/r/adaptant/go-region-router
[docker-geocoder]: https://hub.docker.com/r/adaptant/reverse-geocoding-service
[consul-docker]: https://hub.docker.com/_/consul## Features and bugs
Please file feature requests and bugs at the [issue tracker][tracker].
[tracker]: https://github.com/adaptant-labs/go-region-router/issues
## Acknowledgements
This project has received funding from the European Union’s Horizon 2020 research and innovation programme under grant
agreement No 731678.## License
`go-region-router` is licensed under the terms of the Apache 2.0 license, the full version of which can
be found in the LICENSE file included in the distribution.