Skip to content

Commit 13f59f3

Browse files
authored
Merge pull request #13 from bitrise-io/refactor-404-handlers
Refactor 404 handlers
2 parents 740201c + 29d3a97 commit 13f59f3

17 files changed

Lines changed: 190 additions & 79 deletions

File tree

src/js/404.js

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,17 @@
11
import '../css/404.css';
22
import '../css/status.css';
3-
import { detectTopicFromUrl } from './shared/common';
3+
import { handleAppNavigator404 } from './app-navigator/404';
4+
import { handleChangelog404 } from './changelog/404';
5+
import { handleIntegrations404 } from './integrations/404';
6+
import { handleStacks404 } from './stacks/404';
47
import { renderStatus } from './shared/status';
58

69
(async () => {
710
const url = new URL(document.location.href);
8-
const topicSlugId = detectTopicFromUrl(url, 'changelog', 'topic');
9-
if (topicSlugId) {
10-
const changelogProxyAvailable = await fetch('/changelog-proxy')
11-
.then((changelogProxyResponse) => changelogProxyResponse.ok)
12-
.catch(() => false);
13-
if (!changelogProxyAvailable) {
14-
window.location.href = `/changelog/topic?topic=${topicSlugId}`;
15-
}
16-
}
17-
18-
const subpagePath = detectTopicFromUrl(url, 'stacks', 'subpage');
19-
if (subpagePath) {
20-
const stacksProxyAvailable = await fetch('/stacks-proxy')
21-
.then((stacksProxyResponse) => stacksProxyResponse.ok)
22-
.catch(() => false);
23-
if (!stacksProxyAvailable) {
24-
window.location.href = `/stacks/subpage?subpage=${subpagePath}`;
25-
}
26-
}
27-
28-
const stepPath = detectTopicFromUrl(url, 'integrations/steps', 'step');
29-
if (stepPath) {
30-
const integrationsProxyAvailable = await fetch('/integrations-proxy')
31-
.then((integrationsProxyResponse) => integrationsProxyResponse.ok)
32-
.catch(() => false);
33-
if (!integrationsProxyAvailable) {
34-
window.location.href = `/integrations/step?step=${stepPath}`;
35-
}
36-
}
37-
38-
if (url.pathname.match(/^\/resources\/tools\/app-navigator/)) {
39-
const appNavigatorProxyAvailable = await fetch('/resources/tools/app-navigator-proxy')
40-
.then((appNavigatorProxyResponse) => appNavigatorProxyResponse.ok)
41-
.catch(() => false);
42-
if (!appNavigatorProxyAvailable) {
43-
window.location.href = `https://app.bitrise.io${url.pathname}`;
44-
}
45-
}
11+
await handleStacks404(url);
12+
await handleChangelog404(url);
13+
await handleIntegrations404(url);
14+
await handleAppNavigator404(url);
4615
})();
4716

4817
window.addEventListener('load', async () => {

src/js/app-navigator/404.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { APP_NAVIGATOR_FALLBACK_DOMAIN, APP_NAVIGATOR_PATH_PREFIX, APP_NAVIGATOR_PROXY_PATH } from './config';
2+
3+
/**
4+
* Handles a 404 error for the App Navigator by checking if a proxy is available and redirecting if necessary.
5+
* @param {URL} url - The URL that resulted in a 404 error.
6+
* @return {Promise<void>}
7+
*/
8+
export const handleAppNavigator404 = async (url) => {
9+
if (url.pathname.startsWith(APP_NAVIGATOR_PATH_PREFIX)) {
10+
const appNavigatorProxyAvailable = await fetch(APP_NAVIGATOR_PROXY_PATH)
11+
.then((appNavigatorProxyResponse) => appNavigatorProxyResponse.ok)
12+
.catch(() => false);
13+
if (!appNavigatorProxyAvailable) {
14+
window.location.href = `${APP_NAVIGATOR_FALLBACK_DOMAIN}${url.pathname}`;
15+
}
16+
}
17+
};

src/js/app-navigator/config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const APP_NAVIGATOR_PATH_PREFIX = '/resources/tools/app-navigator';
2+
3+
export const APP_NAVIGATOR_PROXY_PATH = '/resources/tools/app-navigator-proxy';
4+
5+
export const APP_NAVIGATOR_FALLBACK_DOMAIN = 'https://app.bitrise.io';

src/js/changelog-topic.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import YouTubeLoader from './changelog/YouTubeLoader';
77
import { detectTopicFromUrl, formatDate, setMetaContent } from './shared/common';
88

99
import '../css/changelog.css';
10+
import { CHANGELOG_PATH_PREFIX, CHANGELOG_SUBPAGE_PARAM_NAME } from './changelog/config';
1011

1112
const tagFactory = new ChangelogTagFactory();
1213
const youTubeLoader = new YouTubeLoader();
@@ -16,7 +17,7 @@ const topicMetaSeparator = document.querySelector('#changelog-topic-meta-separat
1617
topicMetaSeparator.style.display = 'none';
1718

1819
const url = new URL(document.location.href);
19-
const topicSlugId = detectTopicFromUrl(url, 'changelog', 'topic');
20+
const topicSlugId = detectTopicFromUrl(url, CHANGELOG_PATH_PREFIX, CHANGELOG_SUBPAGE_PARAM_NAME);
2021

2122
/** @type {string} */
2223
const apiBase = document.location.hostname.match(/(localhost|127\.0\.0\.1)/) ? '' : 'https://bitrise.io';

src/js/changelog/404.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { handleProxy404 } from '../shared/common';
2+
import {
3+
CHANGELOG_PATH_PREFIX,
4+
CHANGELOG_PROXY_PATH,
5+
CHANGELOG_SUBPAGE_PARAM_NAME,
6+
CHANGELOG_SUBPAGE_PATH_PREFIX,
7+
} from './config';
8+
9+
/**
10+
* Handles a 404 error for the Changelog by checking if a proxy is available and redirecting if necessary.
11+
* @param {URL} url - The URL that resulted in a 404 error.
12+
* @returns {Promise<void>}
13+
*/
14+
export const handleChangelog404 = async (url) =>
15+
handleProxy404(url, {
16+
pathPrefix: CHANGELOG_PATH_PREFIX,
17+
subpageParamName: CHANGELOG_SUBPAGE_PARAM_NAME,
18+
proxyPath: CHANGELOG_PROXY_PATH,
19+
subpagePathPrefix: CHANGELOG_SUBPAGE_PATH_PREFIX,
20+
});

src/js/changelog/ChangelogService.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class ChangelogService {
6060
*/
6161
async loadTopic(topicSlugId) {
6262
const apiBase = await this.getApiBase();
63-
if (topicSlugId.match(/rm-\d+/)) {
63+
if (topicSlugId.match(/^rm-v\d+-.*/)) {
6464
const url = `${apiBase}/changelog.json`;
6565
const response = await fetch(url);
6666
const json = await response.json();

src/js/changelog/ChangelogTopic.js

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,23 @@ class ChangelogTopic {
102102

103103
/** @returns {string} */
104104
get content() {
105-
if (this.data.slug.match(/^rm-/) && this.data.changelog) {
105+
if (this.data.slug.match(/^rm-v\d+-.*/) && this.data.changelog) {
106106
return this.data.changelog
107-
.map(
108-
(changelog) => `
109-
<div class='rmcl'>
110-
<h3>${changelog.operationId}</h3>
111-
<div>
112-
<span class="rmcl-http-method-tag rmcl-http-method-${changelog.operation.toLocaleLowerCase()}">${changelog.operation}</span>
113-
<span class="rmcl-api-endpoint-url">${changelog.path}</span>
114-
</div>
115-
<p>${changelog.text.replaceAll(/'([^']+)'/g, '<span class="rmcl-inline-code">$1</span>')}</p>
116-
</div>
117-
`,
118-
)
107+
.map((changelog) => {
108+
if (changelog.operationId) {
109+
return `<div class='rmcl'>
110+
<h3>${changelog.operationId}</h3>
111+
<div>
112+
<span class="rmcl-http-method-tag rmcl-http-method-${changelog.operation.toLocaleLowerCase()}">${changelog.operation}</span>
113+
<span class="rmcl-api-endpoint-url">${changelog.path}</span>
114+
</div>
115+
<p>${changelog.text.replaceAll(/'([^']+)'/g, '<span class="rmcl-inline-code">$1</span>')}</p>
116+
</div>`;
117+
}
118+
return `<div class='rmcl'>
119+
<p>${changelog.text.replaceAll(/'([^']+)'/g, '<span class="rmcl-inline-code">$1</span>')}</p>
120+
</div>`;
121+
})
119122
.join('');
120123
}
121124
return this.posts.length ? this.posts[0].cooked : '';

src/js/changelog/config.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const CHANGELOG_PATH_PREFIX = '/changelog';
2+
3+
export const CHANGELOG_SUBPAGE_PARAM_NAME = 'topic';
4+
5+
export const CHANGELOG_SUBPAGE_PATH_PREFIX = `/changelog/topic`;
6+
7+
export const CHANGELOG_PROXY_PATH = `/changelog-proxy`;

src/js/integrations.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ import SidebarSection from './integrations/SidebarSection';
44
import { fancyConsoleLog } from './shared/common';
55

66
import '../css/integrations.css';
7+
import {
8+
INTEGRATIONS_PATH_PREFIX,
9+
INTEGRATIONS_PROXY_PATH,
10+
INTEGRATIONS_SUBPAGE_PARAM_NAME,
11+
INTEGRATIONS_SUBPAGE_PATH_PREFIX,
12+
} from './integrations/config';
713

814
const url = new URL(document.location.href);
915
const platformFilter = url.searchParams.get('platform');
@@ -41,13 +47,14 @@ searchField.value = queryFilter;
4147
}, 500);
4248
}
4349

44-
const proxyAvailable = await fetch('/integrations-proxy')
50+
const proxyAvailable = await fetch(INTEGRATIONS_PROXY_PATH)
4551
.then((proxyResponse) => proxyResponse.ok)
4652
.catch(() => false);
4753

4854
if (!proxyAvailable) {
49-
document.querySelectorAll('a[href^="/integrations"]').forEach((link) => {
50-
link.href = `/integrations/step?step=${link.getAttribute('href').replace(/^.*\/integrations\/steps\//, '')}`;
55+
document.querySelectorAll(`a[href^="${INTEGRATIONS_PATH_PREFIX}"]`).forEach((link) => {
56+
const stepKey = link.getAttribute('href').replace(new RegExp(`^.*${INTEGRATIONS_PATH_PREFIX}/`), '');
57+
link.href = `${INTEGRATIONS_SUBPAGE_PATH_PREFIX}?${INTEGRATIONS_SUBPAGE_PARAM_NAME}=${stepKey}`;
5158
});
5259
}
5360

src/js/integrations/404.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { handleProxy404 } from '../shared/common';
2+
import {
3+
INTEGRATIONS_PATH_PREFIX,
4+
INTEGRATIONS_PROXY_PATH,
5+
INTEGRATIONS_SUBPAGE_PARAM_NAME,
6+
INTEGRATIONS_SUBPAGE_PATH_PREFIX,
7+
} from './config';
8+
9+
/**
10+
* Handles a 404 error for the Integrations by checking if a proxy is available and redirecting if necessary.
11+
* @param {URL} url - The URL that resulted in a 404 error.
12+
* @returns {Promise<void>}
13+
*/
14+
export const handleIntegrations404 = async (url) =>
15+
handleProxy404(url, {
16+
pathPrefix: INTEGRATIONS_PATH_PREFIX,
17+
subpageParamName: INTEGRATIONS_SUBPAGE_PARAM_NAME,
18+
proxyPath: INTEGRATIONS_PROXY_PATH,
19+
subpagePathPrefix: INTEGRATIONS_SUBPAGE_PATH_PREFIX,
20+
});

0 commit comments

Comments
 (0)