diff --git a/app/addons/activetasks/layout.js b/app/addons/activetasks/layout.js index b01a84e99..b6b88d203 100644 --- a/app/addons/activetasks/layout.js +++ b/app/addons/activetasks/layout.js @@ -11,6 +11,7 @@ // the License. import React from 'react'; +import Helpers from "../../helpers"; import FauxtonAPI from "../../core/api"; import {OnePane, OnePaneHeader, OnePaneContent} from '../components/layouts'; import {ActiveTasksController, ActiveTasksPollingWidgetController} from "./components"; @@ -25,7 +26,7 @@ export const ActiveTasksLayout = () => { diff --git a/app/addons/activetasks/resources.js b/app/addons/activetasks/resources.js index 7b8867793..23803bb94 100644 --- a/app/addons/activetasks/resources.js +++ b/app/addons/activetasks/resources.js @@ -10,14 +10,14 @@ // License for the specific language governing permissions and limitations under // the License. -import app from "../../app"; +import Helpers from "../../helpers"; import Actions from "./actions"; var Active = {}; Active.AllTasks = Backbone.Collection.extend({ url: function () { - return app.host + '/_active_tasks'; + return Helpers.getServerUrl('/_active_tasks'); }, pollingFetch: function () { //still need this for the polling diff --git a/app/addons/auth/api.js b/app/addons/auth/api.js index d70682092..75363769f 100644 --- a/app/addons/auth/api.js +++ b/app/addons/auth/api.js @@ -11,6 +11,7 @@ // the License. import app from './../../app'; +import Helpers from "../../helpers"; import { defaultsDeep } from "lodash"; export const json = (url, opts = {}) => fetch( @@ -43,7 +44,8 @@ export const formEncoded = (url, opts = {}) => fetch( export function createAdmin({name, password, node}) { - return json(`${app.host}/_node/${node}/_config/admins/${name}`, { + const url = Helpers.getServerUrl(`/_node/${node}/_config/admins/${name}`); + return json(url, { method: "PUT", body: JSON.stringify(password) }); @@ -56,7 +58,8 @@ export function getSession() { return loggedInSessionPromise; } - const promise = json(app.host + "/_session").then(resp => { + const url = Helpers.getServerUrl('/_session'); + const promise = json(url).then(resp => { if (resp.userCtx.name) { loggedInSessionPromise = promise; } @@ -67,7 +70,8 @@ export function getSession() { } export function login(body) { - return formEncoded(app.host + "/_session", { + const url = Helpers.getServerUrl('/_session'); + return formEncoded(url, { method: "POST", body: app.utils.queryParams(body) }); @@ -75,7 +79,8 @@ export function login(body) { export function logout() { loggedInSessionPromise = null; - return formEncoded(app.host + "/_session", { + const url = Helpers.getServerUrl('/_session'); + return formEncoded(url, { method: "DELETE", body: app.utils.queryParams({ username: "_", password: "_" }) }); diff --git a/app/addons/cluster/resources.js b/app/addons/cluster/resources.js index 675c8ac78..95b7ccb11 100644 --- a/app/addons/cluster/resources.js +++ b/app/addons/cluster/resources.js @@ -10,17 +10,14 @@ // License for the specific language governing permissions and limitations under // the License. -import app from "../../app"; import FauxtonAPI from "../../core/api"; +import Helpers from "../../helpers"; var Cluster = FauxtonAPI.addon(); Cluster.ClusterNodes = Backbone.Model.extend({ - url: function (context) { - if (context === 'apiurl') { - return window.location.origin + '/_membership'; - } - return app.host + '/_membership'; + url: function () { + return Helpers.getServerUrl('/_membership'); }, parse: function (res) { diff --git a/app/addons/config/resources.js b/app/addons/config/resources.js index 98820066d..cd4401dec 100644 --- a/app/addons/config/resources.js +++ b/app/addons/config/resources.js @@ -10,8 +10,8 @@ // License for the specific language governing permissions and limitations under // the License. -import app from "../../app"; import FauxtonAPI from "../../core/api"; +import Helpers from "../../helpers"; import { deleteRequest, put } from "../../core/ajax"; var Config = FauxtonAPI.addon(); @@ -23,9 +23,9 @@ Config.OptionModel = Backbone.Model.extend({ if (!this.get('node')) { throw new Error('no node set'); } - - return app.host + '/_node/' + this.get('node') + '/_config/' + + const endpointUrl = '/_node/' + this.get('node') + '/_config/' + this.get('sectionName') + '/' + encodeURIComponent(this.get('optionName')); + return Helpers.getServerUrl(endpointUrl); }, isNew () { return false; }, @@ -59,8 +59,7 @@ Config.ConfigModel = Backbone.Model.extend({ if (!this.get('node')) { throw new Error('no node set'); } - - return app.host + '/_node/' + this.get('node') + '/_config'; + return Helpers.getServerUrl('/_node/' + this.get('node') + '/_config'); }, parse (resp) { diff --git a/app/addons/cors/reducers.js b/app/addons/cors/reducers.js index 0a35d4bed..81ede6170 100644 --- a/app/addons/cors/reducers.js +++ b/app/addons/cors/reducers.js @@ -11,6 +11,7 @@ // the License. import ActionTypes from "./actiontypes"; +import _ from "lodash"; const initialState = { corsEnabled: false, @@ -34,7 +35,7 @@ export default function cors (state = initialState, action) { isLoading: false, node: corsOptions.node, corsEnabled: corsOptions.corsEnabled, - isAllOrigins: _.include(corsOptions.origins, '*'), + isAllOrigins: _.includes(corsOptions.origins, '*'), origins: corsOptions.origins, deleteDomainModalVisible: false, domainToDelete: '' diff --git a/app/addons/databases/actions.js b/app/addons/databases/actions.js index 5b112bc50..5e2178178 100644 --- a/app/addons/databases/actions.js +++ b/app/addons/databases/actions.js @@ -10,6 +10,7 @@ // License for the specific language governing permissions and limitations under // the License. import app from "../../app"; +import Helpers from "../../helpers"; import FauxtonAPI from "../../core/api"; import { get } from "../../core/ajax"; import Stores from "./stores"; @@ -184,7 +185,7 @@ export default { limit: 30 }); - const url = `${app.host}/_all_dbs${query}`; + const url = Helpers.getServerUrl(`/_all_dbs${query}`); get(url).then((dbs) => { const options = dbs.map(db => { return { diff --git a/app/addons/databases/base.js b/app/addons/databases/base.js index 8264e93e2..72d50e371 100644 --- a/app/addons/databases/base.js +++ b/app/addons/databases/base.js @@ -11,6 +11,7 @@ // the License. import app from "../../app"; +import Helpers from "../../helpers"; import FauxtonAPI from "../../core/api"; import Databases from "./routes"; import "./assets/less/databases.less"; @@ -34,7 +35,7 @@ Databases.databaseUrl = function (database) { FauxtonAPI.registerUrls('changes', { server: function (id, query) { - return app.host + '/' + id + '/_changes' + query; + return Helpers.getServerUrl('/' + id + '/_changes' + query); }, app: function (id, query) { @@ -42,13 +43,13 @@ FauxtonAPI.registerUrls('changes', { }, apiurl: function (id, query) { - return window.location.origin + '/' + id + '/_changes' + query; + return Helpers.getApiUrl('/' + id + '/_changes' + query); } }); FauxtonAPI.registerUrls('allDBs', { server: function (query = '') { - return `${app.host}/_all_dbs${query}`; + return Helpers.getServerUrl(`/_all_dbs${query}`); }, app: function () { @@ -56,15 +57,17 @@ FauxtonAPI.registerUrls('allDBs', { }, apiurl: function () { - return window.location.origin + '/_all_dbs'; + return Helpers.getApiUrl('/_all_dbs'); } }); FauxtonAPI.registerUrls('databaseBaseURL', { server: function (database) { - return window.location.origin + '/' + app.utils.safeURLName(database); + return Helpers.getServerUrl('/' + app.utils.safeURLName(database)); + }, + apiurl: function(database) { + return Helpers.getApiUrl('/' + app.utils.safeURLName(database)); }, - app: function (database) { return '/database/' + database; } @@ -72,7 +75,7 @@ FauxtonAPI.registerUrls('databaseBaseURL', { FauxtonAPI.registerUrls('permissions', { server: function (db) { - return app.host + '/' + db + '/_security'; + return Helpers.getServerUrl('/' + db + '/_security'); }, app: function (db) { @@ -80,7 +83,7 @@ FauxtonAPI.registerUrls('permissions', { }, apiurl: function (db) { - return window.location.origin + '/' + db + '/_security'; + return Helpers.getApiUrl('/' + db + '/_security'); } }); diff --git a/app/addons/databases/resources.js b/app/addons/databases/resources.js index dfb9c46d5..ae379c44d 100644 --- a/app/addons/databases/resources.js +++ b/app/addons/databases/resources.js @@ -11,6 +11,7 @@ // the License. import app from "../../app"; +import Helpers from "../../helpers"; import FauxtonAPI from "../../core/api"; import Documents from "../documents/resources"; var Databases = FauxtonAPI.addon(); @@ -47,7 +48,7 @@ Databases.Model = FauxtonAPI.Model.extend({ } else if (context === "web-index") { return "#/database/" + this.safeID() + "/_all_docs?limit=" + Databases.DocLimit; } else if (context === "apiurl") { - return window.location.origin + "/database/" + this.safeID() + "/_all_docs"; + return Helpers.getApiUrl("/database/" + this.safeID() + "/_all_docs"); } else if (context === "changes") { return FauxtonAPI.urls('changes', 'app', this.safeID(), '?descending=true&limit=100&include_docs=true'); } else if (context === "changes-apiurl") { @@ -55,7 +56,7 @@ Databases.Model = FauxtonAPI.Model.extend({ } else if (context === "app") { return "/database/" + this.safeID(); } - return app.host + "/" + this.safeID(); + return Helpers.getServerUrl("/" + this.safeID()); }, diff --git a/app/addons/documentation/components.js b/app/addons/documentation/components.js index 1cde5d701..b2fe310be 100644 --- a/app/addons/documentation/components.js +++ b/app/addons/documentation/components.js @@ -11,6 +11,7 @@ // the License. import React from "react"; +import Helpers from '../../helpers'; const docLinks = [ { @@ -20,7 +21,7 @@ const docLinks = [ }, { title: 'CouchDB Official Documentation — Offline', - link: '/_utils/docs/index.html', + link: Helpers.getServerUrl('/docs/index.html'), iconClassName: 'couchdb-icon' }, { diff --git a/app/addons/documentation/tests/nightwatch/checksDocsPage.js b/app/addons/documentation/tests/nightwatch/checksDocsPage.js index e36e3c5f4..0fc5baa5a 100644 --- a/app/addons/documentation/tests/nightwatch/checksDocsPage.js +++ b/app/addons/documentation/tests/nightwatch/checksDocsPage.js @@ -14,13 +14,13 @@ module.exports = { 'Check the documentation page exists': function (client) { - var waitTime = client.globals.maxWaitTime; + const waitTime = client.globals.maxWaitTime; client .loginToGUI() .clickWhenVisible('a[href="#/documentation"]') .waitForElementVisible('a[href="http://docs.couchdb.org/en/latest/"]', waitTime, false) - .waitForElementVisible('a[href="/_utils/docs/index.html"]', waitTime, false) + .waitForElementVisible('a[href="./docs/index.html"]', waitTime, false) .waitForElementVisible('a[href="http://blog.couchdb.org/"]', waitTime, false) .waitForElementVisible('a[href="https://couchdb.apache.org/"]', waitTime, false) .waitForElementVisible('a[href="https://github.com/apache/couchdb"]', waitTime, false) diff --git a/app/addons/documents/base.js b/app/addons/documents/base.js index 053b9b472..144be20fd 100644 --- a/app/addons/documents/base.js +++ b/app/addons/documents/base.js @@ -11,6 +11,7 @@ // the License. import app from "../../app"; +import Helpers from "../../helpers"; import FauxtonAPI from "../../core/api"; import Documents from "./routes"; import reducers from "./index-results/reducers"; @@ -36,7 +37,7 @@ function getQueryParam (query) { FauxtonAPI.registerUrls('allDocs', { server: function (id, query) { /** XXX DEPRECATED: use allDocsSanitized **/ - return app.host + '/' + id + '/_all_docs' + getQueryParam(query); + return Helpers.getServerUrl('/' + id + '/_all_docs' + getQueryParam(query)); }, app: function (id, query) { /** XXX DEPRECATED: use allDocsSanitized **/ @@ -44,14 +45,14 @@ FauxtonAPI.registerUrls('allDocs', { }, apiurl: function (id, query) { /** XXX DEPRECATED: use allDocsSanitized **/ - return window.location.origin + '/' + id + '/_all_docs' + getQueryParam(query); + return Helpers.getApiUrl('/' + id + '/_all_docs' + getQueryParam(query)); } }); FauxtonAPI.registerUrls('allDocsSanitized', { server: function (id, query) { id = encodeURIComponent(id); - return app.host + '/' + id + '/_all_docs' + getQueryParam(query); + return Helpers.getServerUrl('/' + id + '/_all_docs' + getQueryParam(query)); }, app: function (id, query) { @@ -61,19 +62,19 @@ FauxtonAPI.registerUrls('allDocsSanitized', { apiurl: function (id, query) { id = encodeURIComponent(id); - return window.location.origin + '/' + id + '/_all_docs' + getQueryParam(query); + return Helpers.getApiUrl('/' + id + '/_all_docs' + getQueryParam(query)); } }); FauxtonAPI.registerUrls('bulk_docs', { server: function (id, query) { - return app.host + '/' + encodeURIComponent(id) + '/_bulk_docs' + getQueryParam(query); + return Helpers.getServerUrl('/' + encodeURIComponent(id) + '/_bulk_docs' + getQueryParam(query)); }, app: function (id, query) { return 'database/' + id + '/_bulk_docs' + getQueryParam(query); }, apiurl: function (id, query) { - return window.location.origin + '/' + id + '/_bulk_docs' + getQueryParam(query); + return Helpers.getApiUrl('/' + id + '/_bulk_docs' + getQueryParam(query)); } }); @@ -85,7 +86,7 @@ FauxtonAPI.registerUrls('revision-browser', { FauxtonAPI.registerUrls('designDocs', { server: function (id, designDoc) { - return app.host + '/' + id + '/' + designDoc + '/_info'; + return Helpers.getServerUrl('/' + id + '/' + designDoc + '/_info'); }, app: function (id, designDoc) { @@ -93,13 +94,13 @@ FauxtonAPI.registerUrls('designDocs', { }, apiurl: function (id, designDoc) { - return window.location.origin + '/' + id + '/' + designDoc + '/_info'; + return Helpers.getApiUrl('/' + id + '/' + designDoc + '/_info'); } }); FauxtonAPI.registerUrls('view', { server: function (database, designDoc, viewName) { - return app.host + '/' + database + '/_design/' + designDoc + '/_view/' + viewName; + return Helpers.getServerUrl('/' + database + '/_design/' + designDoc + '/_view/' + viewName); }, app: function (database, designDoc) { @@ -107,7 +108,7 @@ FauxtonAPI.registerUrls('view', { }, apiurl: function (id, designDoc, viewName) { - return window.location.origin + '/' + id + '/_design/' + designDoc + '/_view/' + viewName; + return Helpers.getApiUrl('/' + id + '/_design/' + designDoc + '/_view/' + viewName); }, edit: function (database, designDoc, indexName) { @@ -128,14 +129,14 @@ FauxtonAPI.registerUrls('document', { if (_.isUndefined(query)) { query = ''; } - return app.host + '/' + database + '/' + doc + query; + return Helpers.getServerUrl('/' + database + '/' + doc + query); }, attachment: function (database, doc, filename, query) { if (_.isUndefined(query)) { query = ''; } - return app.host + '/' + database + '/' + doc + '/' + filename + query; + return Helpers.getServerUrl('/' + database + '/' + doc + '/' + filename + query); }, app: function (database, doc) { @@ -145,10 +146,9 @@ FauxtonAPI.registerUrls('document', { apiurl: function (database, doc) { if (!doc) { // api url for creating a doc with POST - return window.location.origin + '/' + database; + return Helpers.getApiUrl('/' + database); } - - return window.location.origin + '/' + database + '/' + doc; + return Helpers.getApiUrl('/' + database + '/' + doc); }, 'web-index': function (database, doc) { @@ -172,7 +172,7 @@ FauxtonAPI.registerUrls('new', { FauxtonAPI.registerUrls('base', { server: function (database) { - return app.host + '/' + database + '/'; + return Helpers.getServerUrl('/' + database + '/'); }, app: function (database) { @@ -187,7 +187,7 @@ FauxtonAPI.registerUrls('mango', { query = ''; } - return app.host + '/' + db + '/_index' + query; + return Helpers.getServerUrl('/' + db + '/_index' + query); }, 'index-apiurl': function (db, query) { @@ -195,7 +195,7 @@ FauxtonAPI.registerUrls('mango', { query = ''; } - return window.location.origin + '/' + db + '/_index' + query; + return Helpers.getApiUrl('/' + db + '/_index' + query); }, 'index-app': function (db, query) { @@ -207,7 +207,7 @@ FauxtonAPI.registerUrls('mango', { }, 'index-server-bulk-delete': function (db) { - return app.host + '/' + db + '/_index/_bulk_delete'; + return Helpers.getServerUrl('/' + db + '/_index/_bulk_delete'); }, 'query-server': function (db, query) { @@ -215,7 +215,7 @@ FauxtonAPI.registerUrls('mango', { query = ''; } - return app.host + '/' + db + '/_find' + query; + return Helpers.getServerUrl('/' + db + '/_find' + query); }, 'query-apiurl': function (db, query) { @@ -223,7 +223,7 @@ FauxtonAPI.registerUrls('mango', { query = ''; } - return window.location.origin + '/' + db + '/_find' + query; + return Helpers.getApiUrl('/' + db + '/_find' + query); }, 'query-app': function (db, query) { @@ -235,11 +235,11 @@ FauxtonAPI.registerUrls('mango', { }, 'explain-server': function (db) { - return app.host + '/' + db + '/_explain'; + return Helpers.getServerUrl('/' + db + '/_explain'); }, 'explain-apiurl': function (db) { - return window.location.origin + '/' + db + '/_explain'; + return Helpers.getApiUrl('/' + db + '/_explain'); } }); diff --git a/app/addons/documents/doc-editor/__tests__/doc-editor.components.test.js b/app/addons/documents/doc-editor/__tests__/doc-editor.components.test.js index 8f314ba5d..c247e91c3 100644 --- a/app/addons/documents/doc-editor/__tests__/doc-editor.components.test.js +++ b/app/addons/documents/doc-editor/__tests__/doc-editor.components.test.js @@ -137,7 +137,7 @@ describe('DocEditorController', () => { const $attachmentNode = el.find('.view-attachments-section .dropdown-menu li'); const attachmentURLactual = $attachmentNode.find('a').first().prop('href'); - assert.equal(attachmentURLactual, '../../a%2Fspecial%3Fdb/_design%2Ftest%23doc/one%252F.png'); + assert.equal(attachmentURLactual, './a%2Fspecial%3Fdb/_design%2Ftest%23doc/one%252F.png'); }); it.skip('setting deleteDocModal=true in store shows modal', () => { diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js index 4fda5f73d..9f843a5bd 100644 --- a/app/addons/documents/resources.js +++ b/app/addons/documents/resources.js @@ -174,7 +174,7 @@ Documents.BulkDeleteDocCollection = FauxtonAPI.Collection.extend({ Documents.MangoBulkDeleteDocCollection = Documents.BulkDeleteDocCollection.extend({ url: function () { - return app.host + '/' + this.databaseId + '/_index/_bulk_delete'; + return Helpers.getServerUrl(`/${this.databaseId}/_index/_bulk_delete`); }, createPayload: function (documents) { diff --git a/app/addons/documents/rev-browser/actions.js b/app/addons/documents/rev-browser/actions.js index 116af0e13..81af70edb 100644 --- a/app/addons/documents/rev-browser/actions.js +++ b/app/addons/documents/rev-browser/actions.js @@ -23,7 +23,8 @@ PouchDB.plugin(PouchHttpAdapter); let db; export const initDiffEditor = (dbName, docId) => dispatch => { - const url = FauxtonAPI.urls('databaseBaseURL', 'server', dbName); + // We have to use API url here because PouchDB doesn't take relative urls. + const url = FauxtonAPI.urls('databaseBaseURL', 'apiurl', dbName); db = PouchDB(url); Promise.all([db.get(docId), getTree(db, docId)]) diff --git a/app/addons/replication/__tests__/actions.test.js b/app/addons/replication/__tests__/actions.test.js index 929a2c77b..36646a78a 100644 --- a/app/addons/replication/__tests__/actions.test.js +++ b/app/addons/replication/__tests__/actions.test.js @@ -37,7 +37,7 @@ describe("Replication Actions", () => { it('creates a new database if it does not exist', (done) => { const dispatch = () => {}; - fetchMock.postOnce('/_replicator', { + fetchMock.postOnce('./_replicator', { status: 404, body: { error: "not_found", @@ -45,14 +45,14 @@ describe("Replication Actions", () => { } }); - fetchMock.putOnce('/_replicator', { + fetchMock.putOnce('./_replicator', { status: 200, body: { ok: true } }); - const finalPost = fetchMock.postOnce('/_replicator', { + const finalPost = fetchMock.postOnce('./_replicator', { status: 200, body: { ok: true @@ -74,7 +74,7 @@ describe("Replication Actions", () => { //this is not pretty, and might cause some false errors. But its tricky to tell when this test has completed setTimeout(() => { - assert.ok(finalPost.called('/_replicator')); + assert.ok(finalPost.called('./_replicator')); done(); }, 100); }); @@ -131,7 +131,7 @@ describe("Replication Actions", () => { } }; - fetchMock.getOnce('/_replicator/7dcea9874a8fcb13c6630a1547001559', doc); + fetchMock.getOnce('./_replicator/7dcea9874a8fcb13c6630a1547001559', doc); getReplicationStateFrom(doc._id)(dispatch); }); @@ -185,7 +185,7 @@ describe("Replication Actions", () => { } }; - fetchMock.getOnce('/_replicator/rep_custom_auth', docWithCustomAuth); + fetchMock.getOnce('./_replicator/rep_custom_auth', docWithCustomAuth); getReplicationStateFrom(docWithCustomAuth._id)(dispatch); }); }); @@ -224,9 +224,9 @@ describe("Replication Actions", () => { } ]; - fetchMock.getOnce('/_scheduler/jobs', 404); - fetchMock.getOnce('/_replicator/_all_docs?include_docs=true&limit=100', {rows: []}); - fetchMock.postOnce('/_replicator/_bulk_docs', { + fetchMock.getOnce('./_scheduler/jobs', 404); + fetchMock.getOnce('./_replicator/_all_docs?include_docs=true&limit=100', {rows: []}); + fetchMock.postOnce('./_replicator/_bulk_docs', { status: 200, body: resp }); diff --git a/app/addons/replication/__tests__/api.tests.js b/app/addons/replication/__tests__/api.tests.js index 113c75b34..4b39507c9 100644 --- a/app/addons/replication/__tests__/api.tests.js +++ b/app/addons/replication/__tests__/api.tests.js @@ -401,7 +401,7 @@ describe('Replication API', () => { }); it('returns true for support', () => { - fetchMock.getOnce('/_scheduler/jobs', {}); + fetchMock.getOnce('./_scheduler/jobs', {}); return supportNewApi(true) .then(resp => { assert.ok(resp); @@ -409,7 +409,7 @@ describe('Replication API', () => { }); it('returns false for no support', () => { - fetchMock.getOnce('/_scheduler/jobs', { + fetchMock.getOnce('./_scheduler/jobs', { status: 404, body: {error: "missing"} }); @@ -425,7 +425,7 @@ describe('Replication API', () => { describe('setCredentials', () => { it('returns true for support', () => { - fetchMock.getOnce('/_scheduler/jobs', {}); + fetchMock.getOnce('./_scheduler/jobs', {}); return supportNewApi(true) .then(resp => { assert.ok(resp); @@ -433,7 +433,7 @@ describe('Replication API', () => { }); it('returns false for no support', () => { - fetchMock.getOnce('/_scheduler/jobs', { + fetchMock.getOnce('./_scheduler/jobs', { status: 404, body: {error: "missing"} }); @@ -547,8 +547,8 @@ describe('Replication API', () => { }); it("returns parsedReplicationDocs and ignores all design docs", () => { - fetchMock.getOnce('/_scheduler/jobs', 404); - fetchMock.get('/_replicator/_all_docs?include_docs=true&limit=100', _repDocs); + fetchMock.getOnce('./_scheduler/jobs', 404); + fetchMock.get('./_replicator/_all_docs?include_docs=true&limit=100', _repDocs); return supportNewApi(true) .then(fetchReplicationDocs) .then(docs => { @@ -564,9 +564,9 @@ describe('Replication API', () => { }); it("returns parsedReplicationDocs", () => { - fetchMock.getOnce('/_scheduler/jobs', 200); - fetchMock.get('/_replicator/_all_docs?include_docs=true&limit=100', _repDocs); - fetchMock.get('/_scheduler/docs?include_docs=true', _schedDocs); + fetchMock.getOnce('./_scheduler/jobs', 200); + fetchMock.get('./_replicator/_all_docs?include_docs=true&limit=100', _repDocs); + fetchMock.get('./_scheduler/docs?include_docs=true', _schedDocs); return supportNewApi(true) .then(fetchReplicationDocs) .then(docs => { diff --git a/app/addons/replication/actions.js b/app/addons/replication/actions.js index 08e073333..a1d2d3de1 100644 --- a/app/addons/replication/actions.js +++ b/app/addons/replication/actions.js @@ -14,6 +14,7 @@ import FauxtonAPI from '../../core/api'; import {get, post} from '../../core/ajax'; import ActionTypes from './actiontypes'; import Helpers from './helpers'; +import MainHelper from '../../helpers'; import Constants from './constants'; import { supportNewApi, @@ -38,7 +39,8 @@ export const initReplicator = (routeLocalSource, localSource) => dispatch => { }; export const getDatabasesList = () => dispatch => { - get('/_all_dbs') + const url = MainHelper.getServerUrl("/_all_dbs"); + get(url) .then((databases) => { dispatch({ type: ActionTypes.REPLICATION_DATABASES_LOADED, @@ -51,8 +53,8 @@ export const getDatabasesList = () => dispatch => { export const replicate = (params) => dispatch => { const replicationDoc = createReplicationDoc(params); - - const promise = post('/_replicator', replicationDoc); + const url = MainHelper.getServerUrl("/_replicator"); + const promise = post(url, replicationDoc); const source = Helpers.getDatabaseLabel(replicationDoc.source); const target = Helpers.getDatabaseLabel(replicationDoc.target); @@ -211,7 +213,8 @@ export const deleteDocs = (docs) => dispatch => { clear: true }); - post('/_replicator/_bulk_docs', {docs: bulkDocs}, {raw: true}) + const url = MainHelper.getServerUrl('/_replicator/_bulk_docs'); + post(url, {docs: bulkDocs}, {raw: true}) .then(resp => { if (!resp.ok) { throw resp; @@ -326,7 +329,8 @@ export const getReplicationStateFrom = (id) => dispatch => { type: ActionTypes.REPLICATION_FETCHING_FORM_STATE }); - get(`/_replicator/${encodeURIComponent(id)}`) + const url = MainHelper.getServerUrl(`/_replicator/${encodeURIComponent(id)}`); + get(url) .then((doc) => { const stateDoc = { replicationDocName: doc._id, diff --git a/app/addons/replication/api.js b/app/addons/replication/api.js index 363228d82..2ec00f82e 100644 --- a/app/addons/replication/api.js +++ b/app/addons/replication/api.js @@ -13,6 +13,7 @@ import '@webcomponents/url'; import Constants from './constants'; import FauxtonAPI from '../../core/api'; +import Helpers from '../../helpers'; import {get, post, put} from '../../core/ajax'; import base64 from 'base-64'; import _ from 'lodash'; @@ -21,7 +22,8 @@ let newApiPromise = null; export const supportNewApi = (forceCheck) => { if (!newApiPromise || forceCheck) { newApiPromise = new FauxtonAPI.Promise((resolve) => { - get('/_scheduler/jobs', {raw: true}) + const url = Helpers.getServerUrl('/_scheduler/jobs'); + get(url, {raw: true}) .then(resp => { if (resp.status > 202) { return resolve(false); @@ -298,7 +300,8 @@ export const combineDocsAndScheduler = (docs, schedulerDocs) => { export const fetchReplicationDocs = () => { return supportNewApi() .then(newApi => { - const docsPromise = get('/_replicator/_all_docs?include_docs=true&limit=100') + const url = Helpers.getServerUrl('/_replicator/_all_docs?include_docs=true&limit=100'); + const docsPromise = get(url) .then((res) => { if (res.error) { return []; @@ -321,7 +324,8 @@ export const fetchReplicationDocs = () => { }; export const fetchSchedulerDocs = () => { - return get('/_scheduler/docs?include_docs=true') + const url = Helpers.getServerUrl('/_scheduler/docs?include_docs=true'); + return get(url) .then((res) => { if (res.error) { return []; @@ -333,7 +337,8 @@ export const fetchSchedulerDocs = () => { export const checkReplicationDocID = (docId) => { return new Promise((resolve) => { - get(`/_replicator/${docId}`) + const url = Helpers.getServerUrl(`/_replicator/${docId}`); + get(url) .then(resp => { if (resp.error === "not_found") { resolve(false); @@ -369,7 +374,8 @@ export const fetchReplicateInfo = () => { return []; } - return get('/_scheduler/jobs') + const url = Helpers.getServerUrl('/_scheduler/jobs'); + return get(url) .then(resp => { return parseReplicateInfo(resp); }); @@ -382,15 +388,16 @@ export const deleteReplicatesApi = (replicates) => { replication_id: replicate._id, cancel: true }; - - return post('/_replicate', data); + const url = Helpers.getServerUrl('/_replicate'); + return post(url, data); }); return FauxtonAPI.Promise.all(promises); }; export const createReplicatorDB = () => { - return put('/_replicator') + const url = Helpers.getServerUrl('/_replicator'); + return put(url) .then(res => { if (!res.ok) { throw {reason: 'Failed to create the _replicator database.'}; diff --git a/app/addons/replication/base.js b/app/addons/replication/base.js index e4b966b5a..951a335a7 100644 --- a/app/addons/replication/base.js +++ b/app/addons/replication/base.js @@ -11,6 +11,7 @@ // the License. import FauxtonAPI from '../../core/api'; +import Helpers from "../../helpers"; import replication from './route'; import './assets/less/replication.less'; import { checkForNewApi } from './actions'; @@ -29,7 +30,7 @@ FauxtonAPI.addReducers({ FauxtonAPI.registerUrls('replication', { app: (db) => '#/replication/_create/' + db, - api: () => window.location.origin + '/_replicator' + api: () => Helpers.getApiUrl('/_replicator') }); export default replication; diff --git a/app/addons/verifyinstall/resources.js b/app/addons/verifyinstall/resources.js index 569066079..0c9f6896b 100644 --- a/app/addons/verifyinstall/resources.js +++ b/app/addons/verifyinstall/resources.js @@ -10,8 +10,8 @@ // License for the specific language governing permissions and limitations under // the License. -import app from "../../app"; import FauxtonAPI from "../../core/api"; +import Helpers from "../../helpers"; import { get, post } from "../../core/ajax"; import Databases from "../databases/resources"; import Documents from "../documents/resources"; @@ -125,7 +125,7 @@ Verifyinstall.testProcess = { target: 'verifytestdb_replicate' }; return post( - app.host + '/_replicate', + Helpers.getServerUrl('/_replicate'), body ).then(res => { if (res.error) { diff --git a/app/app.js b/app/app.js index 260c0ae96..6c3916040 100644 --- a/app/app.js +++ b/app/app.js @@ -26,16 +26,6 @@ if (_.isUndefined(console)) { }; } -// make sure we have location.origin -if (_.isUndefined(window.location.origin)) { - var port = ''; - if (window.location.port) { - port = ':' + window.location.port; - } - window.location.origin = window.location.protocol + '//' + - window.location.hostname + port; -} - // Provide a global location to place configuration settings and module // creation also mix in Backbone.Events Object.assign(app, { diff --git a/app/constants.js b/app/constants.js index 5fd260b3c..66fdc2e96 100644 --- a/app/constants.js +++ b/app/constants.js @@ -9,7 +9,6 @@ // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. - export default { MISC: { @@ -29,24 +28,24 @@ export default { // documentation URLs DOC_URLS: { - GENERAL: '/_utils/docs/intro/api.html#documents', - ALL_DBS: '/_utils/docs/api/server/common.html?highlight=all_dbs#get--_all_dbs', - REPLICATION: '/_utils/docs/replication/replicator.html#basics', - DESIGN_DOCS: '/_utils/docs/ddocs/ddocs.html#design-docs', - DESIGN_DOC_METADATA: '/_utils/docs/api/ddoc/common.html#api-ddoc-view-index-info', - VIEW_FUNCS: '/_utils/docs/ddocs/ddocs.html#view-functions', - MAP_FUNCS: '/_utils/docs/ddocs/ddocs.html#map-functions', - REDUCE_FUNCS: '/_utils/docs/ddocs/ddocs.html#reduce-and-rereduce-functions', - API_REF: '/_utils/docs/http-api.html', - DB_PERMISSION: '/_utils/docs/api/database/security.html#db-security', - STATS: '/_utils/docs/api/server/common.html?highlight=stats#get--_stats', - ACTIVE_TASKS: '/_utils/docs/api/server/common.html?highlight=stats#active-tasks', - LOG: '/_utils/docs/api/server/common.html?highlight=stats#log', - CONFIG: '/_utils/docs/config/index.html', - VIEWS: '/_utils/docs/intro/overview.html#views', - MANGO_INDEX: '/_utils/docs/intro/api.html#documents', - MANGO_SEARCH: '/_utils/docs/intro/api.html#documents', - SETUP: '/_utils/docs/cluster/setup.html#the-cluster-setup-wizard', - CHANGES: '/_utils/docs/api/database/changes.html?highlight=changes#post--db-_changes' + GENERAL:'./docs/intro/api.html#documents', + ALL_DBS:'./docs/api/server/common.html?highlight=all_dbs#get--_all_dbs', + REPLICATION:'./docs/replication/replicator.html#basics', + DESIGN_DOCS:'./docs/ddocs/ddocs.html#design-docs', + DESIGN_DOC_METADATA:'./docs/api/ddoc/common.html#api-ddoc-view-index-info', + VIEW_FUNCS:'./docs/ddocs/ddocs.html#view-functions', + MAP_FUNCS:'./docs/ddocs/ddocs.html#map-functions', + REDUCE_FUNCS:'./docs/ddocs/ddocs.html#reduce-and-rereduce-functions', + API_REF:'./docs/http-api.html', + DB_PERMISSION:'./docs/api/database/security.html#db-security', + STATS:'./docs/api/server/common.html?highlight=stats#get--_stats', + ACTIVE_TASKS:'./docs/api/server/common.html?highlight=stats#active-tasks', + LOG:'./docs/api/server/common.html?highlight=stats#log', + CONFIG:'./docs/config/index.html', + VIEWS:'./docs/intro/overview.html#views', + MANGO_INDEX:'./docs/intro/api.html#documents', + MANGO_SEARCH:'./docs/intro/api.html#documents', + CHANGES:'./docs/api/database/changes.html?highlight=changes#post--db-_changes', + SETUP: './docs/cluster/setup.html#the-cluster-setup-wizard' } }; diff --git a/app/helpers.js b/app/helpers.js index 0b49194f0..ed2513078 100644 --- a/app/helpers.js +++ b/app/helpers.js @@ -17,11 +17,12 @@ // want to change this later, but for now this should be thought of as a // "purely functional" helper system. -import app from "./app"; import constants from "./constants"; -import { get } from "./core/ajax"; +import app from "./initialize"; import utils from "./core/utils"; import moment from "moment"; +import url from "url"; +import {get} from "./core/ajax"; import _ from 'lodash'; var Helpers = {}; @@ -63,6 +64,25 @@ Helpers.escapeJQuerySelector = function (selector) { return selector && selector.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&"); }; +Helpers.getApiUrl = endpointRoute => { + if (app.host.endsWith('/') && endpointRoute.startsWith("/")) { + endpointRoute = endpointRoute.substr(1); + } + return url.resolve(window.location.href, app.host + endpointRoute); +}; + +Helpers.getServerUrl = endpointRoute => { + if (app.host.endsWith('/') && endpointRoute.startsWith("/")) { + endpointRoute = endpointRoute.substr(1); + } + return app.host + endpointRoute; +}; + +Helpers.getUUID = function (count = 1) { + const url = Helpers.getServerUrl(`/_uuids?count=${count}`); + return get(url); +}; + /** * Determine if the current application is running on IE10 or IE11 * @returns {boolean} True if on IE10 or IE11. Otherwise false. @@ -71,9 +91,4 @@ Helpers.isIE1X = function() { return document.documentMode == 11 || document.documentMode == 10; }; -Helpers.getUUID = function (count = 1) { - const url = `${app.host}/_uuids?count=${count}`; - return get(url); -}; - export default Helpers; diff --git a/jest-setup.js b/jest-setup.js index 870b7f8e5..47c726066 100644 --- a/jest-setup.js +++ b/jest-setup.js @@ -39,6 +39,11 @@ Object.defineProperty(window.location, 'origin', { value: 'http://dev:8000' }); +Object.defineProperty(window.location, 'href', { + writable: true, + value: 'http://dev:8000' +}); + // Setup enzyme's react adapter const Enzyme = require('enzyme'); const EnzymeAdapter = require('enzyme-adapter-react-16'); diff --git a/settings.json.default.json b/settings.json.default.json index 9a5e8adc0..31935fbf8 100644 --- a/settings.json.default.json +++ b/settings.json.default.json @@ -27,7 +27,7 @@ }, "app": { "root": "/", - "host": "../..", + "host": "./", "version": "1.0.dev" } }, @@ -42,7 +42,7 @@ }, "app": { "root": "/", - "host": "../..", + "host": "../", "version": "1.0" } },