mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 01:20:24 +03:00
Ensure generating server IDs work even if server URLs are invalid
This commit is contained in:
parent
645abea72a
commit
b31949b468
3 changed files with 64 additions and 3 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
### Added
|
||||||
|
* [#1360](https://github.com/shlinkio/shlink-web-client/issues/1360) Added ability for server IDs to be generated based on the server name and URL, instead of generating a random UUID.
|
||||||
|
|
||||||
|
This can improve sharing a predefined set of servers cia servers.json, env vars, or simply export and import your servers in some other device, and then be able to share server URLs which continue working.
|
||||||
|
|
||||||
|
All existing servers will keep their generated IDs in existing devices for backwards compatibility, but newly created servers will use the new approach.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
|
||||||
## [4.2.2] - 2024-10-19
|
## [4.2.2] - 2024-10-19
|
||||||
### Added
|
### Added
|
||||||
* *Nothing*
|
* *Nothing*
|
||||||
|
|
|
@ -6,9 +6,23 @@ import type { ServerData, ServersMap, ServerWithId } from '../data';
|
||||||
* in lowercase and replacing invalid URL characters with hyphens.
|
* in lowercase and replacing invalid URL characters with hyphens.
|
||||||
*/
|
*/
|
||||||
function idForServer(server: ServerData): string {
|
function idForServer(server: ServerData): string {
|
||||||
// TODO Handle invalid URLs. If not valid url, use the value as is
|
let urlSegment = server.url;
|
||||||
const url = new URL(server.url);
|
try {
|
||||||
return `${server.name} ${url.host}`.toLowerCase().replace(/[^a-zA-Z0-9-_.~]/g, '-');
|
const { host, pathname } = new URL(urlSegment);
|
||||||
|
urlSegment = host;
|
||||||
|
|
||||||
|
// Remove leading slash from pathname
|
||||||
|
const normalizedPathname = pathname.substring(1);
|
||||||
|
|
||||||
|
// Include pathname in the ID, if not empty
|
||||||
|
if (normalizedPathname.length > 0) {
|
||||||
|
urlSegment = `${urlSegment} ${normalizedPathname}`;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// If the server URL is not valid, use the value as is
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${server.name} ${urlSegment}`.toLowerCase().replace(/[^a-zA-Z0-9-_.~]/g, '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serversListToMap(servers: ServerWithId[]): ServersMap {
|
export function serversListToMap(servers: ServerWithId[]): ServersMap {
|
||||||
|
|
|
@ -39,5 +39,31 @@ describe('index', () => {
|
||||||
expect.objectContaining({ id: 'baz-s.test' }),
|
expect.objectContaining({ id: 'baz-s.test' }),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('includes server paths when not empty', () => {
|
||||||
|
const result = ensureUniqueIds({}, [
|
||||||
|
fromPartial({ name: 'Foo', url: 'https://example.com' }),
|
||||||
|
fromPartial({ name: 'Bar', url: 'https://s.test/some/path' }),
|
||||||
|
fromPartial({ name: 'Baz', url: 'https://s.test/some/other-path-here/123' }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
expect.objectContaining({ id: 'foo-example.com' }),
|
||||||
|
expect.objectContaining({ id: 'bar-s.test-some-path' }),
|
||||||
|
expect.objectContaining({ id: 'baz-s.test-some-other-path-here-123' }),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses server URL verbatim when it is not a valid URL', () => {
|
||||||
|
const result = ensureUniqueIds({}, [
|
||||||
|
fromPartial({ name: 'Foo', url: 'invalid' }),
|
||||||
|
fromPartial({ name: 'Bar', url: 'this is not a URL' }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
expect.objectContaining({ id: 'foo-invalid' }),
|
||||||
|
expect.objectContaining({ id: 'bar-this-is-not-a-url' }),
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue