Advanced dynamic smart proxy implementation
This is an advanced setup of the Self-Hosted Query Engine. Vizzly also offers remote config storage which is simpler to use.
The "smart proxy" is so called, because in addition to proxying the requests, it allows you to add in various overrides to dynamically control the Query Engine depending on your own logic, such as showing a different data set to each user.
The smart proxy you implement will receive and then forward all requests to a Vizzly Query Engine, with the addition of a Config-Api-Key
header to authenticate the requests, the Vizzly config and optionally encrypted database connection credentials.
Config-Api-Key
Header
This API key header value must be added for all requests. The value can be generated by running the CLI command
vizzly dynamic-api-key
This will provide you with the API key itself, and the verification hash that needs to be set on the Vizzly Query Engine as an environment variable VIZZLY_DYNAMIC_CONFIG_AUTH_VERIFY_HASH
.
Adding the dynamicConfig
value
For all POST
requests, for which the content-type
header contains a value of application/json
, you will add a dynamicConfig
value to the request body.
Here is a simple NodeJs example of the logic required;
const dynamicConfig = ConfigBuilder.buildConfigForUser(req.cookies['user']);
// Add the `dynamicConfig` property to the body, for POST requests and where content-type is application/json.
if (
req.method == 'POST' &&
req.headers['content-type']?.includes('application/json') &&
proxiedBody
) {
Vizzly Config Structure
The specification of the Vizzly config that defines the data sets to make available on the dashboard, can be found here.
Db-Connection header
Single tenant environments
Using the same encryption key as provided to the Vizzly Query Engine, you can encrypt the connection credentials and provide them in a Db-Connection
header for all requests proxied through to the Vizzly Query Engine.
Here is an example of how you might build the encrypted database connection in a NodeJs environment;
import { Encryption } from '@vizzly/auth';
import * as Settings from './Settings';
export const buildConnection = async (): Promise<string> => {
return await Encryption.encrypt(Settings.getEncryptionSecret(), {
host: Settings.getDatabaseHost(),
password: Settings.getDatabasePassword(),
user: Settings.getDatabaseUser(),
database: Settings.getDatabaseName()
});
};
And then adding it to the request as a Db-Connection
header
// OPTIONAL for dynamic DB connections!
// If you are dynamically changing which database to connect to, you can set the Db-Connection
// header with an encrypted JSON string containing the connection credentials. Alternatively, you
// can setup the connection on the Query Engine using environment variables.
proxiedHeaders[
Example
A NodeJs example written in Typescript can be seen here! (opens in a new tab)