Gateway Documentation
This document provides an overview of the gateway architecture and functionality used in the PORTERS portal.
Overview
The gateway primarily relies on the net/http (opens in a new tab) library and its ReverseProxy
functionality.
Requests are handled by gorilla/mux (opens in a new tab), mapping paths to the reverse proxy.
Reverse Proxy and Middleware
Inside the reverse proxy, middleware runs and hosts logic for allowing or denying requests in addition to modifying aspects of the request (headers, error codes, etc). These middleware plugins are inserted into the request lifecycle, implementing rules for proxying or rejecting requests. Contributors can start by exploring plugins located in the plugins package.
Plugins Package
The main.go
file configures the server and allows adding plugins to the registry.
Contributors can add new logic by providing new plugins.
These plugins are essential for customizing gateway behavior.
The plugin interface is defined as:
type Plugin interface {
Name() string
Key() string
Load()
}
Name()
is just the user-friendly name by which to describe the plugin.
Key()
is used to avoid collisions between Plugins, any cache data specific to a plugin should be prefixed with Key()
.
Load()
is called on application start to perform any steps needed to initialize the plugin
There are two additional sub-interfaces which are called for each request.
PreHandler
introduces a function HandleRequest(*http.Request) error
which can be implemented to be called before requests are forwarded to the POKT network.
This should be used to reject requests and make any precondition checks.
PostHandler
introduces a function HandleResponse(*http.Response) error
which may be implemented to be called after the Response from the gateway server.
It should be used to modify the response or clean up any errant responses.
In either case, an error
may be returned which will reflect in the HTTP response.
Lifecycle Management
This gateway introduces the concept of a lifecycle, where each stage must be fulfilled by a plugin for the request to be considered valid. Plugins are not required to fulfill any lifecycle stages, but may fulfill several. This concept guides the development and integration of plugins into the gateway architecture.
Currently there are four stages:
Auth
AccountLookup
BalanceCheck
RateLimit
Proxy Package
The primary package in this program is the proxy
package.
This defines the above Plugin
type and calls it as part of the request lifecycle.
The proxy can be started as it is in the gateway.go
file by calling Start()
and requests will be proxyed to the gateway server defined by the environment variable PROXY_TO
according to the established usage pattern.
Database Package
The db
package contains logic for interactions between Redis and PostgreSQL, handling data storage and retrieval.
Redis acts as a pass-through cache with a few additional features.
The goal is to keep all database specific interaction in this package (go-redis
and pq
).
Utils Package
The utils
package consists of small utility packages, providing helper functions and tools for various tasks.
gatewaykit.go
definesTarget
which builds the URL to proxy torate.go
defines the encoding of rate limits usingISO 8601
inspired formatsha256.go
is a wrapper on thecrypto/sha256
library for easily producing hashes
Commons Package
The commons
package includes Prometheus metrics and configuration files essential for gateway operations.
Config
Environment variables are used to configure the gateway. In the future configuration may be moved to the database or a config file. Current environment variables are:
- SHUTDOWN_DELAY: How long to wait for processes to finish on graceful shutdown (default: 5sec)
- JOB_BUFFER_SIZE: How many worker tasks to buffer before blocking (default: 50)
- NUM_WORKERS: How many goroutines to run to process the job buffer (default: 10)
- PROXY_TO: Internal URL to gateway server
- HOST: Domain this is hosted on, used to extract chain name from subdomain
- PORT: Network port for server to listen on (default: 9000)
- DATABASE_URL: Postgres connection URL
- REDIS_URL: Redis connection URL, alternative to decomposed vars
- REDIS_ADDR: Host of redis server
- REDIS_USER: Redis username
- REDIS_PASSWORD: Redis password
- INSTRUMENT_ENABLED: Debugging feature flag to add instrumentation
- LOG_LEVEL: How verbose should logs be (default: INFO)
Worker Pool
To avoid random goroutines being managed throughout the code, there is a task queue to coordinate asynchronous jobs.
Implement the Runnable
interface and add to the queue for a job runner to pick it up.
Set the environment variables described above to increase or decrease the queue size and number of workers based on needs.
Healthcheck
There is a healthcheck endpoint exposed at /health
which reports on the status of the gateway proxy.
Any external service can be monitored by adding its health to this service.
In addition, any internal metrics that should cause infrastructure to respond in some way can also be added.
Prometheus
Prometheus is used for tracking metrics. It is exposed with a /metrics
endpoint.
In addition to the common metrics, we add:
- EndpointUsage: A counter for usage on each endpoint, used for reporting
- JobGauge: Shows the current size of the job queue, used for monitoring
- LatencyHistogram: Instrumentation to show how much latency is added by the proxy process
- RateLimitGauge: Notifications that a rate limit has been hit, resets when resolved