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/serverdefault middleware:- HTTP status memoisation
- Taggin request with UUID
- Adding logger to request context
- Logging request/response
recovering frompanic, and returning500 Internal Server Errorif no other HTTP status has been "sent" from a later handler.
-
Request tracing via Opentracing/Jaeger
-
Notification of
panics 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 config to request context
SERVICE_NAME can be set in the environment, this will be used by:
-
Loggger: as
svcfield. -
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_UsernameBASICAUTH_PasswordBASICAUTH_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-OriginHTTP header. -
CORS_AllowCredentials: boolean-ish value forAccess-Control-Allow-CredentialsHTTP header. -
CORS_RawAllowedHeaders: comma-separated list of allowed values forAccess-Control-Allow-HeadersHTTP 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_PROJECTIDAIRBRAKE_TOKENAIRBRAKE_ENVIRONMENTAIRBRAKE_FILTERS
If notifier can't be created due to blank project ID or token, a logging notifier will be used instead.
NEWRELIC_APIKeyNEWRELIC_AppName: If this is blank,$SERVICE_NAMEwill 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.