mirror of
https://github.com/jason5ng32/MyIP.git
synced 2026-11-04 08:55:47 +00:00
All 16 handlers previously mixed two HTTP client styles:
- 7 used Node's built-in https.get()/http.get() with callback events
(data/end/error) and 20+ lines of JSON accumulation
- 4 used modern fetch() but without any timeout — upstream hangs would
pin the Express connection indefinitely
Every upstream request now goes through common/fetch-upstream.js, which
wraps fetch() with an 8s AbortController timeout. Handlers shrink from
~20 lines of request boilerplate to a 5-line try/catch:
try {
const apiRes = await fetchUpstream(url);
const json = await apiRes.json();
res.json(modifyJson(json));
} catch (e) {
res.status(500).json({ error: e.message });
}
Converted handlers:
- ipinfo-io / ipapi-com / ipapi-is / ip2location-io / ip-sb / mac-checker
(dropped `import { get } from 'https'/'http'`, rewrote the request)
- ipcheck-ing / invisibility-test / update-user-achievement / get-user-info
(already on fetch, swapped to fetchUpstream to gain the timeout)
- cf-radar (inline fetchFromCloudflare helper swapped to fetchUpstream)
Special case: google-map.js streams a binary JPEG to the client rather
than parsing JSON. Uses Readable.fromWeb(apiRes.body).pipe(res) to
bridge the fetch ReadableStream to the Express response.
Net -150 lines of handler code; upstream hangs now cap at 8s instead
of 30-120s; consistent error handling across all handlers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
37 lines
1021 B
JavaScript
37 lines
1021 B
JavaScript
import { fetchUpstream } from '../common/fetch-upstream.js';
|
|
|
|
export default async (req, res) => {
|
|
// IP presence + validity guaranteed by requireValidIP middleware.
|
|
const ipAddress = req.query.ip;
|
|
|
|
// 构建请求 ip-api.com 的 URL
|
|
const lang = req.query.lang || 'en';
|
|
const url = `http://ip-api.com/json/${ipAddress}?fields=66842623&lang=${lang}`;
|
|
|
|
try {
|
|
const apiRes = await fetchUpstream(url);
|
|
const json = await apiRes.json();
|
|
res.json(modifyJsonForIPAPI(json));
|
|
} catch (e) {
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
};
|
|
|
|
function modifyJsonForIPAPI(json) {
|
|
const { query, country, countryCode, regionName, city, lat, lon, isp, as } = json;
|
|
const asn = as ? as.split(" ")[0] : '';
|
|
|
|
return {
|
|
ip: query,
|
|
city,
|
|
region: regionName,
|
|
country: countryCode,
|
|
country_name: country,
|
|
country_code: countryCode,
|
|
latitude: lat,
|
|
longitude: lon,
|
|
asn,
|
|
org: isp
|
|
};
|
|
}
|