11import { NextRequest , NextResponse } from 'next/server' ;
22import { getSessionFromHeader , validateSession } from '@/lib/auth' ;
33
4- // WHOIS 查询 API - 使用 apihz.cn 格式化接口实现
4+ // WHOIS 查询 API - 使用 apihz.cn whoisall 接口实现(支持全球1000+域名后缀)
55export async function GET ( request : NextRequest ) {
66 const authHeader = request . headers . get ( 'authorization' ) ;
77 const session = getSessionFromHeader ( authHeader ) ;
@@ -48,7 +48,7 @@ export async function GET(request: NextRequest) {
4848 console . log ( `🔍 Querying WHOIS for: ${ domain } ` ) ;
4949 const startTime = Date . now ( ) ;
5050
51- // 使用 apihz.cn WHOIS API(支持顶级域名格式化查询 )
51+ // 使用 apihz.cn WHOIS API(支持全球1000+域名后缀查询 )
5252 const apiId = process . env . WHOIS_API_ID ;
5353 const apiKey = process . env . WHOIS_API_KEY ;
5454
@@ -57,7 +57,7 @@ export async function GET(request: NextRequest) {
5757 }
5858
5959 // 先尝试获取最优接口地址
60- let apiEndpoint = 'https://cn.apihz.cn/api/wangzhan/whois .php' ;
60+ let apiEndpoint = 'https://cn.apihz.cn/api/wangzhan/whoisall .php' ;
6161
6262 try {
6363 const optimalResponse = await fetch ( 'https://api.apihz.cn/getapi.php' , {
@@ -66,15 +66,17 @@ export async function GET(request: NextRequest) {
6666 if ( optimalResponse . ok ) {
6767 const optimalUrl = await optimalResponse . text ( ) ;
6868 if ( optimalUrl && optimalUrl . startsWith ( 'http' ) ) {
69- apiEndpoint = optimalUrl . trim ( ) ;
69+ // 替换接口路径为 whoisall.php
70+ apiEndpoint = optimalUrl . trim ( ) . replace ( '/whois.php' , '/whoisall.php' ) ;
7071 console . log ( `📡 Using optimal endpoint: ${ apiEndpoint } ` ) ;
7172 }
7273 }
7374 } catch ( err ) {
7475 console . log ( '⚠️ Could not fetch optimal endpoint, using default domain endpoint' ) ;
7576 }
7677
77- const whoisUrl = `${ apiEndpoint } ?id=${ apiId } &key=${ apiKey } &domain=${ domain } ` ;
78+ // type=1 表示优先使用缓存,type=2 直接查询官方
79+ const whoisUrl = `${ apiEndpoint } ?id=${ apiId } &key=${ apiKey } &domain=${ domain } &type=1` ;
7880 const whoisResponse = await fetch ( whoisUrl , {
7981 headers : {
8082 'User-Agent' : 'DomainManagement/1.0' ,
@@ -95,33 +97,23 @@ export async function GET(request: NextRequest) {
9597 throw new Error ( whoisData . msg || 'WHOIS lookup failed' ) ;
9698 }
9799
98- console . log ( `✅ WHOIS query completed in ${ queryTime } s using apihz.cn` ) ;
100+ console . log ( `✅ WHOIS query completed in ${ queryTime } s using apihz.cn (whoisall) ` ) ;
99101
100- // 解析API返回的数据
101- const registrarId = mapRegistrarToId ( whoisData . zcname || '' ) ;
102+ // 解析原始 WHOIS 文本数据
103+ const whoisText = whoisData . whois || '' ;
104+ const parsedData = parseWhoisText ( whoisText ) ;
102105
103- // 收集所有非空的 nameservers
104- const nameServers = [ ] ;
105- for ( let i = 1 ; i <= 7 ; i ++ ) {
106- const ns = whoisData [ `ns${ i } ` ] ;
107- if ( ns ) {
108- nameServers . push ( ns . toLowerCase ( ) ) ;
109- }
110- }
106+ const registrarId = mapRegistrarToId ( parsedData . registrar || '' ) ;
111107
112108 const responseData = {
113- domain : whoisData . domain || domain . toUpperCase ( ) ,
109+ domain : parsedData . domain || domain . toUpperCase ( ) ,
114110 registrar : registrarId ,
115- registrationDate : whoisData . addtime || null ,
116- expiryDate : whoisData . endtime || null ,
117- registrarName : whoisData . zcname || '' ,
118- nameServers : nameServers ,
111+ registrationDate : parsedData . creationDate || null ,
112+ expiryDate : parsedData . expirationDate || null ,
113+ registrarName : parsedData . registrar || '' ,
114+ nameServers : parsedData . nameServers || [ ] ,
119115 queryTime,
120- source : 'apihz.cn' ,
121- // 额外信息
122- handle : whoisData . handle ,
123- status : whoisData . status ,
124- dnssec : whoisData . dnssec ,
116+ source : 'apihz.cn-whoisall' ,
125117 } ;
126118
127119 // 缓存结果
@@ -172,46 +164,65 @@ export async function GET(request: NextRequest) {
172164}
173165
174166
175- // 解析 WHOIS 原始文本
167+ // 解析 WHOIS 原始文本(支持全球多种格式)
176168function parseWhoisText ( whoisText : string ) {
177169 const lines = whoisText . split ( '\n' ) ;
178170 const data : any = { } ;
179171
180- // 提取关键信息的正则表达式
172+ // 提取关键信息的正则表达式(扩展支持更多格式)
181173 const patterns = {
174+ domain : [
175+ / D o m a i n N a m e : \s * ( .+ ) / i,
176+ / 域 名 : \s * ( .+ ) / i,
177+ ] ,
182178 registrar : [
183179 / R e g i s t r a r : \s * ( .+ ) / i,
184180 / S p o n s o r i n g R e g i s t r a r : \s * ( .+ ) / i,
185181 / R e g i s t r a r N a m e : \s * ( .+ ) / i,
186182 / 注 册 商 : \s * ( .+ ) / i,
183+ / 注 册 局 : \s * ( .+ ) / i,
187184 ] ,
188185 creationDate : [
189186 / C r e a t i o n D a t e : \s * ( .+ ) / i,
190187 / C r e a t e d O n : \s * ( .+ ) / i,
191188 / C r e a t e d : \s * ( .+ ) / i,
192189 / R e g i s t r a t i o n T i m e : \s * ( .+ ) / i,
190+ / R e g i s t r a t i o n D a t e : \s * ( .+ ) / i,
193191 / 注 册 时 间 : \s * ( .+ ) / i,
194192 / 创 建 时 间 : \s * ( .+ ) / i,
195193 ] ,
196194 expirationDate : [
197195 / R e g i s t r y E x p i r y D a t e : \s * ( .+ ) / i,
196+ / R e g i s t r a r R e g i s t r a t i o n E x p i r a t i o n D a t e : \s * ( .+ ) / i,
198197 / E x p i r a t i o n D a t e : \s * ( .+ ) / i,
198+ / E x p i r a t i o n T i m e : \s * ( .+ ) / i,
199199 / E x p i r e s O n : \s * ( .+ ) / i,
200200 / E x p i r y D a t e : \s * ( .+ ) / i,
201+ / E x p i r e D a t e : \s * ( .+ ) / i,
201202 / 过 期 时 间 : \s * ( .+ ) / i,
202203 / 到 期 时 间 : \s * ( .+ ) / i,
203204 ] ,
204205 nameServers : [
205206 / N a m e S e r v e r : \s * ( .+ ) / i,
206207 / n s e r v e r : \s * ( .+ ) / i,
207208 / D N S : \s * ( .+ ) / i,
209+ / N a m e s e r v e r : \s * ( .+ ) / i,
208210 ] ,
209211 } ;
210212
211213 // 解析每一行
212214 for ( const line of lines ) {
213215 const trimmedLine = line . trim ( ) ;
214- if ( ! trimmedLine ) continue ;
216+ if ( ! trimmedLine || trimmedLine . startsWith ( '%' ) || trimmedLine . startsWith ( '#' ) ) continue ;
217+
218+ // 域名
219+ for ( const pattern of patterns . domain ) {
220+ const match = trimmedLine . match ( pattern ) ;
221+ if ( match && ! data . domain ) {
222+ data . domain = match [ 1 ] . trim ( ) . toUpperCase ( ) ;
223+ break ;
224+ }
225+ }
215226
216227 // 注册商
217228 for ( const pattern of patterns . registrar ) {
@@ -253,7 +264,11 @@ function parseWhoisText(whoisText: string) {
253264 const match = trimmedLine . match ( pattern ) ;
254265 if ( match ) {
255266 if ( ! data . nameServers ) data . nameServers = [ ] ;
256- data . nameServers . push ( match [ 1 ] . trim ( ) . toLowerCase ( ) ) ;
267+ const ns = match [ 1 ] . trim ( ) . toLowerCase ( ) ;
268+ // 去重
269+ if ( ! data . nameServers . includes ( ns ) ) {
270+ data . nameServers . push ( ns ) ;
271+ }
257272 }
258273 }
259274 }
0 commit comments