Outdated documentation
You are reading documentation for v3, which is an outdated version. Click here to go to the latest documentation.
# Configuration
# Introduction
The Goyave framework lets you configure its core and your application.
To configure your application, use the config.json
file at your project's root. If you are using the template project, copy config.example.json
to config.json
. config.json
should be ignored in your .gitignore
file as it can differ from one developer to another. To avoid accidental commit or change to the default project's config, it is a good practice to ignore this file and define the project's default config in config.example.json
.
If this config file misses some config entries, the default values will be used. Refer to the configuration reference to know more.
All entries are validated. That means that the application will not start if you provided an invalid value in your config (for example if the specified port is not a number). That also means that a goroutine trying to change a config entry with the incorrect type will panic.
Entries can be registered with a default value, their type and authorized values from any package.
Configuration can be used concurrently safely.
The following JSON file is an example of default configuration:
{
"app": {
"name": "goyave_template",
"environment": "localhost",
"debug": true,
"defaultLanguage": "en-US"
},
"server": {
"host": "127.0.0.1",
"maintenance": false,
"protocol": "http",
"domain": "",
"port": 8080,
"httpsPort": 8081,
"timeout": 10,
"maxUploadSize": 10,
"tls": {
"cert": "/path/to/cert",
"key": "/path/to/key"
}
},
"database": {
"connection": "mysql",
"host": "127.0.0.1",
"port": 3306,
"name": "goyave",
"username": "root",
"password": "root",
"options": "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
"maxOpenConnections": 20,
"maxIdleConnections": 20,
"maxLifetime": 300,
"autoMigrate": false,
"config": {
"skipDefaultTransaction": false,
"dryRun": false,
"prepareStmt": true,
"disableNestedTransaction": false,
"allowGlobalUpdate": false,
"disableAutomaticPing": false,
"disableForeignKeyConstraintWhenMigrating": false
}
}
}
# Terminology
Entry: a configuration entry is a value accessible using a key.
Registering an entry: informs the framework that an entry with the given key is expected. Registering an entry allows to set a default value to be used if this entry is not provided in an app's configuration file, to enforce a certain type for this entry (for example if it needs to be an integer), and to set a list of allowed values.
Category: a category is represented by a JSON object in your configuration file, delimited by braces. Sub-categories are categories that are not at root level, for example: server.tls
is a sub-category of the server
category.
# Environment configuration
Most projects need different configuration values based on the environment. For example, you won't connect to the same database if you're in local development, in a testing environment inside continuous integration pipelines, or in production. Goyave supports multiple configurations and will pick the appropriate one depending on the environment variable GOYAVE_ENV
.
Since v2.0.0
, you can use custom environments.
GOYAVE_ENV | Config file |
---|---|
test | config.test.json |
production | config.production.json |
custom_env | config.custom_env.json |
local / localhost / not set | config.json |
# Using the configuration
Before being able to use the config, import the config package:
import "goyave.dev/goyave/v3/config"
The configuration is loaded automatically when the server starts, but you can reload it manually if needed.
When the configuration is loaded, all default values are copied to the newly created map holding the configuration. Then, the configuration file is read, parsed and is applied over. This means that all entries from the file override the default ones. However, if an entry has a default value and the same entry is not present in the configuration file, then it is kept as it is. On the other hand, if an entry is present in the configuration file and not in the default values (meaning that this entry is not expected), a new entry will be registered. This new entry will be subsequently validated using the type of its initial value and have an empty slice as authorized values (meaning it can have any value of its type).
The following cases will raise errors when the configuration is being overridden:
- When the configuration file overrides an entry with a category
- When the configuration file overrides a category with an entry
# config.Load
Parameters | Return |
---|---|
error |
Example:
config.Load()
# config.LoadFrom
You may need to load a configuration file from a custom path instead of using the standard one. LoadFrom
lets you load a config file from the given path.
Parameters | Return |
---|---|
path string | error |
Example: load the config from the path given through a flag
import (
"flag"
"os"
"goyave.dev/goyave/v3"
"goyave.dev/goyave/v3/config"
//...
)
func handleFlags() {
flag.Usage = func() {
goyave.ErrLogger.Println("usage: " + os.Args[0] + " -config=[config]")
flag.PrintDefaults()
os.Exit(1)
}
flag.String("config", "", "JSON config file")
flag.Parse()
configDir := flag.Lookup("config")
path := configDir.Value.String()
if path != configDir.DefValue {
if err := config.LoadFrom(path); err != nil {
goyave.ErrLogger.Println(err)
os.Exit(goyave.ExitInvalidConfig)
}
}
}
func main() {
handleFlags()
if err := goyave.Start(route.Register); err != nil {
os.Exit(err.(*goyave.Error).ExitCode)
}
}
# config.LoadJSON
Load a configuration file from raw JSON. Can be used in combination with Go's 1.16 embed (opens new window) directive.
Parameters | Return |
---|---|
cfg string | error |
Example: load the config from an embedded configuration file
import (
"os"
"goyave.dev/goyave/v3"
"goyave.dev/goyave/v3/config"
//...
_ "embed"
)
var (
//go:embed config.json
cfg string
)
func main() {
if err := config.LoadJSON(cfg); err != nil {
goyave.ErrLogger.Println(err)
os.Exit(goyave.ExitInvalidConfig)
}
// This is the entry point of your application.
if err := goyave.Start(route.Register); err != nil {
os.Exit(err.(*goyave.Error).ExitCode)
}
}
# Using environment variables
Since v3.0.0
You can use environment variables in your configuration file. Environment variables are identified by the following syntax: ${VARIABLE_NAME}
.
{
"database": {
"host": "${DB_HOST}"
}
}
Note: This syntax is strict. If the string doesn't start with ${
or doesn't end with }
, it will not be considered an environment variable.
string
, int
, float64
and bool
values are supported. If the configuration entry is expected to be of one of these types, the content of the environment variable will be automatically converted. If the conversion fails, a configuration loading error will be returned.
If an environment variable mentioned in a configuration file is not set, the configuration validation will not pass. Environment variables are not supported inside slices.
# Getting a value
All entries are accessible using dot-separated paths. If you want to access the name
entry in the app
category, the key will be app.name
.
# config.Get
Get a generic config entry.
Prefer using the GetString
, GetBool
, GetInt
, GetFloat
, ... accessors. If you need a type not covered by those accessors, use config.Get
. You may need to type-assert the returned value before using it. You can do so safely as the config values and types are validated.
Panics if the entry doesn't exist.
Parameters | Return |
---|---|
key string | interface{} or panic |
Example:
config.Get("app.name") // "goyave"
# config.GetString
Get a string config entry. Panics if the entry doesn't exist or is not a string
.
Parameters | Return |
---|---|
key string | string or panic |
Example:
config.GetString("server.protocol") // "http"
# config.GetBool
Get a bool config entry. Panics if the entry doesn't exist or is not a bool
.
Parameters | Return |
---|---|
key string | bool or panic |
Example:
config.GetBool("app.debug") // true
# config.GetInt
Since v3.0.0
Get an int config entry. Panics if the entry doesn't exist or is not an int
.
Parameters | Return |
---|---|
key string | int or panic |
Example:
config.GetInt("server.port") // 8080
# config.GetFloat
Since v3.0.0
Get a float config entry. Panics if the entry doesn't exist or is not a float64
.
Parameters | Return |
---|---|
key string | float64 or panic |
Example:
config.GetInt("server.port") // 8080
# config.GetStringSlice
Since v3.0.0
Get a string slice config entry. Panics if the entry doesn't exist or is not a []string
.
Parameters | Return |
---|---|
key string | []string or panic |
Example:
config.GetStringSlice("stringSlice") // [val1 val2]
# config.GetBoolSlice
Since v3.0.0
Get a bool slice config entry. Panics if the entry doesn't exist or is not a []bool
.
Parameters | Return |
---|---|
key string | []bool or panic |
Example:
config.GetBoolSlice("boolSlice") // [true false]
# config.GetIntSlice
Since v3.0.0
Get an int slice config entry. Panics if the entry doesn't exist or is not a []int
.
Parameters | Return |
---|---|
key string | []int or panic |
Example:
config.GetIntSlice("intSlice") // [3 5]
# config.GetFloatSlice
Since v3.0.0
Get a float64 slice config entry. Panics if the entry doesn't exist or is not a []float64
.
Parameters | Return |
---|---|
key string | []float64 or panic |
Example:
config.GetFloatSlice("floatSlice") // [1.42 3.24]
# config.Has
Check if a config entry exists.
Parameters | Return |
---|---|
key string | bool |
Example:
config.Has("app.name") // true
# Setting a value
You can set a config value at runtime with the config.Set(key, value)
function. Bear in mind that this change is temporary and will be lost after your application restarts or if the config is reloaded. This function is mainly used for testing purposes. Values set using this function are still being validated: your application will panic and revert changes if the validation doesn't pass.
Use nil
to unset a value.
- A category cannot be replaced with an entry.
- An entry cannot be replaced with a category.
- New categories can be created with they don't already exist.
- New entries can be created if they don't already exist. This new entry will be subsequently validated using the type of its initial value and have an empty slice as authorized values (meaning it can have any value of its type)
# config.Set
Parameters | Return |
---|---|
key string | void or panic |
value interface{} |
Example:
config.Set("app.name", "my awesome app")
# Custom config entries
Since v3.0.0
Configuration can be expanded. It is very likely that a plugin or a package you're developing is using some form of options. These options can be added to the configuration system so it is not needed to set them in the code or to make some wiring.
# config.Register
Register a new config entry and its validation.
Each module should register its config entries in an init()
function, even if they don't have a default value, in order to ensure they will be validated.
Each module should use its own category and use a name both expressive and unique to avoid collisions. For example, the auth
package registers, among others, auth.basic.username
and auth.jwt.expiry
, thus creating a category for its package, and two subcategories for its features.
To register an entry without a default value (only specify how it will be validated), set Entry.Value
to nil
.
Is IsSlice
is true
, the value of the entry will be a slice of the given Type
. Authorized values for slices define the values that can be used inside the slice. It doesn't represent the value of the slice itself (content and order).
Panics if an entry already exists for this key and is not identical to the one passed as parameter of this function. On the other hand, if the entries are identical, no conflict is expected so the configuration is left in its current state.
Parameters | Return |
---|---|
key string | void or panic |
kind config.Entry |
Example:
func init() {
config.Register("my-plugin.name", config.Entry{
Value: "default value",
Type: reflect.String,
IsSlice: false,
AuthorizedValues: []interface{}{},
})
// Without a default value (only validation)
config.Register("my-plugin.protocol", config.Entry{
Value: nil,
Type: reflect.String,
IsSlice: false,
AuthorizedValues: []interface{}{"ftp", "sftp", "scp"},
})
// Slice
config.Register("my-plugin.remoteHosts", config.Entry{
Value: []string{"first host", "second host"},
Type: reflect.String,
IsSlice: true,
AuthorizedValues: []interface{}{},
})
}
# Configuration reference
# App category
Entry | Type | Default | Note |
---|---|---|---|
name | string | "goyave" | |
environment | string | "localhost" | |
debug | bool | true | When activated, print stacktrace on error and sends error message in response. Disable this in production! |
defaultLanguage | string | "en-US" | See the Localization section |
# Server category
Entry | Type | Accepted values | Default | Note |
---|---|---|---|---|
host | string | any | "127.0.0.1" | |
domain | string | any | "" | Used for URL generation. Leave empty to use IP instead. |
protocol | string | "http", "https" | "http" | See the HTTPS section |
port | int | any | 8080 | |
httpsPort | int | any | 8081 | |
timeout | int | any | 10 | Timeout in seconds |
maxUploadSize | float64 | any | 10 | Maximum size of the request, in MiB |
maintenance | bool | any | false | If true , start the server in maintenance mode. (Always return HTTP 503) |
# TLS sub-category
Entry | Type | Default | Note |
---|---|---|---|
cert | string | none | Path to your TLS cert |
key | string | none | Path to your TLS key |
# Database category
Entry | Type | Default | Note |
---|---|---|---|
connection | string | "none" | See the Database guide |
host | string | "127.0.0.1" | |
port | int | 3306 | |
name | string | "goyave" | |
username | string | "root" | |
password | string | "root" | |
options | string | "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local" | |
maxOpenConnections | int | 20 | |
maxIdleConnections | int | 20 | |
maxLifetime | int | 300 | The maximum time (in seconds) a connection may be reused. |
autoMigrate | bool | false | When activated, migrate all registered models at startup |
# GORM config sub-category
Since v3.10.0
Entry | Type | Default | Note |
---|---|---|---|
skipDefaultTransaction | bool | false | |
dryRun | bool | false | |
prepareStmt | bool | true | |
disableNestedTransaction | bool | false | |
allowGlobalUpdate | bool | false | |
disableAutomaticPing | bool | false | |
disableForeignKeyConstraintWhenMigrating | bool | false |
TIP
See GORM's documentation (opens new window) for more details.
# Setting up HTTPS
Setting up HTTPS on your Goyave application is easy. First, turn server.protocol
to https
in the config. Then, add the server.tls.cert
and server.tls.key
entries in the config. These two entries represent respectively the path to your TLS certificate and your TLS key.
Certbot example:
{
...
"server": {
"protocol": "https",
"tls": {
"cert": "/etc/letsencrypt/live/mydomain.com/cert.pem",
"key": "/etc/letsencrypt/live/mydomain.com/privkey.pem"
}
},
...
}
Restart your server and you should now be able to connect securely to your Goyave application! All HTTP requests will automatically be redirected to HTTPS.