# Plugins
EMQX allows users to customize the business logic or implement other protocols using plugins. In this chapter, you will learn how to develop plugins.
The basic process of plugin development and operation is as follows:
- Generate the corresponding plugin tar.gz package through the plugin template provided by EMQX.
- Install the plugin packages via Dashboard or CLI.
- Start/stop/uninstall plugins via Dashboard or CLI.
# Develop EMQX Plugins
EMQX offers an emqx-plugin-template (opens new window), which allows you to further customize your plugins. In the section below, we will use the access control plugin as an example to give you a step-by-step guide to plugin development.
Download the plugin template
To download the emqx-plugin-template (opens new window), run:
git clone https://github.com/emqx/emqx-plugin-template
As we can see from the directory structure, this is a standard Erlang application.
$ git clone https://github.com/emqx/emqx-plugin-template
$ ls
LICENSE _build get-rebar3
Makefile check-vsn.sh priv
README.md rebar.config src
2
3
4
5
Test the compile environment
Run make rel
to test whether the plugin can be successfully compiled and packed. No coding is needed.
The plugins under development need to use the functions of the main EMQX, so the program needs first to download the dependency and then compile the main project. Therefore, the first compilation usually takes a long time to complete.
For the compiling environment, see Install from Source code. {% endemqxce %}
Mount the hook functions
Below is the directory structure:
> tree src/
src/
├── emqx_cli_demo.erl
├── emqx_plugin_template.app.src
├─ emqx_plugin_template.erl
├── emqx_plugin_template_app.erl
└── emqx_plugin_template_sup.erl
2
3
4
5
6
7
emqx_plugins_template_app.erl
is the initiation portal of the application, where you can create your own supervision tree or load EMQX's hook functions. This template contains all hook functions, please remove the unnecessary hooks before using it. In this example, we only need 2 hooks for authentication and access control, so we can modify emqx_plugins_template:load/1
as follows:
load(Env) ->
emqx_hooks:add('client.authenticate', {?MODULE, on_client_authenticate, [Env]}, ?HP_HIGHEST),
emqx_hooks:add('client.authorize', {?MODULE, on_client_authorize, [Env]}, ?HP_HIGHEST),
ok.
2
3
4
We will use on_client_authenticate/3
for client authentication and on_client_authorize/5
for access control.
As one hook function may be mounted both by EMQX and customized plugins, we also need to specify the execution order when mounting it to the plugin. HP_HIGHEST
specifies that the current hook function has the highest priority and is executed first.
Customize access control code
%% Only allow connections with clientID name matching any of the following characters: A-Z, a-z, 0-9, and underscore.
on_client_authenticate(_ClientInfo = #{clientid := ClientId}, Result, _Env) ->
case re:run(ClientId, "^[A-Za-z0-9_]+$", [{capture, none}]) of
match -> {ok, Result};
nomatch -> {stop, {error, banned}}
end.
%% Can only subscribe topic /room/{clientid}, but can send messages to any topics.
on_client_authorize(_ClientInfo = #{clientid := ClientId}, subscribe, Topic, Result, _Env) ->
case emqx_topic:match(Topic, <<"/room/", ClientId/binary>>) of
true -> {ok, Result};
false -> stop
end;
on_client_authorize(_ClientInfo, _Pub, _Topic, Result, _Env) -> {ok, Result}.
2
3
4
5
6
7
8
9
10
11
12
13
In the above code example, we only allow clients with clientID matching the specification to log in. These clients can only subscribe to topic /room/{clientid}
, thus building a simple chat room, that is, clients can send messages to any other clients, but each client can only subscribe to topics related to itself.
TIP
- Be sure to set
authorization.no_match
todeny
in the configuration first, that is, EMQX will reject any unauthorized connection requests. - In this example, we illustrate how to customize an access control plugin, you can also set similar authorization rules based on File.
Pack the customized plugin
Modify the version information of the plugin via rebar.config
:
{relx, [ {release, {emqx_plugin_template, "5.0.0-rc.3"}, [emqx_plugin_template, map_sets]}
, {dev_mode, false}
, {include_erts, false}
]}.
%% Additional info about the plugin
{emqx_plugrel,
[ {authors, ["EMQX Team"]}
, {builder,
[ {name, "EMQX Team"}
, {contact, "emqx-support@emqx.io"}
, {website, "www.emqx.com"}
]}
, {repo, "https://github.com/emqx/emqx-plugin-template"}
, {functionality, ["Demo"]}
, {compatibility,
[ {emqx, "~> 5.0"}
]}
, {description, "This is a demo plugin"}
]
}.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Rerun the packing command:
make rel
...
===> Release successfully assembled: _build/default/rel/emqx_plugin_template
===> [emqx_plugrel] creating _build/default/emqx_plugrel/emqx_plugin_template-5.0.0-rc.3.tar.gz
2
3
4
The command will prompt to generate the plugin pluginname-version.tar.gz
.
Install/launch the plugin
Use CLI to install the compiled package:
./bin/emqx_ctl plugins install {pluginName}
Uninstall the plugin
When you don't need the plugin, you can easily uninstall it with CLI:
./bin/emqx_ctl plugins uninstall {pluginName}