Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use <base> and config webpack at runtime to allow path prefix #198

Merged
merged 2 commits into from
Mar 21, 2018
Merged
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
File renamed without changes.
2 changes: 1 addition & 1 deletion config-overrides.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const rewireLess = require('react-app-rewire-less');
const lessToJs = require('less-vars-to-js');

// Read the less file in as string
const loadedVarOverrides = fs.readFileSync('config-overrides-ant-variables.less', 'utf8');
const loadedVarOverrides = fs.readFileSync('config-overrides-antd-vars.less', 'utf8');

// Pass in file contents
const modifyVars = lessToJs(loadedVarOverrides);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"xfwd": true
}
},
"homepage": null,
"homepage": ".",
"devDependencies": {
"babel-eslint": "^7.2.3",
"babel-plugin-import": "^1.6.3",
Expand Down
3 changes: 3 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />

<!-- NOTE: The document MUST have a <base> element. package.json#homepage is set to "." as part of resolving https://github.com/jaegertracing/jaeger-ui/issues/42 and therefore static assets are linked via relative URLs. This will break on many document URLs, e.g. /trace/abc, unless a valid base URL is provided. The base href defaults to "/" but the query-service can inject an override. -->
<base href="/" data-inject-target="BASE_URL" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>Jaeger UI</title>
<script>
Expand Down
18 changes: 0 additions & 18 deletions src/api/jaeger.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,4 @@ const JaegerAPI = {
},
};

/* istanbul ignore next */
function getMock(fnName, ...rest) {
return new Promise(resolve => {
require.ensure(['../demo/jaeger-mock'], require => {
resolve(require('../demo/jaeger-mock').default[fnName](...rest));
});
});
}

/* istanbul ignore if */
if (process.env.REACT_APP_DEMO === 'true') {
Object.keys(JaegerAPI).forEach(key => {
if (typeof JaegerAPI[key] === 'function') {
JaegerAPI[key] = (...args) => getMock(key, ...args);
}
});
}

export default JaegerAPI;
5 changes: 5 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// site-prefix.js must be the first import of the main webpack entrypoint
// becaue it configures the webpack publicPath.
/* eslint-disable import/first */
import './site-prefix';

import React from 'react';
import ReactDOM from 'react-dom';
import { document } from 'global';
Expand Down
29 changes: 29 additions & 0 deletions src/site-prefix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2018 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Per the resolution of https://github.com/jaegertracing/jaeger-ui/issues/42,
// package.json#homepage is set to "." and the document MUST have a <base>
// element to define a usable base URL.
const baseNode = document.querySelector('base');
if (!baseNode && process.env.NODE_ENV !== 'test') {
throw new Error('<base> element not found');
}
const sitePrefix = baseNode ? baseNode.href : `${global.location.origin}/`;

// Configure the webpack publicPath to match the <base>:
// https://webpack.js.org/guides/public-path/#on-the-fly
// eslint-disable-next-line camelcase
window.__webpack_public_path__ = sitePrefix;

export default sitePrefix;
41 changes: 13 additions & 28 deletions src/utils/prefix-url.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,29 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import { homepage } from '../../package.json';

// strip the domain, first slash and trailing slash (if present)
const rx = new RegExp('^(?:https?://[^/]+)?/?(.*?)/?$', 'i');
let prefix = '';
import sitePrefix from '../site-prefix';

const origin = process.env.NODE_ENV === 'test' ? global.location.origin : window.location.origin;
/**
* Generate the URL prefix from `value` and use it for all subsequent calls to
* `prefixUrl()`. All of the following `value` parameters result in the prefix
* `"/some/prefix"` (although, the first is the preferred form).
*
* - `"/some/prefix"`
* - `"some/prefix"`
* - `"/some/prefix/"`
* - `"http://my.example.com/some/prefix"`
* - `"https://my.example.com/some/prefix/"`
*
* Note: This function has a side effect of setting the default URL prefix
* applied via the file's default explort.
* Generate the URL prefix from `sitePrefix` and use it for all subsequent calls
* to `prefixUrl()`. `sitePrefix` should be an absolute URL, e.g. with an origin.
* `pathPrefix` is just the path portion and should not have a trailing slash:
*
* @param {?string} value The value to derive the URL prefix from.
* @return {string} The resultant prefix.
* - `"http://localhost:3000/"` to `""`
* - `"http://localhost:3000/abc/"` to `"/abc"`
* - `"http://localhost:3000/abc/def/"` to `"/abc/def"`
*/
export function deriveAndSetPrefix(value) {
prefix = value ? value.replace(rx, '/$1') : '';
return prefix;
}

deriveAndSetPrefix(homepage);
const rx = new RegExp(`^${origin}|/$`, 'ig');
const pathPrefix = sitePrefix.replace(rx, '');

/**
* Add the URL prefix, derived from `homepage` in `package.json`, to the URL
* argument. The domain is stripped from `homepage` before being added.
* Add the path prefix to the URL. See [site-prefix.js](../site-prefix.js) and
* the `<base>` tag in [index.html](../../public/index.html) for details.
*
* @param {string} value The URL to have the prefix added to.
* @return {string} The resultant URL.
*/
export default function prefixUrl(value) {
const s = value == null ? '' : String(value);
return prefix + s;
return `${pathPrefix}${s}`;
}
39 changes: 12 additions & 27 deletions src/utils/prefix-url.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import prefixUrl, { deriveAndSetPrefix } from './prefix-url';
/* eslint-disable import/first */

describe('deriveAndSetPrefix()', () => {
const targetPrefix = '/some/prefix';
const homepages = [
'/some/prefix',
'some/prefix',
'/some/prefix/',
'http://my.example.com/some/prefix',
'https://my.example.com/some/prefix/',
];
jest.mock('../site-prefix', () => `${global.location.origin}/a/site/prefix/`);

homepages.forEach(s => {
it(`parses "${s}" correctly`, () => {
expect(deriveAndSetPrefix(s)).toBe(targetPrefix);
});
});
});
import prefixUrl from './prefix-url';

describe('prefixUrl()', () => {
beforeAll(() => {
deriveAndSetPrefix('/some/prefix');
});
const PATH_PREFIX = '/a/site/prefix';

describe('prefixUrl()', () => {
const tests = [
{ source: undefined, target: '/some/prefix' },
{ source: null, target: '/some/prefix' },
{ source: '', target: '/some/prefix' },
{ source: '/', target: '/some/prefix/' },
{ source: '/a', target: '/some/prefix/a' },
{ source: '/a/', target: '/some/prefix/a/' },
{ source: '/a/b', target: '/some/prefix/a/b' },
{ source: undefined, target: PATH_PREFIX },
{ source: null, target: PATH_PREFIX },
{ source: '', target: PATH_PREFIX },
{ source: '/', target: `${PATH_PREFIX}/` },
{ source: '/a', target: `${PATH_PREFIX}/a` },
{ source: '/a/', target: `${PATH_PREFIX}/a/` },
{ source: '/a/b', target: `${PATH_PREFIX}/a/b` },
];

tests.forEach(({ source, target }) => {
Expand Down