cloudcms-server 0.9.246 → 0.9.252
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +6 -1
- package/insight/insight.js +1 -1
- package/middleware/awareness/plugins/editorial.js +4 -4
- package/middleware/form/form.js +2 -2
- package/middleware/virtual-config/virtual-config.js +3 -3
- package/package.json +3 -2
- package/server/index.js +83 -2
- package/server/standalone.js +6 -0
- package/util/cloudcms.js +1 -1
- package/util/renditions.js +1 -1
- package/util/util.js +14 -1
package/index.js
CHANGED
|
@@ -136,6 +136,7 @@ exports = module.exports = function()
|
|
|
136
136
|
// not already specified
|
|
137
137
|
var defaultGitanaProxyScheme = "https";
|
|
138
138
|
var defaultGitanaProxyHost = "api.cloudcms.com";
|
|
139
|
+
var defaultGitanaProxyPath = "";
|
|
139
140
|
var defaultGitanaProxyPort = 443;
|
|
140
141
|
|
|
141
142
|
var gitanaJsonPath = path.join(process.env.CLOUDCMS_APPSERVER_BASE_PATH, "gitana.json");
|
|
@@ -147,6 +148,7 @@ exports = module.exports = function()
|
|
|
147
148
|
var parsedUrl = url.parse(gitanaJson.baseURL);
|
|
148
149
|
|
|
149
150
|
defaultGitanaProxyHost = parsedUrl.hostname;
|
|
151
|
+
defaultGitanaProxyPath = parsedUrl.path;
|
|
150
152
|
defaultGitanaProxyScheme = parsedUrl.protocol.substring(0, parsedUrl.protocol.length - 1); // remove the :
|
|
151
153
|
|
|
152
154
|
if (parsedUrl.port)
|
|
@@ -171,13 +173,16 @@ exports = module.exports = function()
|
|
|
171
173
|
if (!process.env.GITANA_PROXY_HOST) {
|
|
172
174
|
process.env.GITANA_PROXY_HOST = defaultGitanaProxyHost;
|
|
173
175
|
}
|
|
176
|
+
if (!process.env.GITANA_PROXY_PATH) {
|
|
177
|
+
process.env.GITANA_PROXY_PATH = defaultGitanaProxyPath;
|
|
178
|
+
}
|
|
174
179
|
if (!process.env.GITANA_PROXY_PORT) {
|
|
175
180
|
process.env.GITANA_PROXY_PORT = defaultGitanaProxyPort;
|
|
176
181
|
}
|
|
177
182
|
|
|
178
183
|
if (cluster.isMaster)
|
|
179
184
|
{
|
|
180
|
-
process.log("Gitana Proxy pointed to: " + util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT));
|
|
185
|
+
process.log("Gitana Proxy pointed to: " + util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH));
|
|
181
186
|
}
|
|
182
187
|
|
|
183
188
|
// all web modules are included by default
|
package/insight/insight.js
CHANGED
|
@@ -131,7 +131,7 @@ var doSend = function(callback)
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
// url over to cloud cms
|
|
134
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/warehouses/" + warehouseId + "/interactions/_create";
|
|
134
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/warehouses/" + warehouseId + "/interactions/_create";
|
|
135
135
|
var requestConfig = {
|
|
136
136
|
"url": URL,
|
|
137
137
|
"qs": {},
|
|
@@ -43,7 +43,7 @@ exports.bindSocket = function(socket, provider)
|
|
|
43
43
|
var acquireEditorialSession = function(socket, provider, sessionKey, repositoryId, branchId, force, callback)
|
|
44
44
|
{
|
|
45
45
|
// send an HTTP command to acquire an editorial session for this repository and branch
|
|
46
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/oneteam/editorial/session/acquire";
|
|
46
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/oneteam/editorial/session/acquire";
|
|
47
47
|
|
|
48
48
|
var headers = {};
|
|
49
49
|
//headers["Authorization"] = socket.gitana.platform().getDriver().getHttpHeaders()["Authorization"];
|
|
@@ -101,7 +101,7 @@ exports.bindSocket = function(socket, provider)
|
|
|
101
101
|
var releaseEditorialSession = function(socket, provider, sessionKey, repositoryId, branchId, callback)
|
|
102
102
|
{
|
|
103
103
|
// send an HTTP command to release the session
|
|
104
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/oneteam/editorial/session/release";
|
|
104
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/oneteam/editorial/session/release";
|
|
105
105
|
|
|
106
106
|
var json = {};
|
|
107
107
|
json.repositoryId = repositoryId;
|
|
@@ -152,7 +152,7 @@ exports.bindSocket = function(socket, provider)
|
|
|
152
152
|
*/
|
|
153
153
|
var commitEditorialSession = function(socket, provider, sessionKey, repositoryId, branchId, callback)
|
|
154
154
|
{
|
|
155
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/oneteam/editorial/session/commit";
|
|
155
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/oneteam/editorial/session/commit";
|
|
156
156
|
|
|
157
157
|
var json = {};
|
|
158
158
|
json.repositoryId = repositoryId;
|
|
@@ -202,7 +202,7 @@ exports.bindSocket = function(socket, provider)
|
|
|
202
202
|
*/
|
|
203
203
|
var editorialSessionInfo = function(socket, provider, sessionKey, repositoryId, branchId, callback)
|
|
204
204
|
{
|
|
205
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/oneteam/editorial/session/info";
|
|
205
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/oneteam/editorial/session/info";
|
|
206
206
|
|
|
207
207
|
var json = {};
|
|
208
208
|
json.repositoryId = repositoryId;
|
package/middleware/form/form.js
CHANGED
|
@@ -121,7 +121,7 @@ exports = module.exports = function()
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// post form to Cloud CMS using public method
|
|
124
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + url;
|
|
124
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + url;
|
|
125
125
|
|
|
126
126
|
var headers = {};
|
|
127
127
|
headers["Authorization"] = req.gitana.platform().getDriver().getHttpHeaders()["Authorization"];
|
|
@@ -194,7 +194,7 @@ exports = module.exports = function()
|
|
|
194
194
|
|
|
195
195
|
var url = branch.getUri() + "/alpaca/datasource";
|
|
196
196
|
|
|
197
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + url;
|
|
197
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + url;
|
|
198
198
|
|
|
199
199
|
var headers = {};
|
|
200
200
|
headers["Authorization"] = req.gitana.platform().getDriver().getHttpHeaders()["Authorization"];
|
|
@@ -83,7 +83,7 @@ exports = module.exports = function()
|
|
|
83
83
|
|
|
84
84
|
var URL = configuration.virtualDriver.baseURL;
|
|
85
85
|
if (!URL) {
|
|
86
|
-
URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT);
|
|
86
|
+
URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH);
|
|
87
87
|
}
|
|
88
88
|
URL += "/virtual/driver/config";
|
|
89
89
|
var requestConfig = {
|
|
@@ -217,7 +217,7 @@ exports = module.exports = function()
|
|
|
217
217
|
}
|
|
218
218
|
if (!gitanaJson.baseURL)
|
|
219
219
|
{
|
|
220
|
-
gitanaJson.baseURL = util.cleanupURL(util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT));
|
|
220
|
+
gitanaJson.baseURL = util.cleanupURL(util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH));
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
// mark as retrieved from virtual driver
|
|
@@ -340,7 +340,7 @@ exports = module.exports = function()
|
|
|
340
340
|
// defaults
|
|
341
341
|
if (!configuration.baseURL)
|
|
342
342
|
{
|
|
343
|
-
configuration.baseURL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT);
|
|
343
|
+
configuration.baseURL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH);
|
|
344
344
|
}
|
|
345
345
|
if (!configuration.key) {
|
|
346
346
|
configuration.key = "virtual";
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"name": "cloudcms-server",
|
|
8
8
|
"description": "Cloud CMS Application Server Module",
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.252",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
12
|
"url": "git://github.com/gitana/cloudcms-server.git"
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"gitana": "^1.0.315",
|
|
40
40
|
"handlebars": "^4.4.2",
|
|
41
41
|
"hbs": "^4.0.5",
|
|
42
|
+
"helmet": "^4.6.0",
|
|
42
43
|
"http-proxy": "^1.18.1",
|
|
43
44
|
"json5": "^1.0.1",
|
|
44
45
|
"jsonwebtoken": "^8.5.1",
|
|
@@ -85,7 +86,7 @@
|
|
|
85
86
|
"targz": "^1.0.1",
|
|
86
87
|
"temp": "^0.8.3",
|
|
87
88
|
"toobusy-js": "^0.5.1",
|
|
88
|
-
"uuid": "^3.3.
|
|
89
|
+
"uuid": "^3.3.2",
|
|
89
90
|
"vm2": "^3.8.4",
|
|
90
91
|
"watch": "^1.0.2",
|
|
91
92
|
"winston": "^3.3.3"
|
package/server/index.js
CHANGED
|
@@ -16,6 +16,9 @@ var session = require('express-session');
|
|
|
16
16
|
var cookieParser = require('cookie-parser');
|
|
17
17
|
var flash = require("connect-flash");
|
|
18
18
|
|
|
19
|
+
const redis = require('redis');
|
|
20
|
+
const connectRedis = require('connect-redis');
|
|
21
|
+
|
|
19
22
|
// we don't bind a single passport - instead, we get the constructor here by hand
|
|
20
23
|
var Passport = require("passport").Passport;
|
|
21
24
|
|
|
@@ -37,6 +40,8 @@ var duster = require("../duster/index");
|
|
|
37
40
|
|
|
38
41
|
var coreHelpers = require("../duster/helpers/core/index");
|
|
39
42
|
|
|
43
|
+
var helmet = require("helmet");
|
|
44
|
+
|
|
40
45
|
var toobusy = require("toobusy-js");
|
|
41
46
|
toobusy.maxLag(500); // 500 ms lag in event queue, quite high but usable for now
|
|
42
47
|
toobusy.interval(250);
|
|
@@ -585,6 +590,51 @@ var startSlave = function(config, afterStartFn)
|
|
|
585
590
|
if (!process.env.CLOUDCMS_STANDALONE_HOST) {
|
|
586
591
|
process.env.CLOUDCMS_STANDALONE_HOST = "local";
|
|
587
592
|
}
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
// auto-configuration for HTTPS
|
|
596
|
+
if (!process.configuration.https) {
|
|
597
|
+
process.configuration.https = {};
|
|
598
|
+
}
|
|
599
|
+
if (process.env.CLOUDCMS_HTTPS) {
|
|
600
|
+
process.configuration.https = JSON.parse(process.env.CLOUDCMS_HTTPS);
|
|
601
|
+
}
|
|
602
|
+
if (process.env.CLOUDCMS_HTTPS_KEY_FILEPATH) {
|
|
603
|
+
process.configuration.https.key = fs.readFileSync(process.env.CLOUDCMS_HTTPS_KEY_FILEPATH);
|
|
604
|
+
}
|
|
605
|
+
if (process.env.CLOUDCMS_HTTPS_CERT_FILEPATH) {
|
|
606
|
+
process.configuration.https.cert = fs.readFileSync(process.env.CLOUDCMS_HTTPS_CERT_FILEPATH);
|
|
607
|
+
}
|
|
608
|
+
if (process.env.CLOUDCMS_HTTPS_PFX_FILEPATH) {
|
|
609
|
+
process.configuration.https.pfx = fs.readFileSync(process.env.CLOUDCMS_HTTPS_PFX_FILEPATH);
|
|
610
|
+
}
|
|
611
|
+
if (process.env.CLOUDCMS_HTTPS_PASSPHRASE) {
|
|
612
|
+
process.configuration.https.passphrase = process.env.CLOUDCMS_HTTPS_PASSPHRASE;
|
|
613
|
+
}
|
|
614
|
+
if (process.env.CLOUDCMS_HTTPS_REQUEST_CERT === "true") {
|
|
615
|
+
process.configuration.https.requestCert = true;
|
|
616
|
+
}
|
|
617
|
+
if (process.env.CLOUDCMS_HTTPS_CA_FILEPATH) {
|
|
618
|
+
process.configuration.https.ca = [ fs.readFileSync(process.env.CLOUDCMS_HTTPS_CA_FILEPATH) ];
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// if https config is empty, remove it
|
|
622
|
+
if (Object.keys(process.configuration.https).length === 0) {
|
|
623
|
+
delete process.configuration.https;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
// auto configuration of session store
|
|
628
|
+
if (!process.configuration.session) {
|
|
629
|
+
process.configuration.session = {};
|
|
630
|
+
}
|
|
631
|
+
if (process.env.CLOUDCMS_SESSION_TYPE) {
|
|
632
|
+
process.configuration.session.enabled = true;
|
|
633
|
+
process.configuration.session.type = process.env.CLOUDCMS_SESSION_TYPE;
|
|
634
|
+
}
|
|
635
|
+
if (process.env.CLOUDCMS_SESSION_SECRET) {
|
|
636
|
+
process.configuration.session.secret = process.env.CLOUDCMS_SESSION_SECRET;
|
|
637
|
+
}
|
|
588
638
|
|
|
589
639
|
// session store
|
|
590
640
|
var initializedSession = null;
|
|
@@ -618,6 +668,28 @@ var startSlave = function(config, afterStartFn)
|
|
|
618
668
|
var SessionFileStore = require('session-file-store')(session);
|
|
619
669
|
sessionConfig.store = new SessionFileStore(options);
|
|
620
670
|
}
|
|
671
|
+
else if (process.configuration.session.type === "redis")
|
|
672
|
+
{
|
|
673
|
+
var redisPort = process.env.CLOUDCMS_REDIS_PORT;
|
|
674
|
+
var redisHost = process.env.CLOUDCMS_REDIS_ENDPOINT;
|
|
675
|
+
|
|
676
|
+
if (!redisPort)
|
|
677
|
+
{
|
|
678
|
+
console.error("Cannot configure session for Redis storage because CLOUDCMS_REDIS_PORT is not defined");
|
|
679
|
+
}
|
|
680
|
+
else if (!redisHost)
|
|
681
|
+
{
|
|
682
|
+
console.error("Cannot configure session for Redis storage because CLOUDCMS_REDIS_ENDPOINT is not defined");
|
|
683
|
+
}
|
|
684
|
+
else
|
|
685
|
+
{
|
|
686
|
+
var redisOptions = {};
|
|
687
|
+
var redisClient = redis.createClient(redisPort, redisHost, redisOptions);
|
|
688
|
+
|
|
689
|
+
var RedisStore = connectRedis(session);
|
|
690
|
+
sessionConfig.store = new RedisStore({ client: redisClient });
|
|
691
|
+
}
|
|
692
|
+
}
|
|
621
693
|
else if (process.configuration.session.type === "memory" || !process.configuration.session.type)
|
|
622
694
|
{
|
|
623
695
|
var options = {};
|
|
@@ -1045,8 +1117,17 @@ var startSlave = function(config, afterStartFn)
|
|
|
1045
1117
|
////////////////////////////////////////////////////////////////////////////
|
|
1046
1118
|
|
|
1047
1119
|
|
|
1048
|
-
//
|
|
1049
|
-
var server =
|
|
1120
|
+
// create the server (either HTTP or HTTPS)
|
|
1121
|
+
var server = null;
|
|
1122
|
+
if (process.configuration.https) {
|
|
1123
|
+
// configure helmet to support auto-upgrade of http->https
|
|
1124
|
+
app.use(helmet());
|
|
1125
|
+
// create https server
|
|
1126
|
+
server = https.createServer(process.configuration.https, app);
|
|
1127
|
+
} else {
|
|
1128
|
+
// legacy
|
|
1129
|
+
server = http.Server(app);
|
|
1130
|
+
}
|
|
1050
1131
|
|
|
1051
1132
|
// request timeout
|
|
1052
1133
|
var requestTimeout = 30000; // 30 seconds
|
package/server/standalone.js
CHANGED
|
@@ -45,6 +45,7 @@ server.report(function(callback) {
|
|
|
45
45
|
console.log("Server Base Path: " + process.env.CLOUDCMS_APPSERVER_BASE_PATH);
|
|
46
46
|
console.log("Gitana Scheme: " + process.env.GITANA_PROXY_SCHEME);
|
|
47
47
|
console.log("Gitana Host: " + process.env.GITANA_PROXY_HOST);
|
|
48
|
+
console.log("Gitana Path: " + process.env.GITANA_PROXY_PATH);
|
|
48
49
|
console.log("Gitana Port: " + process.env.GITANA_PROXY_PORT);
|
|
49
50
|
console.log("CPU Count: " + cpuCount);
|
|
50
51
|
|
|
@@ -68,6 +69,11 @@ server.report(function(callback) {
|
|
|
68
69
|
console.log("Hosts Directory: " + process.env.CLOUDCMS_HOSTS_PATH);
|
|
69
70
|
console.log("LaunchPad Mode: " + process.env.CLOUDCMS_LAUNCHPAD_SETUP);
|
|
70
71
|
console.log("Max Files Detected: " + process.env.CLOUDCMS_MAX_FILES);
|
|
72
|
+
console.log("Session Type: " + process.configuration.session.type);
|
|
73
|
+
|
|
74
|
+
if (process.configuration.https) {
|
|
75
|
+
console.log("Server is configured to use HTTPS");
|
|
76
|
+
}
|
|
71
77
|
|
|
72
78
|
console.log("");
|
|
73
79
|
|
package/util/cloudcms.js
CHANGED
|
@@ -382,7 +382,7 @@ exports = module.exports = function()
|
|
|
382
382
|
agent = https.globalAgent;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + uri;
|
|
385
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + uri;
|
|
386
386
|
request({
|
|
387
387
|
"method": "GET",
|
|
388
388
|
"url": URL,
|
package/util/renditions.js
CHANGED
|
@@ -61,7 +61,7 @@ exports = module.exports = function()
|
|
|
61
61
|
|
|
62
62
|
var syncRows = function(rows, callback)
|
|
63
63
|
{
|
|
64
|
-
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT) + "/bulk/pagerenditions";
|
|
64
|
+
var URL = util.asURL(process.env.GITANA_PROXY_SCHEME, process.env.GITANA_PROXY_HOST, process.env.GITANA_PROXY_PORT, process.env.GITANA_PROXY_PATH) + "/bulk/pagerenditions";
|
|
65
65
|
|
|
66
66
|
var agent = http.globalAgent;
|
|
67
67
|
if (process.env.GITANA_PROXY_SCHEME === "https")
|
package/util/util.js
CHANGED
|
@@ -1787,7 +1787,7 @@ var zip = exports.zip = function(directoryPath, writableStream)
|
|
|
1787
1787
|
*
|
|
1788
1788
|
* @type {Function}
|
|
1789
1789
|
*/
|
|
1790
|
-
var asURL = exports.asURL = function(protocol, host, port)
|
|
1790
|
+
var asURL = exports.asURL = function(protocol, host, port, path)
|
|
1791
1791
|
{
|
|
1792
1792
|
// protocol lower case
|
|
1793
1793
|
protocol = protocol.toLowerCase();
|
|
@@ -1813,6 +1813,19 @@ var asURL = exports.asURL = function(protocol, host, port)
|
|
|
1813
1813
|
}
|
|
1814
1814
|
}
|
|
1815
1815
|
|
|
1816
|
+
// include url "path" if defined
|
|
1817
|
+
if (path) {
|
|
1818
|
+
path = '/' + path;
|
|
1819
|
+
path = path.replace(/\/+/g, '/'); // ensure no extra '/' characters
|
|
1820
|
+
if (path.endsWith('/')) {
|
|
1821
|
+
// remove trailing '/' character
|
|
1822
|
+
path = path.substring(0, path.length - 1);
|
|
1823
|
+
}
|
|
1824
|
+
if (path) {
|
|
1825
|
+
url += path;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1816
1829
|
return url;
|
|
1817
1830
|
};
|
|
1818
1831
|
|