Learn the basic functionality of the Weebly Node Webhook Client. Click the "Start" button below to see how Viewsaurus works.
Start TutorialThe tutorial's navigation controls are located above this text. Use <i class="fa fa-fw fa-play"></i> to move to the next step of the tutorial. Use <i class="fa fa-fw fa-play fa-rotate-180"></i> to move to the previous step of the tutorial (if there is one). Use <i class="fa fa-fw fa-list"></i> to see an overview of all the steps in the tutorial.
To obtain valid API Keys, you must first register your weebly app.
Please name this new app uniquely by using the following app naming convention (you will use this later in the tutorial as well): {{PREFIX}}-evt-sub
To ensure a unique naming patter, I recommend setting {{PREFIX}} to the initial of your first name + first three characters of your last name.
For example, if your name is "James Gunn", your {{PREFIX}} would be: jgun
.
Set the 'category' of your new app to Services
.
Please use the instructions Usages in the README.md
file to setup this app for live operation and to see it in action.
This app uses the Express.js web application framework. Since Express.js is well documented, this tutorial will not go into too many details, but there are some specific pieces of code you should understand.
Express.js allows developers to write middleware for their applications to customize how their applications handle requests and responses.
While it is outside of the scope of this tutorial, it is important to note, there are other types of middlware Express allows you to use:
Express.js allows developers to write middleware for their applications.
Highlighted is the instantiation of custom Express.js - Application-Level Middleware written specifically for the Weebly Node Webhook Client,
Next, take a look at the code-behind the Weebly Middleware...
In case you are not familiar, the Weebly Middleware is a Node.js module that exports a function wrapper.
The wrapperfunction sets up some internal variables then ensures API Keys have been set either explicitly in code and supplied as arguments, or implicitly in your environment variables or from command line options.
This particular middleware exposes your Weebly API Keys as properties of the request in Express.
This allows you to reference these values from within subsequent Router Middleware in the following manner:
req.app.clientId
req.app.clientSecret
Mounting middleware into your app is relatively simple once it is defined, but the order is very important.
For each HTTP request your app will receives to: /oauth
or /webhooks
this code defines how it should be handled.
Specifically, you can see that each route has its own middleware chain and they both share the Weebly (Application-Level) Middleware, which is executed before the Router-Level Middleware for both routes.
/oauth[...]
will be sent to the Weebly Middleware, and then to the OAuth Routing Middleware/webhooks[...]
will be sent to the Weebly Middleware, and then to the Webhook Routing Middleware oauth-router.js
is custom Express.js Routing Middleware made specifically for Weebly.
It handles all incoming HTTP requests to /oauth
(where '/' is the webroot of the app).
Please read the App Authorization and Installation Flow to understand each phase of the OAuth2 Authorization Flow that Weebly apps encounter during installation.
First, the code will accept HTTP GET requests going to /oauth/phase-one
, and immediately defines the clientId
and secretKey
variables which were made available from the Weebly Middleware.
As a developer, you must KNOW with great confidence the inbound requests your web applications can trust.
In this section of code you can see how to invalidate requests to ensure that requests sent to this particular route can be trusted as coming from Weebly. Here, a comparison object is created and converted into a string (verification HMAC) using identical values to the Weebly generated HMAC. then you use these two pieces of data to invalidate the HMAC query parameter received in requests to this route, are actually requests you can trust were sent from Weebly servers.
You can read the details about this here, but to provide you the 'gist' of what happens:
manifest.json
) that your app is requestingSince the request is trusted, you first generate the second phase URL, callback parameters, and version (if included in the original request).
Then your app tells the Express response object to redirect to the appropriate Weebly URL to obtain an authorization_code
.
If the redirect is successfully formed/accepted, Weebly will respond to your redirect by sending a new HTTP request to containing an authorization_code
correlating to the Weebly User and Site.
Here, the code designates it will accept HTTP GET requests going to /oauth/phase-two
, and immediately defines the clientId
and secretKey
variables which were made available from the Weebly Middleware.
NOTE: It is of CRITICAL IMPORTANCE you take every measure possible to secure and mitigate attackers from obtaining your Weebly API Keys (including your app manifest.json
file).
There are a few things happening here to exchange the authorization_code
for a valid access_token
:
authorization_code
, client_id
, client_secret
redirect_url
parameter is used as the destination for the subsequent code-token exchange request/app-center/oauth/access_token
access_token
will be received upon a successful request, and should be stored securely by your app for future Weebly API requestsMany developers get confused about when their app is actually "installed" and "connected" to a Weebly site.
Logging new access_tokens to '/messages/messages.txt' file is not very useful or productive. What this section of code represents is the correct point-in-time during the App Authorization and Installation Flow when your app/service has an opportunity to ensure the most optimal User Experience by performing any:
These types of service initializations should occur prior to your app redirecting to the final destination, which you can see in the next step of the tutorial.
To reach this point in the code, your app must have:
manifest.json
callback_url propertyauthorization_code
from the phase-two portion of the OAuth2 Authorization Flowauthorization_code
for a valid API access_token
This final redirect indicates to Weebly that your app has completed all necessary setup and configuration operations, and the app should be considered "installed" and "connected".
If your app does not perform this final redirect, your app will be in a disconnected state.
webhooks-router.js
is custom Express.js Routing Middleware handling all incoming HTTP requests beginning with /webhooks
.
The URL where events will be sent is defined in webhooks.callback_url
property of your manifest.json
.
Please read the Receiving Webhooks to understand the data Weebly will POST to your app when events occur to which your app has subscribed.
Weebly apps can subscribe to events. There are several different types of events available for your app to be notified about when they occur upon a site where your app is installed:
You define the types of Weebly Events your app will receive in the webhooks.events property in your manifest.json
.
The default events
this app subscribes to are: app.uninstall
, user.update
, site.publish
, site.delete
. These are all crucial events for any Weebly App and are highly recommended for subscription.
The code here indicates this app will only HTTP POST requests sent to:
{{YOUR_APP_ROOT_URL}}/webhooks/callback
will be accepted, but you still need to peform request invalidation to be certain Weebly sent the request.
To prevent malicious attackers from spoofing or forging requests to your webhook.callback_url
you need to invalidate the request.
All Webhook Event POST Request Body will contain:
client_id
: Your app's Client ID from the Weebly Developer Admin Portalclient_version
: The version of your app which generated the event (helpful in cases of managing multiple versions)event
: The event name (according to the Weebly Webhook docs)timestamp
: Unix epoch timestamp when the event occurred according to Weebly serversdata
: Event-specific data, see the respective Webhook Event Type docshmac
: client_id,
client_version,
event,
timestamp, and
data` sent in the request to be used to invalidate incoming event requestsSimilar to verifying the HMAC hash received on app installation, here we prepare a comparison object/string and then re-generate the HMAC to be certain the request was actually created and sent by Weebly.
Here, the code is merely logging the event headers and requests to console, but this is an opportunity for your app to become event-driven!
In production apps, this is the point-in-time to handle events allowing your app to behave proactively, addressing concerns such as:
app.uninstall
or site.delete
events)When your app has received a valid and verified Weebly Event Request, it is expected that your server will respond with an HTTP 200 Status Code before the request times out.
If you respond with anything other than an HTTP 200 to a valid Weebly Webhook Event Request, Weebly will continue to retry sending the Webhook event to your server up to 12 times over a 48 hour period.
A natural next step is for you to develop custom event handlers that interoperate with your business systems.
This app is already subscribed to: app.uninstall
, site.publish
, site.delete
, and user.update
events.
How would you implement custom handlers for each of these types of events?
You'll want to have a persistent data store to handle:
app.uninstall
or site.delete
eventsTo help us improve this tutorial, and the code we open source, we need your feedback: