# Database and other connection URLs

A database or a cache takes its address from a setting. Each one is a
connection in the `connections:` block of `app.jadpo`, with a driver that
says what kind of store it is
([How packages, connections, capabilities and services fit together](how-integrations-fit-together.md)
says what a connection, a driver and a provider package are):

```jadpo
application {
    connections: {
        main: {
            driver: Driver.postgres
            url: config.database_url
        }
        cache: {
            driver: Driver.redis
            url: config.redis_url
        }
    }
}
```

```jadpo
config {
    database_url: PostgresUrl
    redis_url: RedisUrl
}
```

A project that declares no database has one called `main` on PostgreSQL.
It opens at `config.database_url` when the project declares that setting as
a `PostgresUrl`.

## Connection types

`Url` accepts only `http://` and `https://`, so it can't hold an address
such as `postgres://user:password@host/db`. Each driver has a built-in
type that can:

- `PostgresUrl`, for `postgres://` or `postgresql://`;
- `RedisUrl`, for `redis://` or `rediss://`.

They are always secret, because they normally carry a password. A
connection's `url:` must read a setting of the type its `driver:` needs
(`configuration.url_type`), and an address written in source is refused the
same way. The runtime opens the connection only through that setting.

A connection type checks the address's structure as well as its scheme,
with the same check for literals, the check before the app starts and
`jadpo config check`. Checking never looks up a name or opens a connection.
These are invalid:

- an empty target after the user information;
- a malformed percent escape;
- an invalid port;
- broken IPv6 brackets.

These pass: PostgreSQL addresses with several hosts, encoded credentials,
bracketed IPv6, and explicit socket addresses (`postgres://%2Ftmp/app`,
`postgresql:///app?host=/tmp`). The type also accepts `postgres:///app`,
but that alone gives the driver no socket folder, and the driver assumes
no default one. The driver checks its own options, and whether the
database can be reached, separately. A Redis address needs a host and,
when it has a database path, a number from 0. Every invalid declaration is
reported at once, and credentials are never shown.

## TLS and certificates

A `PostgresUrl` can't set TLS itself (`sslmode` and libpq's other `ssl…`
settings), because its connection in `app.jadpo` decides that
([PostgreSQL over TLS](stores.md#postgresql-over-tls)). Such a value is
`configuration.value_invalid`, which says so.

A setting can be a `Certificate`, read from its PEM text. It is what a
database connection's `authority:` reads: the authority that signed the
database server's certificate.

## Provider packages

A connection to a provider package, a package that calls an outside
service ([Connecting in `app.jadpo`](connecting-in-app-jadpo.md)),
reads its settings the same way, never a value written in source:

- `credential:` reads a `secret: true` setting;
- `environment:` reads a `ProviderEnvironment` setting, the built-in enum
  `.sandbox` or `.live`, which chooses between the package's hosts;
- `host:`, for a package with no fixed hosts, reads a `Url` setting.

A wrong one is `connection.value_invalid`.

```jadpo
// config.jadpo
config {
    couriers_api_key: Text {
        secret: true
    }
    couriers_environment: ProviderEnvironment
}
```
