This package provides a common harness for running HTTP apps, that configures middleware that we use nearly all the time, and provides a standard way to configure the different parts of the service.
Basic usage is to call service.ListenAndServe
, and pass a function
that registers your HTTP handlers on the *http.ServeMux
parameter
passed to your function.
There are some pre-configured common things available in the background context passed to the function:
Most of these are also made available via middleware, and should be accessed via the HTTP request context instead.
In request-processing order:
-
appkit/server
default middleware:- HTTP status memoisation
- Taggin request with UUID
- Adding logger to request context
- Logging request/response
recover
ing frompanic
, and returning500 Internal Server Error
if no other HTTP status has been "sent" from a later handler.
-
Request tracing via Opentracing/Jaeger
-
Notification of
panic
s to Airbrake -
Logging request metrics in InfluxDB
-
Add clickjacking countermeasure header
-
Add HSTS header
-
Sending request information to New Relic
-
CORS handling
-
HTTP Basic Authentication
-
Adding AWS session to request context
SERVICE_NAME
can be set in the environment, this will be used by:
-
Loggger: as
svc
field. -
Vault+AWS client credentials sourcing: as default role for Vault authn, and default AWS credentials path.
-
Request Tracing (Opentracing/Jaeger): As service name for traced requests.
-
New Relic Middleware: Application name reported to New Relic.
Environment variables:
BASICAUTH_Username
BASICAUTH_Password
BASICAUTH_UserAgentWhitelistRegexp
: Regexp matched against HTTP User-Agent header to bypass HTTP Basic Authentication.BASICAUTH_PathWhitelistRegexp
: Regexp matched against request path to bypass HTTP Basic Authentication.
CORS configuration of https://github.com/rs/cors
Environment variables:
-
CORS_RawAllowedOrigins
: comma-separated list of allowed values forAccess-Control-Allow-Origin
HTTP header. -
CORS_AllowCredentials
: boolean-ish value forAccess-Control-Allow-Credentials
HTTP header. -
CORS_RawAllowedHeaders
: comma-separated list of allowed values forAccess-Control-Allow-Headers
HTTP header.
Environment variables:
-
VAULT_AUTHN_ADDRESS
: base URL of Vault server. -
VAULT_AUTH_PATH
: path to Vault K8s auth backend. By default this is set toauth/kubernetes/login
. -
VAULT_AUTH_ROLE
: role used when authenticating with Vault. By default this is set to$SERVICE_NAME
. -
VAULT_AUTH_AUTORENEW
: flag to enable/disable automatic renewal of Vault lease in background goroutine. Defaults totrue
. -
VAULT_AWSPATH
: When using AWS credentials sourced from Vault, the Vault path of the credentials secret. By default this is set toaws/sts/<$SERVICE_NAME>
. -
VAULT_AUTHN_DISABLED
: flag to enable/disable Vault authentication completely. Use this when the service does not need any access to Vault.
PORT
: port number for HTTP server to bind to, defaults to 9800
. If
required, ADDR
can be set instead to allow binding to a specific
interface/IP address using [interface]:port
syntax.
INFLUXDB_URL
: Set to URL of InfluxDB server. If blank, a logging
(via appkit/log
monitor will be used instead of sending data to
InfluxDB.
If INFLUXDB_URL
's scheme is vault
(vs http
or https
), then the
client will source InfluxDB credentials from Vault. In this case,
INFLUXDB_URL
does not need any credentials. See the Vault+InfluxDB
client documentation in the credentials
README for information about configuration
constraints.
If INFLUXDB_URL
has no (or blank) service-name
query parameter,
the parameter will be set to SERVICE_NAME
.
AIRBRAKE_PROJECTID
AIRBRAKE_TOKEN
AIRBRAKE_ENVIRONMENT
AIRBRAKE_FILTERS
If notifier can't be created due to blank project ID or token, a logging notifier will be used instead.
NEWRELIC_APIKey
NEWRELIC_AppName
: If this is blank,$SERVICE_NAME
will be used.
Configured as for Jaeger Go client.
If JAEGER_SERVICE_NAME
is blank, $SERVICE_NAME
will be used.
Environment variables:
-
HSTS_MaxAge
: the time in seconds value formax-age
. -
HSTS_IncludeSubDomains
: boolean-ish value forincludeSubDomains
.
HSTS header will only be added when the value of HSTS_MaxAge
is greater than 0
X-Frame-Options Content-Security-Policy
Default:
the page cannot be displayed in a frame.
Environment variables:
-
DISPLAY_IN_FRAME_NoLimit
: Bool type. Iftrue
, no headers added, the page should be able to be displayed in a frame without limit(depend on browser's default behavior). -
DISPLAY_IN_FRAME_SameOrigin
: Bool type. Iftrue
, the page can only be displayed in a frame on the same origin as the page itself. -
DISPLAY_IN_FRAME_AllowURIs
: A string contains URIs separated by spaces. If it has value, the page can only be displayed in a frame on specified URIs.
Design is implemented via a configuration callback because the lifecycle of the app is controlled by the serivce harness.
-
Create and configure service background context (including starting background goroutines used by some middleware).
-
Set up common middleware using background context.
-
Hand over to app-side code (passed function) to do app-specific configuration.
-
App-side code hands back to the service harness (by returning from the passed function).
-
Start HTTP server in background goroutine.
-
Wait for signal to terminate.
-
Ask HTTP server to shut down, and wait.
-
Once HTTP server has shut down (=> all requests have been handled or rejected, no more HTTP requests will be accepted), shut down background context goroutines.
-
Exit
The reason for this structure is that step 7 needs to finish before step 8 is started, and managing this lifecycle is somewhat complex, and tedious. So we don't want to implement it in every service.