While working on Bookis, a need arose to add payments and I used stripe as my payment gateway. In the process of implementation I needed to also setup webhooks. Thats fine in production, but in a local environment I needed a way to "tunnel" the request from stripe to my local computer.
There are numerous free and paid options for this - in the end I used ngrok as I have used it before but this time I did not use the CLI part of it but I used it in a programmatic way.
First add ngrok
to your dev dependencies
npm i -D ngrok
Now, lets create a file called ngrok.js
and add the following
ngrok.js
const ngrok = require('ngrok')
const path = require('path')
const fs = require('fs')
const dotenvFilePath = path.resolve(__dirname, `./.env`)
const dotenv = require('dotenv')
if (fs.existsSync(dotenvFilePath)) {
dotenv.config({
path: dotenvFilePath,
encoding: 'utf8',
})
}
ngrok
.connect({
addr: process.env.PORT, // port or network address, defaultst to 80
authtoken: process.env.NGROK_AUTH_TOKEN, // your authtoken from ngrok.com
subdomain: process.env.NGROK_SUBDOMAIN, // reserved tunnel name https://alex.ngrok.io
region: process.env.NGROK_REGION, // one of ngrok regions (us, eu, au, ap), defaults to us
})
.then(url => {
console.log(`👩🏻💻 Webhook URL for INSERT_DESCRIPTION: ${url}/auth/google`)
console.log(`💳 App URL to see the demo in your browser: ${url}/`)
})
.catch(err => {
if (err.code === 'ECONNREFUSED') {
console.log(`⚠️ Connection refused at ${err.address}:${err.port}`)
} else {
console.log(`⚠️ ${JSON.stringify(err)}`)
}
process.exit(1)
})
OK, so what happens above? Basically you call ngrok.connect
and you are good to go. You will get a random url which you can use to connect any APIs that need to connect with a local API like yours.
Some of the optional parameters I added is for paid use, others are for free/paid use like the region
which you can specify for example 'eu' if you prefer to get a tunnel on a european server of ngrok or the addr
which can be used to specify the port which your local API is running on.
Usage examples
Import in your server file
Wrap the ngrok.js in a function, export that function and include in a server file and call the function from there.
Ngrok and Nodemon
Now ideally, you would load ngrok and your server, but you want your server to be auto-reloaded on change since you are still developing right?
// package.json
...
"scripts": {
"tunnel": "node ngrok.js",
"dev":"nodemon server.js",
"start": "npm-run-all --parallel tunnel dev"
}
...
Conclusion
And there you have it. You are now able to test seamlessly and webhooks from external APIs will be able to communicate with your local app.