mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
refactor(api): tidy the api and shared packages (#2733)
This commit is contained in:
1 parent
580401d2dc
commit
5afbf67a70
333 files changed
+10180
-7910
No files matched your search
@@ -52,31 +52,11 @@ function toStringHeaderValue(value: string | Array<string> | null | undefined):
|
||||
return typeof value === 'string' ? value : null;
|
||||
}
|
||||
|
||||
function parseSingleIpValue(value: string): ParsedIpAddress | null {
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
return parseIpAddress(trimmed);
|
||||
}
|
||||
|
||||
function parseClientIpHeaderValue(value: string | null): ParsedIpAddress | null {
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
const [firstHop] = value.split(',');
|
||||
if (firstHop === undefined) {
|
||||
return null;
|
||||
}
|
||||
return parseSingleIpValue(firstHop);
|
||||
}
|
||||
|
||||
function createRequestHeaderReader(request: Request): HeaderReader {
|
||||
return {
|
||||
get: (name: string): string | null => {
|
||||
return request.headers.get(name);
|
||||
},
|
||||
};
|
||||
return parseIpAddress(value.split(',', 1)[0]);
|
||||
}
|
||||
|
||||
function getHeaderValue(headers: HeadersLike, name: string): string | null {
|
||||
@@ -121,7 +101,7 @@ function extractClientIpDetailsFromReader(
|
||||
}
|
||||
|
||||
export function extractClientIpDetails(req: Request, options?: ClientIpExtractionOptions): ExtractedClientIp | null {
|
||||
return extractClientIpDetailsFromReader(createRequestHeaderReader(req), options);
|
||||
return extractClientIpDetailsFromReader(req.headers, options);
|
||||
}
|
||||
|
||||
export function extractClientIp(req: Request, options?: ClientIpExtractionOptions): string | null {
|
||||
|
||||
@@ -21,6 +21,23 @@ const SAME_IP_DECISION_KEY_OPTIONS: Readonly<IpNetworkKeyOptions> = {
|
||||
ipv6PrefixLength: 64,
|
||||
};
|
||||
|
||||
const RESERVED_IPV4_RANGES: ReadonlyArray<readonly [base: number, prefixLength: number]> = [
|
||||
[0x00000000, 8],
|
||||
[0x0a000000, 8],
|
||||
[0x64400000, 10],
|
||||
[0x7f000000, 8],
|
||||
[0xa9fe0000, 16],
|
||||
[0xac100000, 12],
|
||||
[0xc0000000, 24],
|
||||
[0xc0000200, 24],
|
||||
[0xc0a80000, 16],
|
||||
[0xc6120000, 15],
|
||||
[0xc6336400, 24],
|
||||
[0xcb007100, 24],
|
||||
[0xe0000000, 4],
|
||||
[0xf0000000, 4],
|
||||
];
|
||||
|
||||
function stripIpv6Brackets(value: string): string {
|
||||
if (value.startsWith('[') && value.endsWith(']')) {
|
||||
return value.slice(1, -1);
|
||||
@@ -112,7 +129,7 @@ function expandIpv6ToGroups(address: string): Array<string> {
|
||||
return address.split(':').map((g) => g.padStart(4, '0'));
|
||||
}
|
||||
|
||||
function isIpv4MappedIpv6Groups(groups: Array<string>): boolean {
|
||||
function isIpv4MappedIpv6Groups(groups: ReadonlyArray<string>): boolean {
|
||||
return (
|
||||
groups[0] === '0000' &&
|
||||
groups[1] === '0000' &&
|
||||
@@ -123,7 +140,7 @@ function isIpv4MappedIpv6Groups(groups: Array<string>): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function ipv4FromMappedIpv6Groups(groups: Array<string>): string {
|
||||
function ipv4FromMappedIpv6Groups(groups: ReadonlyArray<string>): string {
|
||||
const hi = parseInt(groups[6], 16);
|
||||
const lo = parseInt(groups[7], 16);
|
||||
const a = (hi >> 8) & 0xff;
|
||||
@@ -237,72 +254,28 @@ function isPublicIpv4Address(address: string): boolean {
|
||||
if (!octets) {
|
||||
return false;
|
||||
}
|
||||
const reservedRanges: Array<[base: number, prefixLength: number]> = [
|
||||
[0x00000000, 8],
|
||||
[0x0a000000, 8],
|
||||
[0x64400000, 10],
|
||||
[0x7f000000, 8],
|
||||
[0xa9fe0000, 16],
|
||||
[0xac100000, 12],
|
||||
[0xc0000000, 24],
|
||||
[0xc0000200, 24],
|
||||
[0xc0a80000, 16],
|
||||
[0xc6120000, 15],
|
||||
[0xc6336400, 24],
|
||||
[0xcb007100, 24],
|
||||
[0xe0000000, 4],
|
||||
[0xf0000000, 4],
|
||||
];
|
||||
return !reservedRanges.some(([base, prefixLength]) => isIpv4InCidr(octets, base, prefixLength));
|
||||
return !RESERVED_IPV4_RANGES.some(([base, prefixLength]) => isIpv4InCidr(octets, base, prefixLength));
|
||||
}
|
||||
|
||||
function getIpv4MappedIpv6(address: string): string | null {
|
||||
const groups = expandIpv6ToGroups(address);
|
||||
function getIpv4MappedIpv6(groups: ReadonlyArray<string>): string | null {
|
||||
if (!isIpv4MappedIpv6Groups(groups)) {
|
||||
return null;
|
||||
}
|
||||
return ipv4FromMappedIpv6Groups(groups);
|
||||
}
|
||||
|
||||
function ipv6GroupValue(group: string): number {
|
||||
return Number.parseInt(group, 16);
|
||||
}
|
||||
|
||||
function isPublicIpv6Address(address: string): boolean {
|
||||
const mappedIpv4 = getIpv4MappedIpv6(address);
|
||||
const groups = expandIpv6ToGroups(address);
|
||||
const mappedIpv4 = getIpv4MappedIpv6(groups);
|
||||
if (mappedIpv4) {
|
||||
return isPublicIpv4Address(mappedIpv4);
|
||||
}
|
||||
const groups = expandIpv6ToGroups(address);
|
||||
const first = ipv6GroupValue(groups[0]);
|
||||
const second = ipv6GroupValue(groups[1]);
|
||||
const last = ipv6GroupValue(groups[7]);
|
||||
const isUnspecifiedOrLoopback = groups.slice(0, 7).every((group) => group === '0000') && (last === 0 || last === 1);
|
||||
if (isUnspecifiedOrLoopback) {
|
||||
return false;
|
||||
}
|
||||
const first = Number.parseInt(groups[0], 16);
|
||||
const second = Number.parseInt(groups[1], 16);
|
||||
if ((first & 0xe000) !== 0x2000) {
|
||||
return false;
|
||||
}
|
||||
if ((first & 0xffc0) === 0xfe80) {
|
||||
return false;
|
||||
}
|
||||
if ((first & 0xfe00) === 0xfc00) {
|
||||
return false;
|
||||
}
|
||||
if ((first & 0xff00) === 0xff00) {
|
||||
return false;
|
||||
}
|
||||
if (first === 0x2001 && second === 0x0db8) {
|
||||
return false;
|
||||
}
|
||||
if (first === 0x0064 && second === 0xff9b) {
|
||||
return false;
|
||||
}
|
||||
if (first === 0x0100 && second === 0x0000) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return first !== 0x2001 || second !== 0x0db8;
|
||||
}
|
||||
|
||||
export function isPublicIpAddress(ip: string): boolean {
|
||||
@@ -332,11 +305,11 @@ export function isLoopbackIpAddress(ip: string): boolean {
|
||||
if (parsed.family === 'ipv4') {
|
||||
return isLoopbackIpv4Address(parsed.normalized);
|
||||
}
|
||||
const mappedIpv4 = getIpv4MappedIpv6(parsed.normalized);
|
||||
const groups = expandIpv6ToGroups(parsed.normalized);
|
||||
const mappedIpv4 = getIpv4MappedIpv6(groups);
|
||||
if (mappedIpv4) {
|
||||
return isLoopbackIpv4Address(mappedIpv4);
|
||||
}
|
||||
const groups = expandIpv6ToGroups(parsed.normalized);
|
||||
return groups.length === 8 && groups.slice(0, 7).every((group) => group === '0000') && groups[7] === '0001';
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user