Analysis of partial source code of Node-RED editor-api

freeFree Technical Resource

This content is free to read, suitable for basic learning and search traffic.

Analysis of partial source code of Node-RED editor-api

Background

Recently, I have been receiving inquiries from readers about how to customize and develop Node-RED for their own projects.
For example, they want to adjust the layout and theme color of Node-RED, add some buttons, or integrate other functionalities.
In the following articles, we will analyze the source code of NODE-RED.

The core code of NODE-RED is mainly located in thepackages/node_modules/@node-reddirectory.
According to the latest version, there are six subdirectories under this directory, namely:

  • editor-api: backend code of the editor
  • editor-client: frontend code of the editor
  • nodes: default installed nodes
  • registry: registration management of plugins, libraries, and nodes
  • runtime: runtime entry, also the entry of node-red
  • util auxiliary tool

This section first explains the role and important source code of the editor-api directory. It is convenient for developers to quickly understand and find the corresponding files during development.

editor-api

This directory stores the backend API services that support the editor-client functionality.
It is an application started using express. It depends on @node-red/util and @node-red/editor-client.
The entry point of this module is the./lib/index.js

application initialization code

function init(settings,_server,storage,runtimeAPI) {
    server = _server;
    if (settings.httpAdminRoot !== false) {
        adminApp = express();

        var cors = require('cors');
        var corsHandler = cors({
           origin: "*",
           methods: "GET,PUT,POST,DELETE"
        });
        adminApp.use(corsHandler);

        if (settings.httpAdminMiddleware) {
            if (typeof settings.httpAdminMiddleware === "function" || Array.isArray(settings.httpAdminMiddleware)) {
                adminApp.use(settings.httpAdminMiddleware);
            }
        }

        var defaultServerSettings = {
            "x-powered-by": false
        }
        var serverSettings = Object.assign({},defaultServerSettings,settings.httpServerOptions||{});
        for (var eOption in serverSettings) {
            adminApp.set(eOption, serverSettings[eOption]);
        }

        auth.init(settings,storage);

        var maxApiRequestSize = settings.apiMaxLength || '5mb';
        adminApp.use(bodyParser.json({limit:maxApiRequestSize}));
        adminApp.use(bodyParser.urlencoded({limit:maxApiRequestSize,extended:true}));

        adminApp.get("/auth/login",auth.login,apiUtil.errorHandler);
        if (settings.adminAuth) {
            if (settings.adminAuth.type === "strategy") {
                auth.genericStrategy(adminApp,settings.adminAuth.strategy);
            } else if (settings.adminAuth.type === "credentials") {
                adminApp.use(passport.initialize());
                adminApp.post("/auth/token",
                    auth.ensureClientSecret,
                    auth.authenticateClient,
                    auth.getToken,
                    auth.errorHandler
                );
            } else if (settings.adminAuth.tokens) {
                adminApp.use(passport.initialize());
            }
            adminApp.post("/auth/revoke",auth.needsPermission(""),auth.revoke,apiUtil.errorHandler);
        }

        // Editor
        if (!settings.disableEditor) {
            editor = require("./editor");
            var editorApp = editor.init(server, settings, runtimeAPI);
            adminApp.use(editorApp);
        }

        if (settings.httpAdminCors) {
            var corsHandler = cors(settings.httpAdminCors);
            adminApp.use(corsHandler);
        }

        var adminApiApp = require("./admin").init(settings, runtimeAPI);
        adminApp.use(adminApiApp);
    } else {
        adminApp = null;
    }
}

located in the lib directory. There are three directories under lib: admin, auth, and editor.
Each of these three directories contains an index.js file that defines the interface routes, required permissions for the interface, and the corresponding processing functions.

The login logic and authentication of the editor are all handled in this module.
The login authentication and editor-related interfaces provided in this module are stored ineditor-api/lib/auth/index.js

The editor-related interfaces provided under this module are stored ineditor-api/lib/editorunder the directory.
For example, internationalization, certificates, themes, settings,

the underlying interface in the editor-api calls the runtime interface. For instance, the delete function in admin/context.
It callsruntimeAPI

runtimeAPI.context.delete(opts).then(function(result) {
    res.status(204).end();
}).catch(function(err) {
    apiUtils.rejectHandler(req,res,err);
})

. By now, I believe everyone understands that when a user clicks a button in the editor to request an interface,
the user's request first reaches the editor-api module. Some logic is processed directly in this module and returned to the client.
While some logic calls functions in the runtime and is processed by the runtime before being returned to the user's client.

For example,
opening the node-red editor requests a flows interface,
http://127.0.0.1:1880/flows?_=1676345536746

which can be found in admin/index.js
adminApp.get("/flows",needsPermission("flows.read"),flows.get,apiUtil.errorHandler);
as shown below
to define the route entry

Analysis of partial source code of Node-RED editor-api插图

Define the handler function

Analysis of partial source code of Node-RED editor-api插图1

This is the handler function/flowscorresponding to the routeflows.get.

. By injecting this class, every request you see in the browser can find its corresponding route configuration in the editor-api.
Of course, some use wildcards. They are loaded as static resources.

Summary

To modify NODE-RED, you must understand how to find the corresponding code based on the page and interface you see.
Sometimes, you only need to modify one line of code, but finding the location of that line can take half a day.

Related Tags
Put this resource to use in a real project?

Go to the Tool Center for message parsing, CRC verification and device debugging, or submit your requirements for selection and integration advice.

Engineer Membership

Turn this article into actionable debugging resources

After activation, you can use advanced message parsing, resource pack downloads, code examples, engineering cases and priority technical support, suitable for real project delivery.

Unlimited Advanced Tools
Resource & Code Packs
Complete Engineering Case Library
Priority Technical Support

Leave a Reply

Your email address will not be published. Required fields are marked *.