It is good practice to make a FLAT app configurable so that it can run in multiple environments. For example, the upstream APIs have different locations in a local development setup and the production system.
FLAT runs as a Docker Container and can make use of the environment variables defined, for example, in the Dockerfile, docker-compose.yaml or with docker run -e.
As usual, environment variables can be defined in the docker-compose.yaml like this:
services:
flat:
image: code-registry.avenga.cloud/product/flat/flat/flatrunner
volumes:
- .:/app
ports:
- 8080:8080
environment:
- MY_VAR=my value
- FLAT_DEBUG_ALLOW_HEADER=true
Here, we have defined MY_VAR in the environment section and enabled debugging via HTTP header.
(We assume, that you have a swagger.yaml and some API path that you can call. If you’re not so far, yet, checkout the tutorial).
Start the container with
$ docker compose up
and run the following curl command.
The environment variables can be inspected with the env debug topic:
The inline sink interweaves the debug output with your API response. It will disturb your response, but it is sometimes handy for debugging:
$ curl -s -H debug:env::inline localhost:8080
debug [env] Env vars: {
…
"FLAT_DEBUG_ALLOW_HEADER": "true",
…
"MY_VAR": "my value",
…
}
There’s our MY_VAR!
Another way of defining environment vars would be the -e flag of a simple docker run:
$ docker run --rm -it -e MY_VAR="my value" -v "$(pwd):/app" code-registry.avenga.cloud/product/flat/flat-src/flatrunner
Great! We now know how to define environment variables. Let’s use them!
All environment variables are accessible from flows by the system variable $env. It is an object with the defined environment variables as properties:
{
"MY_VAR": "my value",
…
}
We could create a simple template to send our environment variable back to the client:
<flow>
<template>
{
"my var": {{ $env/MY_VAR }}
}
</template>
</flow>
A typical use-case for an environment variable is the base URL of an upstream API.
Let’s define the origin of our auth service:
AUTH_SERVICE=http://localhost:3000
To request the auth service, we have to build a URL:
<flow>
<request>
{
"url": {{ concat($env/AUTH_SERVICE, "/v1/logout" )}},
"headers": {
{{: $request/headers/authorization }}
}
}
</request>
</flow>
If the app is deployed into production, the AUTH_SERVICE variable will be set to another value, probably one with https and running on a different port.
When working with JWT a signing key (or two, in case of RS* algorithms) need to be configured in FLAT. It is good idea to pass these as environment variables.
See Working with JWT for a larger example.
Often, access between services is restricted by an HTTP Authentication.
You could read Basic Authentication credentials from an environment variable in your request:
<flow>
<request>
{
"url": "…",
"options": {
"basic-auth-credentials": {{ $env/AUTH_SERVICE_CREDS }}
}
}
</request>
</flow>
Or if you need to include a token in your requests:
<flow>
<request>
{
"url": "…",
"headers": {
"authentication": {{ concat("Bearer ", $env/AUTH_SERVICE_TOKEN) }}
}
}
</request>
</flow>
set-env (reference)