Merge pull request #739 from thornbill/protocol-and-port

Use url exclusively when protocol & port specified
This commit is contained in:
Bill Thornton 2024-07-10 14:59:34 -04:00 committed by GitHub
commit 918ef7ccc4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 6 deletions

View File

@ -33,12 +33,26 @@ describe('Address Candidates', () => {
});
it('should use the specified port when provided', () => {
const candidates = getAddressCandidates('http://example.com:8888');
const candidates = getAddressCandidates('example.com:8888');
expect(candidates).toHaveLength(2);
expect(candidates[0]).toBe('https://example.com:8888/');
expect(candidates[1]).toBe('http://example.com:8888/');
});
it('should return a single candidate when protocol and port are specified', () => {
let candidates = getAddressCandidates('https://example.com:443');
expect(candidates).toHaveLength(1);
expect(candidates[0]).toBe('https://example.com/');
candidates = getAddressCandidates('http://example.com:80');
expect(candidates).toHaveLength(1);
expect(candidates[0]).toBe('http://example.com/');
candidates = getAddressCandidates('http://example.com:8096');
expect(candidates).toHaveLength(1);
expect(candidates[0]).toBe('http://example.com:8096/');
});
it('should return an empty list for urls with non http(s) protocols', () => {
const candidates = getAddressCandidates('ftp://example.com');
expect(candidates).toHaveLength(0);

View File

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { HTTPS_PORT, HTTP_PORT, HTTP_PROTOCOL, HTTPS_PROTOCOL, parseUrl, copyUrl, getDefaultPort } from './url';
import { HTTPS_PORT, HTTP_PORT, HTTP_PROTOCOL, HTTPS_PROTOCOL, parseUrl, copyUrl, getDefaultPort, hasProtocolAndPort } from './url';
/** The default http port for Jellyfin servers. */
export const JF_HTTP_PORT = 8096;
@ -54,14 +54,23 @@ export function getAddressCandidates(input: string): Array<string> {
try {
const url = parseUrl(input);
// If the input specifies the protocol and port return it directly
if (hasProtocolAndPort(input, url)) {
return [ url.toString() ];
}
// Add the parsed url as a candidate
candidates.push(url);
// Always try https if http is specified
if (url.protocol === HTTP_PROTOCOL) {
const copy = copyUrl(url);
copy.protocol = HTTPS_PROTOCOL;
candidates.push(copy);
}
// Add candidates with JF default ports for candidates using the protocol default port
candidates
.filter(val => !val.port || val.port === getDefaultPort(val.protocol).toString())
.forEach(val => {
@ -79,9 +88,11 @@ export function getAddressCandidates(input: string): Array<string> {
}
});
return candidates
.sort((a, b) => getScore(b) - getScore(a))
.map(candidate => candidate.toString());
// Sort by score
candidates.sort((a, b) => getScore(b) - getScore(a));
// Return the list of candidate urls as strings
return candidates.map(candidate => candidate.toString());
} catch (err) {
console.warn(err);
return [];

View File

@ -6,7 +6,7 @@
import { describe, it, expect } from 'vitest';
import { getDefaultPort, HTTP_PORT, HTTPS_PORT, HTTPS_PROTOCOL, HTTP_PROTOCOL, copyUrl, parseUrl } from '..';
import { getDefaultPort, HTTP_PORT, HTTPS_PORT, HTTPS_PROTOCOL, HTTP_PROTOCOL, copyUrl, parseUrl, hasProtocolAndPort } from '..';
/**
* Url tests.
@ -40,6 +40,26 @@ describe('Url', () => {
});
});
describe('hasProtocolAndPort()', () => {
it('should return true if the protocol and port are specified', () => {
const urlString = 'https://example.com:443';
const url = parseUrl(urlString);
expect(hasProtocolAndPort(urlString, url)).toBe(true);
});
it('should return false if the port is not specified', () => {
const urlString = 'https://example.com';
const url = parseUrl(urlString);
expect(hasProtocolAndPort(urlString, url)).toBe(false);
});
it('should return false if the protocol is not specified', () => {
const urlString = 'example.com:443';
const url = parseUrl(urlString);
expect(hasProtocolAndPort(urlString, url)).toBe(false);
});
});
describe('parseUrl()', () => {
it('should parse a url string', () => {
const url = parseUrl('https://example.com');

View File

@ -30,6 +30,20 @@ export function getDefaultPort(protocol: string): number {
throw new Error('Unsupported protocol');
}
/**
* Checks if the url string specifies the protocol and port.
* @param urlString The url string to test.
* @param url The parsed url object.
* @returns True if the the url string includes the protocol and port.
*/
export function hasProtocolAndPort(urlString: string, url: URL): boolean {
// The parsed URL object drops the default port
const port = url.port || getDefaultPort(url.protocol);
return urlString
.toLowerCase()
.startsWith(`${url.protocol}//${url.hostname.toLowerCase()}:${port}`);
}
/**
* Parses a string to a Url object.
* @param input A string representing a url.