// ==UserScript== // @name CDN & Server Info Displayer Enhanced (增强版CDN及服务器信息显示) // @name:en CDN & Server Info Displayer Enhanced // @namespace http://tampermonkey.net/ // @version 4.3.0 // @description [v4.3.0 Final Fix] Correctly uses unsafeWindow to detect challenge pages, fixing conflicts definitively. // @description:en [v4.3.0 Final Fix] Correctly uses unsafeWindow to detect challenge pages, fixing conflicts definitively. // @author Gemini // @license MIT // @match *://*/* // @grant GM_addStyle // @run-at document-end // @downloadURL https://update.greasyfork.icu/scripts/538977/CDN%20%20Server%20Info%20Displayer%20Enhanced%20%28%E5%A2%9E%E5%BC%BA%E7%89%88CDN%E5%8F%8A%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BF%A1%E6%81%AF%E6%98%BE%E7%A4%BA%29.user.js // @updateURL https://update.greasyfork.icu/scripts/538977/CDN%20%20Server%20Info%20Displayer%20Enhanced%20%28%E5%A2%9E%E5%BC%BA%E7%89%88CDN%E5%8F%8A%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%BF%A1%E6%81%AF%E6%98%BE%E7%A4%BA%29.meta.js // ==/UserScript== (function() { 'use strict'; // --- Configuration --- const config = { initialPosition: { bottom: '15px', right: '15px' }, panelBgColor: 'rgba(44, 62, 80, 0.95)', panelTextColor: '#ffffff', borderColor: '#3498db', opacity: '0.9', animationDuration: '0.3s', minWindowSize: { width: 400, height: 300 }, execution_delay: 500, excludePatterns: [ /(\/|&)pay(pal|ment)/i, /\/checkout|\/billing/i, /\/login|\/signin|\/auth/i, /\/phpmyadmin/i, /(\/ads\/|ad_id=|advertisement)/i, /doubleclick\.net/i, /facebook\.com\/plugins/i, /twitter\.com\/widgets/i, /\/popup|\/modal/i ] }; // --- Helper function to get cache status --- function getCacheStatus(h) { const headersToCheck = [ h.get('cache-status'), h.get('x-cache-status'), h.get('x-cache'), h.get('x-edge-cache-status'), h.get('x-sucuri-cache'), h.get('x-vercel-cache'), h.get('x-qc-cache'), h.get('cf-cache-status'), h.get('x-response-cache'), h.get('x-bdcdn-cache-status'), h.get('cdn-cache'), h.get('bunny-cache-state') ]; for (const value of headersToCheck) { if (!value) continue; const upperVal = value.toUpperCase(); if (upperVal.includes('HIT')) return 'HIT'; if (upperVal.includes('MISS')) return 'MISS'; if (upperVal.includes('BYPASS')) return 'BYPASS'; if (upperVal.includes('DYNAMIC')) return 'DYNAMIC'; if (upperVal.includes('UPDATING')) return 'UPDATING'; if (upperVal.includes('STALE')) return 'STALE'; if (upperVal.includes('EXPIRED')) return 'EXPIRED'; } if (parseInt(h.get('age'), 10) > 0) return 'HIT (inferred)'; let hitCount = 0; for (const value of h.values()) { if (value.toLowerCase() === 'hit') hitCount++; } if (hitCount >= 3) return 'HIT (inferred)'; return 'N/A'; } // --- CDN Provider Detection Rules --- const cdnProviders = { 'ByteDance Edge': { headers: ['x-tt-trace-tag', 'x-bytefaas-request-id'], priority: 11, getInfo: (h) => { let cache = 'N/A'; const traceTag = h.get('x-tt-trace-tag') || ''; const match = traceTag.match(/cdn-cache=([^;]+)/); if (match && match[1]) cache = match[1].toUpperCase(); else cache = getCacheStatus(h); return { provider: 'ByteDance Edge', cache: cache, pop: 'N/A', extra: `Trace ID: ${h.get('x-tt-logid') || 'N/A'}` }; } }, 'Baidu Cloud CDN': { headers: ['x-bdcdn-cache-status'], priority: 10, getInfo: (h) => ({ provider: 'Baidu Cloud CDN', cache: getCacheStatus(h), pop: 'N/A', extra: `Req ID: ${h.get('x-request-id') || 'N/A'}`}) }, 'Cloudflare': { headers: ['cf-ray'], serverHeaders: ['cloudflare'], priority: 10, getInfo: (h) => ({ provider: 'Cloudflare', cache: h.get('cf-cache-status')?.toUpperCase() || 'N/A', pop: h.get('cf-ray')?.slice(-3).toUpperCase() || 'N/A', extra: `Ray ID: ${h.get('cf-ray') || 'N/A'}` }) }, 'Tencent EdgeOne': { serverHeaders: ['TencentEdgeOne'], headers: ['eo-cache-status'], priority: 10, getInfo: (h) => ({ provider: 'Tencent EdgeOne', cache: h.get('eo-cache-status')?.toUpperCase() || 'N/A', pop: 'N/A', extra: `Log-UUID: ${h.get('eo-log-uuid') || 'N/A'}` }) }, 'Imperva': { headers: ['incap-proxy-id'], priority: 10, getInfo: (h) => ({ provider: 'Imperva', cache: h.get('x-iinfo') ? 'HIT' : getCacheStatus(h), pop: h.get('incap-origin-pop') || h.get('incap-pop') || 'N/A', extra: `Proxy ID: ${h.get('incap-proxy-id')?.split(' ')[0] || 'N/A'}` }) }, 'Sucuri': { headers: ['x-sucuri-id'], priority: 10, getInfo: (h) => ({ provider: 'Sucuri', cache: getCacheStatus(h), pop: 'N/A', extra: `Firewall ID: ${h.get('x-sucuri-id') || 'N/A'}` }) }, 'Netlify': { headers: ['x-nf-request-id'], priority: 10, getInfo: (h) => ({ provider: 'Netlify', cache: getCacheStatus(h), pop: 'N/A', extra: `Request ID: ${h.get('x-nf-request-id') || 'N/A'}` }) }, 'QUIC.cloud': { headers: ['x-qc-pop'], priority: 10, getInfo: (h) => { let pop = h.get('x-qc-pop') || 'N/A'; const match = pop.match(/[A-Z]{3}/); pop = match ? match[0] : pop; return { provider: 'QUIC.cloud', cache: getCacheStatus(h), pop: pop, extra: null }; } }, 'Vercel': { headers: ['x-vercel-id'], priority: 10, getInfo: (h) => { let pop = 'N/A'; const vercelId = h.get('x-vercel-id'); if (vercelId) { const regionPart = vercelId.split('::')[0]; const match = regionPart.match(/^[a-zA-Z]+/); if (match) pop = match[0].toUpperCase(); } return { provider: 'Vercel', cache: getCacheStatus(h), pop: pop, extra: `ID: ${h.get('x-vercel-id') || 'N/A'}` }; } }, 'Fastly': { headers: ['x-fastly-request-id', 'x-served-by'], priority: 9, getInfo: (h) => ({ provider: 'Fastly', cache: getCacheStatus(h), pop: h.get('x-served-by')?.split('-').pop() || 'N/A', extra: `ReqID: ${h.get('x-fastly-request-id') || 'N/A'}` }) }, 'AWS CloudFront': { headers: ['x-amz-cf-pop', 'x-amz-cf-id'], priority: 9, getInfo: (h) => ({ provider: 'AWS CloudFront', cache: getCacheStatus(h), pop: (h.get('x-amz-cf-pop') || 'N/A').substring(0,3), extra: `CF ID: ${h.get('x-amz-cf-id') || 'N/A'}` }) }, 'Qiniu CDN': { headers: ['x-qiniu-zone', 'x-qnm-cache'], priority: 9, getInfo: (h) => ({ provider: 'Qiniu CDN', cache: h.get('x-qnm-cache')?.toUpperCase() || getCacheStatus(h), pop: `Zone ${h.get('x-qiniu-zone') || 'N/A'}`, extra: `ReqID: ${h.get('x-reqid') || 'N/A'}` }) }, 'Alibaba Cloud CDN': { headers: ['eagleid', 'eagleeye-traceid'], serverHeaders: ['alicdn', 'ESA'], priority: 9, getInfo: (h) => { let cacheStatus = getCacheStatus(h); if (cacheStatus === 'N/A' || cacheStatus.includes('(inferred)')) { const siteCacheStatus = h.get('x-site-cache-status')?.toUpperCase(); const serverTiming = h.get('server-timing') || ''; const via = h.get('via') || ''; if (siteCacheStatus) cacheStatus = siteCacheStatus; else if (serverTiming.includes('fetch-origin')) cacheStatus = 'MISS (inferred)'; else if (via.includes('[') && via.includes(',0]')) cacheStatus = 'MISS (inferred)'; } const traceId = h.get('eagleid')?.split(',')[0] || h.get('eagleeye-traceid'); return { provider: 'Alibaba Cloud CDN', cache: cacheStatus, pop: 'N/A', extra: `TraceID: ${traceId || 'N/A'}` }; } }, 'Tencent Cloud CDN': { headers: ['x-cache-lookup', 'x-nws-log-uuid'], serverHeaders: ['nws'], priority: 9, getInfo: (h) => { let cache = (h.get('x-cache-lookup') || '').split(',')[0].toUpperCase(); cache = cache ? cache.replace('CACHE ', '') : getCacheStatus(h); return { provider: 'Tencent Cloud CDN', cache: cache, pop: 'N/A', extra: `Log-UUID: ${h.get('x-nws-log-uuid') || 'N/A'}`}; } }, 'Akamai': { headers: ['x-akamai-transformed', 'x-check-cacheable'], serverHeaders:['AkamaiGHost'], priority: 9, getInfo: (h) => ({ provider: 'Akamai', cache: (h.get('x-check-cacheable') || getCacheStatus(h))?.toUpperCase() || 'N/A', pop: 'N/A', extra: h.get('x-akamai-transformed') ? 'Content transformed' : null }) }, 'Azure CDN': { headers: ['x-azure-ref'], serverHeaders:['ECAcc', 'ECS'], priority: 9, getInfo: (h) => ({ provider: 'Azure CDN', cache: getCacheStatus(h), pop: 'N/A', extra: `Ref: ${h.get('x-azure-ref') || 'N/A'}` }) }, 'CDN77': { headers: ['x-77-cache'], priority: 9, getInfo: (h) => ({ provider: 'CDN77', cache: h.get('x-77-cache')?.toUpperCase() || 'N/A', pop: h.get('x-77-pop')?.toUpperCase() || 'N/A', extra: `Ray: ${h.get('x-77-nzt-ray') || 'N/A'}` }) }, 'BunnyCDN': { serverHeaders: ['BunnyCDN'], headers: ['cdn-pullzone'], priority: 9, getInfo: (h) => ({ provider: 'BunnyCDN', cache: getCacheStatus(h), pop: h.get('bunny-pop')?.toUpperCase() || h.get('cdn-requestcountrycode')?.toUpperCase() || 'N/A', extra: `Pullzone: ${h.get('bunny-cdn-pullzone') || h.get('cdn-pullzone') || 'N/A'}` }) }, 'KeyCDN': { serverHeaders: ['keycdn'], priority: 8, getInfo: (h) => ({ provider: 'KeyCDN', cache: getCacheStatus(h), pop: h.get('x-edge-location')?.toUpperCase() || 'N/A', extra: null }) }, 'Varnish': { headers: ['x-varnish'], priority: 5, getInfo: (h) => ({ provider: 'Varnish (Cache)', cache: h.get('x-varnish-cache')?.toUpperCase() || getCacheStatus(h), pop: 'N/A', extra: `ID: ${h.get('x-varnish')?.split(' ')[0] || 'N/A'}` }) }, 'LiteSpeed': { serverHeaders: ['litespeed'], priority: 1, getInfo: (h) => ({ provider: 'LiteSpeed', cache: getCacheStatus(h), pop: 'N/A', extra: 'No CDN detected' }) } }; function parseInfo(headers) { const lowerCaseHeaders = new Map(); for (const [key, value] of headers.entries()) { lowerCaseHeaders.set(key.toLowerCase(), value); } let detectedProviders = []; for (const [cdnName, cdn] of Object.entries(cdnProviders)) { let isMatch = false; if (cdn.headers?.some(header => lowerCaseHeaders.has(header.toLowerCase()))) { isMatch = true; } if (!isMatch && cdn.serverHeaders) { const serverHeader = lowerCaseHeaders.get('server') || ''; if (cdn.serverHeaders.some(server => serverHeader.toLowerCase().includes(server.toLowerCase()))) isMatch = true; } if (isMatch) { detectedProviders.push({ ...cdn.getInfo(lowerCaseHeaders), priority: cdn.priority || 5 }); } } if (detectedProviders.length > 0) { detectedProviders.sort((a, b) => b.priority - a.priority); return detectedProviders[0]; } const server = lowerCaseHeaders.get('server'); if (server) { return { provider: server, cache: getCacheStatus(lowerCaseHeaders), pop: 'N/A', extra: 'No CDN detected' }; } return { provider: 'Unknown', cache: 'N/A', pop: 'N/A', extra: 'No CDN or Server info' }; } function getPanelCSS() { return ` :host { all: initial; position: fixed; z-index: 99999; bottom: ${config.initialPosition.bottom}; right: ${config.initialPosition.right}; } #cdn-info-panel-enhanced { padding: 12px 16px; border-radius: 12px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 13px; color: ${config.panelTextColor}; background: ${config.panelBgColor}; backdrop-filter: blur(10px); border: 1px solid ${config.borderColor}; box-shadow: 0 8px 32px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.1); cursor: move; user-select: none; transition: opacity ${config.animationDuration}, transform ${config.animationDuration}; opacity: ${config.opacity}; transform: scale(1); min-width: 220px; } #cdn-info-panel-enhanced:hover { opacity: 1; transform: scale(1.02); } .panel-header { font-weight: 600; font-size: 14px; margin-bottom: 8px; color: ${config.borderColor}; text-align: center; border-bottom: 1px solid rgba(52, 152, 219, 0.3); padding-bottom: 6px; } .info-line { display: flex; justify-content: space-between; align-items: center; margin: 6px 0; padding: 2px 0; } .info-label { font-weight: 500; color: #a9cce3; font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; } .info-value { font-weight: 600; max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right; } .extra-info { font-size: 11px; color: #95a5a6; font-style: italic; text-align: center; margin-top: 8px; padding-top: 6px; border-top: 1px solid rgba(149, 165, 166, 0.2); word-break: break-all; } .cache-HIT { color: #2ecc71 !important; } .cache-MISS, .cache-BYPASS { color: #e74c3c !important; } .close-btn { position: absolute; top: -8px; right: -8px; width: 20px; height: 20px; border-radius: 50%; background: #e74c3c; color: white; border: none; cursor: pointer; font-size: 12px; display: none; align-items: center; justify-content: center; transition: all 0.2s; } #cdn-info-panel-enhanced:hover .close-btn { display: flex; } .close-btn:hover { background: #c0392b; transform: scale(1.1); } `; } function createDisplayPanel(info) { if (!info || document.getElementById('cdn-info-host-enhanced')) return; const host = document.createElement('div'); host.id = 'cdn-info-host-enhanced'; document.body.appendChild(host); const shadowRoot = host.attachShadow({ mode: 'open' }); const styleEl = document.createElement('style'); styleEl.textContent = getPanelCSS(); shadowRoot.appendChild(styleEl); const panel = document.createElement('div'); panel.id = 'cdn-info-panel-enhanced'; const cacheStatus = info.cache.toUpperCase(); let cacheClass = ''; if (cacheStatus.includes('HIT')) cacheClass = 'cache-HIT'; else if (cacheStatus.includes('MISS') || cacheStatus.includes('BYPASS')) cacheClass = 'cache-MISS'; const providerLabel = info.provider.includes('CDN') || info.provider.includes('Cloud') || info.provider.includes('Edge') || info.provider.includes('(inferred)') || info.provider.includes('(Cache)') ? 'CDN' : 'Server'; panel.innerHTML = `