133 lines
3.3 KiB
TypeScript
133 lines
3.3 KiB
TypeScript
// 网络管理:智能检测内外网
|
||
|
||
// 判断是否为内网IP地址
|
||
function isInternalIP(hostname: string): boolean {
|
||
// 如果是localhost
|
||
if (hostname === 'localhost' || hostname === '127.0.0.1') {
|
||
return true
|
||
}
|
||
|
||
// 判断是否为内网IP段
|
||
// 10.0.0.0 - 10.255.255.255
|
||
// 172.16.0.0 - 172.31.255.255
|
||
// 192.168.0.0 - 192.168.255.255
|
||
const ipv4Regex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
|
||
const match = hostname.match(ipv4Regex)
|
||
|
||
if (match) {
|
||
const [, a, b] = match.map(Number)
|
||
|
||
// 10.x.x.x
|
||
if (a === 10) return true
|
||
|
||
// 172.16.x.x - 172.31.x.x
|
||
if (a === 172 && b >= 16 && b <= 31) return true
|
||
|
||
// 192.168.x.x
|
||
if (a === 192 && b === 168) return true
|
||
}
|
||
|
||
return false
|
||
}
|
||
|
||
function getCurrentHost(): string {
|
||
if (typeof window === 'undefined') return ''
|
||
return window.location.host
|
||
}
|
||
|
||
function getCurrentHostname(): string {
|
||
if (typeof window === 'undefined') return ''
|
||
return window.location.hostname
|
||
}
|
||
|
||
export interface NetworkStatus {
|
||
isInternal: boolean
|
||
host: string
|
||
}
|
||
|
||
let currentNetwork: NetworkStatus | null = null
|
||
|
||
// 初始化网络检测(优先使用后端API获取准确状态)
|
||
export async function initializeNetwork(): Promise<NetworkStatus> {
|
||
if (typeof window === 'undefined') {
|
||
return { isInternal: false, host: '' }
|
||
}
|
||
|
||
// 如果已经检测过,直接返回缓存结果
|
||
if (currentNetwork) {
|
||
return currentNetwork
|
||
}
|
||
|
||
const host = getCurrentHost()
|
||
const hostname = getCurrentHostname()
|
||
|
||
// 优先调用后端API获取准确的网络状态(后端可以通过请求头获取真实的客户端IP)
|
||
try {
|
||
const response = await fetch('/api/network-status', {
|
||
cache: 'no-store', // 不缓存,确保获取最新状态
|
||
})
|
||
|
||
if (response.ok) {
|
||
const data = await response.json()
|
||
if (data.success) {
|
||
currentNetwork = {
|
||
isInternal: data.isIntranet,
|
||
host
|
||
}
|
||
|
||
// 不输出IP和Hostname信息,避免在浏览器控制台暴露内网信息
|
||
if (data.isIntranet) {
|
||
console.log(`✅ 检测到内网访问`)
|
||
} else {
|
||
console.log(`🌐 检测到公网访问`)
|
||
}
|
||
|
||
return currentNetwork
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.warn('后端网络检测失败,使用前端判断:', error)
|
||
}
|
||
|
||
// 如果后端API调用失败,回退到前端判断(基于hostname)
|
||
const isInternal = isInternalIP(hostname)
|
||
currentNetwork = {
|
||
isInternal,
|
||
host
|
||
}
|
||
|
||
// 不输出hostname信息,避免在浏览器控制台暴露内网信息
|
||
if (isInternal) {
|
||
console.log(`✅ 检测到内网访问`)
|
||
} else {
|
||
console.log(`🌐 检测到公网访问`)
|
||
}
|
||
|
||
return currentNetwork
|
||
}
|
||
|
||
// 获取当前网络状态
|
||
export function getNetworkStatus(): NetworkStatus {
|
||
if (!currentNetwork) {
|
||
const host = getCurrentHost()
|
||
const hostname = getCurrentHostname()
|
||
const isInternal = isInternalIP(hostname)
|
||
return { isInternal, host }
|
||
}
|
||
return currentNetwork
|
||
}
|
||
|
||
// 获取API基础URL
|
||
export function getApiBaseUrl(): string {
|
||
if (!currentNetwork) {
|
||
return '' // 使用相对路径
|
||
}
|
||
return currentNetwork.isInternal ? `http://${currentNetwork.host}` : ''
|
||
}
|
||
|
||
// 清除缓存(用于刷新网络状态)
|
||
export function clearNetworkCache() {
|
||
currentNetwork = null
|
||
}
|
||
|