Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions packages/node_modules/@node-red/editor-api/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,39 @@ var adminApp;
var server;
var editor;

function normaliseHttpNodeRoot(root) {
if (typeof root !== "string" || root === "" || root === "/") {
return null;
}
if (root[0] !== "/") {
root = "/" + root;
}
if (root.length > 1 && root[root.length - 1] === "/") {
root = root.substring(0, root.length - 1);
}
return root;
}

function requestMatchesRoot(req, root) {
var requestPath = (req.originalUrl || "").split("?")[0];
return requestPath === root || requestPath.indexOf(root + "/") === 0;
}

function shouldDeferToHttpNodeCors(settings, req, httpNodeRoot) {
return settings.httpNodeCors && req.method === "OPTIONS" && httpNodeRoot && requestMatchesRoot(req,httpNodeRoot);
}

function createCorsMiddleware(corsHandler, settings, httpNodeRoot) {
return function corsMiddleware(req,res,next) {
// Let httpNodeCors answer preflight requests for HTTP In nodes.
if (shouldDeferToHttpNodeCors(settings, req, httpNodeRoot)) {
next();
} else {
corsHandler(req,res,next);
}
};
}

/**
* Initialise the module.
* @param {Object} settings The runtime settings
Expand All @@ -52,7 +85,8 @@ function init(settings,_server,storage,runtimeAPI) {
origin: "*",
methods: "GET,PUT,POST,DELETE"
});
adminApp.use(corsHandler);
var httpNodeRoot = normaliseHttpNodeRoot(settings.httpNodeRoot);
adminApp.use(createCorsMiddleware(corsHandler, settings, httpNodeRoot));

if (settings.httpAdminMiddleware) {
if (typeof settings.httpAdminMiddleware === "function" || Array.isArray(settings.httpAdminMiddleware)) {
Expand Down Expand Up @@ -93,7 +127,7 @@ function init(settings,_server,storage,runtimeAPI) {

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

var adminApiApp = require("./admin").init(settings, runtimeAPI);
Expand Down
26 changes: 26 additions & 0 deletions test/unit/@node-red/editor-api/lib/index_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var should = require("should");
var sinon = require("sinon");
var request = require("supertest");
var express = require("express");
var cors = require("cors");

var NR_TEST_UTILS = require("nr-test-utils");
const auth = require("basic-auth");
Expand Down Expand Up @@ -154,6 +155,31 @@ describe("api/index", function() {
should(middlewareFound).be.length(2);
done();
})

it('lets http node cors handle node preflight requests mounted below the editor', function(done){
const httpAdminCors = {
origin: "*",
methods: "GET,PUT,POST"
};
const httpNodeCors = {
origin: "*",
methods: "GET,PUT,POST,DELETE,PATCH"
};
const httpNode = express();
httpNode.options("*", cors(httpNodeCors));

api.init({ httpAdminRoot: true, httpNodeRoot: "/api", httpAdminCors, httpNodeCors }, {}, {}, {});

const app = express();
app.use("/", api.httpAdmin);
app.use("/api", httpNode);

request(app)
.options("/api/route")
.expect("access-control-allow-methods", "GET,PUT,POST,DELETE,PATCH")
.expect(204)
.end(done);
})
});

describe('editor start', function () {
Expand Down