Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
SSL / mutual TLS examples
<IfModule mod_ssl.c>
<VirtualHost *:443>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
ServerAdmin webmaster@localhost
#DocumentRoot /var/www/projects
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
LogLevel info ssl:debug
ErrorLog /var/www/projects/error.log
CustomLog /var/www/projects/access.log combined
SSLCertificateFile /etc/letsencrypt/live/
SSLCertificateKeyFile /etc/letsencrypt/live/
Include /etc/letsencrypt/options-ssl-apache.conf
SSLVerifyClient require
SSLVerifyDepth 2
SSLCACertificateFile "/var/www/projects/ca-crt.pem"
# access control, only allow to connect to fulfillment
<If "%{SSL_CLIENT_S_DN_CN} != '*'">
Require all denied
# sudo a2enmod proxy
# sudo a2enmod proxy_http
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
curl | openssl x509 -inform der >> ca-crt.pem
curl | openssl x509 -inform der >> ca-crt.pem
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const basicAuth = require('express-basic-auth');
const fs = require('fs');
const { WebhookClient, Card, Suggestion } = require('dialogflow-fulfillment');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
// Dialogflow Fulfillment Code
function welcome(agent) {
agent.add(`Welcome to my agent!`);
function fallback(agent) {
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
function yourFunctionHandler(agent) {
agent.add(`Ok. Buying product:`);
agent.add(new Card({
title: agent.parameters.producttype,
imageUrl: '',
text: `This is the body text of a card. You can even use line\n breaks and emoji! 💁`,
buttonText: 'This is a button',
buttonUrl: ''
agent.add(new Suggestion(`Quick Reply`));
agent.add(new Suggestion(`Suggestion`));
agent.context.set({ name: 'gamestore-picked', lifespan: 2, parameters: { gameStore: 'DialogflowGameStore' }});
}'/fulfillment', (request, response) => {;
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('Buy product regex', yourFunctionHandler);
app.get('/', (req, res) => {
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log('Dialogflow Fulfillment listening on port', port);
"name": "dialogflow-fulfillment",
"description": "This is the default fulfillment for a Dialogflow agents using Compute with mTLS",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Lee Boonstra",
"engines": {
"node": "8"
"dependencies": {
"actions-on-google": "^2.5.0",
"body-parser": "^1.19.0",
"dialogflow-fulfillment": "^0.6.1",
"express": "^4.17.1",
"express-basic-auth": "^1.2.0"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment