Repository navigation
refactor(client): Meteor-less absoluteUrl()
#40324
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
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
dcf0b5e
refactor(client): fork `absoluteUrl` from Meteor codebase
tassoevan 6d8deae
refactor(client): replace references to `Meteor.absoluteUrl`
tassoevan a7fe5ad
chore(client): add remark
tassoevan 37cd256
chore(lint): fix ESLint misbehaving
tassoevan c2e3f66
refactor(client): use more specific default options initialization
tassoevan fcaa621
test(client): adapt unit tests
tassoevan 98dca7a
Merge branch 'develop' into refactor/meteorless-absolute-url
tassoevan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| import { absoluteUrl, _relativeToSiteRootUrl } from './absoluteUrl'; | ||
|
|
||
| jest.mock('./baseURI', () => ({ | ||
| baseURI: 'http://localhost:3000/', | ||
| })); | ||
|
|
||
| beforeEach(() => { | ||
| absoluteUrl.defaultOptions = { rootUrl: 'http://localhost:3000/' }; | ||
| }); | ||
|
|
||
| describe('absoluteUrl', () => { | ||
| it('should return the root URL with a trailing slash when no path is given', () => { | ||
| expect(absoluteUrl(undefined, { rootUrl: 'http://example.com' })).toBe('http://example.com/'); | ||
| }); | ||
|
|
||
| it('should append the path to the root URL', () => { | ||
| expect(absoluteUrl('foo/bar', { rootUrl: 'http://example.com' })).toBe('http://example.com/foo/bar'); | ||
| }); | ||
|
|
||
| it('should strip leading slashes from the path', () => { | ||
| expect(absoluteUrl('///foo', { rootUrl: 'http://example.com' })).toBe('http://example.com/foo'); | ||
| }); | ||
|
|
||
| it('should prepend http:// when the rootUrl has no protocol', () => { | ||
| expect(absoluteUrl(undefined, { rootUrl: 'example.com' })).toBe('http://example.com/'); | ||
| }); | ||
|
|
||
| it('should preserve https:// when already present in rootUrl', () => { | ||
| expect(absoluteUrl('path', { rootUrl: 'https://example.com' })).toBe('https://example.com/path'); | ||
| }); | ||
|
|
||
| it('should throw when rootUrl is not provided and defaultOptions.rootUrl is unset', () => { | ||
| absoluteUrl.defaultOptions = {}; | ||
| expect(() => absoluteUrl()).toThrow('Must pass options.rootUrl or set ROOT_URL in the server environment'); | ||
| }); | ||
|
|
||
| it('should use defaultOptions.rootUrl when no rootUrl option is given', () => { | ||
| absoluteUrl.defaultOptions = { rootUrl: 'http://default.example.com' }; | ||
| expect(absoluteUrl('test')).toBe('http://default.example.com/test'); | ||
| }); | ||
|
|
||
| it('should upgrade http to https when secure is true and host is not localhost', () => { | ||
| expect(absoluteUrl('path', { rootUrl: 'http://example.com', secure: true })).toBe('https://example.com/path'); | ||
| }); | ||
|
|
||
| it('should not upgrade to https for localhost when secure is true', () => { | ||
| expect(absoluteUrl('path', { rootUrl: 'http://localhost:3000', secure: true })).toBe('http://localhost:3000/path'); | ||
| }); | ||
|
|
||
| it('should not upgrade to https for 127.0.0.1 when secure is true', () => { | ||
| expect(absoluteUrl('path', { rootUrl: 'http://127.0.0.1:3000', secure: true })).toBe('http://127.0.0.1:3000/path'); | ||
| }); | ||
|
|
||
| it('should replace localhost with 127.0.0.1 when replaceLocalhost is true', () => { | ||
| expect(absoluteUrl('path', { rootUrl: 'http://localhost:3000', replaceLocalhost: true })).toBe('http://127.0.0.1:3000/path'); | ||
| }); | ||
|
|
||
| it('should not replace localhost when replaceLocalhost is false', () => { | ||
| expect(absoluteUrl('path', { rootUrl: 'http://localhost:3000', replaceLocalhost: false })).toBe('http://localhost:3000/path'); | ||
| }); | ||
|
|
||
| it('should accept options as the first argument when path is omitted', () => { | ||
| expect(absoluteUrl({ rootUrl: 'http://example.com' } as any)).toBe('http://example.com/'); | ||
| }); | ||
|
|
||
| it('should not duplicate trailing slash', () => { | ||
| expect(absoluteUrl(undefined, { rootUrl: 'http://example.com/' })).toBe('http://example.com/'); | ||
| }); | ||
| }); | ||
|
|
||
| describe('_relativeToSiteRootUrl', () => { | ||
| const originalConfig = (globalThis as any).__meteor_runtime_config__; | ||
|
|
||
| afterEach(() => { | ||
| (globalThis as any).__meteor_runtime_config__ = originalConfig; | ||
| }); | ||
|
|
||
| it('should prepend ROOT_URL_PATH_PREFIX to links starting with /', () => { | ||
| (globalThis as any).__meteor_runtime_config__ = { ROOT_URL_PATH_PREFIX: '/subdir' }; | ||
| expect(_relativeToSiteRootUrl('/route')).toBe('/subdir/route'); | ||
| }); | ||
|
|
||
| it('should return the link unchanged when it does not start with /', () => { | ||
| (globalThis as any).__meteor_runtime_config__ = { ROOT_URL_PATH_PREFIX: '/subdir' }; | ||
| expect(_relativeToSiteRootUrl('route')).toBe('route'); | ||
| }); | ||
|
|
||
| it('should return the link unchanged when __meteor_runtime_config__ is not an object', () => { | ||
| delete (globalThis as any).__meteor_runtime_config__; | ||
| expect(_relativeToSiteRootUrl('/route')).toBe('/route'); | ||
| }); | ||
|
|
||
| it('should handle empty ROOT_URL_PATH_PREFIX', () => { | ||
| (globalThis as any).__meteor_runtime_config__ = { ROOT_URL_PATH_PREFIX: '' }; | ||
| expect(_relativeToSiteRootUrl('/route')).toBe('/route'); | ||
| }); | ||
| }); | ||
|
|
||
| describe('defaultOptions', () => { | ||
| it('should initialize rootUrl from baseURI', () => { | ||
| expect(absoluteUrl.defaultOptions.rootUrl).toBe('http://localhost:3000/'); | ||
| }); | ||
|
|
||
| it('should initialize secure from window.isSecureContext', () => { | ||
| expect(absoluteUrl.defaultOptions.secure).toBe(window.isSecureContext); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| // There is a good chance this module may be promoted to root lib/ in the future | ||
|
|
||
| import { baseURI } from './baseURI'; | ||
|
|
||
| type AbsoluteUrlOptions = { | ||
| rootUrl?: string; | ||
| secure?: boolean; | ||
| replaceLocalhost?: boolean; | ||
| }; | ||
|
|
||
| export function absoluteUrl(path?: string, options?: AbsoluteUrlOptions): string { | ||
| if (!options && typeof path === 'object') { | ||
| options = path; | ||
| path = undefined; | ||
| } | ||
|
|
||
| options = { ...absoluteUrl.defaultOptions, ...options }; | ||
|
|
||
| let { rootUrl } = options; | ||
|
|
||
| if (!rootUrl) throw Error('Must pass options.rootUrl or set ROOT_URL in the server environment'); | ||
|
|
||
| if (!/^http[s]?:\/\//i.test(rootUrl)) { | ||
| rootUrl = `http://${rootUrl}`; | ||
| } | ||
|
|
||
| if (!rootUrl.endsWith('/')) { | ||
| rootUrl += '/'; | ||
| } | ||
|
|
||
| if (path) { | ||
| while (path.startsWith('/')) path = path.slice(1); | ||
| rootUrl += path; | ||
| } | ||
|
|
||
| if (options.secure && /^http:/.test(rootUrl) && !/http:\/\/localhost[:/]/.test(rootUrl) && !/http:\/\/127\.0\.0\.1[:/]/.test(rootUrl)) { | ||
| rootUrl = rootUrl.replace(/^http:/, 'https:'); | ||
| } | ||
|
|
||
| if (options.replaceLocalhost) { | ||
| rootUrl = rootUrl.replace(/^http:\/\/localhost([:/].*)/, 'http://127.0.0.1$1'); | ||
| } | ||
|
|
||
| return rootUrl; | ||
| } | ||
|
|
||
| absoluteUrl.defaultOptions = { | ||
| rootUrl: baseURI, | ||
| secure: window.isSecureContext, | ||
| } as AbsoluteUrlOptions; | ||
|
|
||
| export function _relativeToSiteRootUrl(link: string): string { | ||
| if (typeof __meteor_runtime_config__ === 'object' && link.slice(0, 1) === '/') { | ||
| link = (__meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '') + link; | ||
| } | ||
|
|
||
| return link; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,8 @@ | ||
| import { Meteor } from 'meteor/meteor'; | ||
|
|
||
| import { baseURI } from '../../lib/baseURI'; | ||
| import { _relativeToSiteRootUrl, absoluteUrl } from '../../lib/absoluteUrl'; | ||
|
|
||
| Meteor.absoluteUrl.defaultOptions.rootUrl = baseURI; | ||
| Object.assign(Meteor, { | ||
| absoluteUrl, | ||
| _relativeToSiteRootUrl, | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,12 @@ | ||
| import { useSetting } from '@rocket.chat/ui-contexts'; | ||
| import { Meteor } from 'meteor/meteor'; | ||
| import { useEffect } from 'react'; | ||
|
|
||
| import { absoluteUrl } from '../../../lib/absoluteUrl'; | ||
|
|
||
| export const useCorsSSLConfig = () => { | ||
| const forceSSlSetting = useSetting('Force_SSL'); | ||
|
|
||
| useEffect(() => { | ||
| Meteor.absoluteUrl.defaultOptions.secure = Boolean(forceSSlSetting); | ||
| absoluteUrl.defaultOptions.secure = Boolean(forceSSlSetting); | ||
| }, [forceSSlSetting]); | ||
| }; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.