|
@@ -0,0 +1,131 @@
|
|
|
|
|
+package xyz.hsj030208.controller;
|
|
|
|
|
+
|
|
|
|
|
+import jakarta.servlet.http.HttpServletResponse;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.jsoup.Jsoup;
|
|
|
|
|
+import org.jsoup.nodes.Document;
|
|
|
|
|
+import org.jsoup.nodes.Element;
|
|
|
|
|
+import org.jsoup.select.Elements;
|
|
|
|
|
+import org.springframework.web.bind.annotation.GetMapping;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RequestParam;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
+import xyz.hsj030208.model.Vo.ApiDetail;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+import java.io.IOException;
|
|
|
|
|
+import java.io.PrintWriter;
|
|
|
|
|
+import java.net.InetAddress;
|
|
|
|
|
+import java.net.UnknownHostException;
|
|
|
|
|
+
|
|
|
|
|
+@RestController
|
|
|
|
|
+@RequestMapping("/ip")
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+public class IPApiController {
|
|
|
|
|
+
|
|
|
|
|
+ @GetMapping("/ip.cn/get")
|
|
|
|
|
+ public ApiDetail getIpDetail(@RequestParam String ip, HttpServletResponse response) throws IOException {
|
|
|
|
|
+ if (!isValidIPAddress(ip)) {
|
|
|
|
|
+ log.error("参数错误,无法解析成ip");
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 设置HTTP状态码为400(Bad Request)
|
|
|
|
|
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
|
|
|
+ response.setContentType("application/json;charset=UTF-8");
|
|
|
|
|
+
|
|
|
|
|
+ // 构建错误响应JSON
|
|
|
|
|
+ String errorJson = "{\"code\": 400, \"message\": \"参数不合法,请输入正确的IP\"}";
|
|
|
|
|
+
|
|
|
|
|
+ PrintWriter out = response.getWriter();
|
|
|
|
|
+ out.print(errorJson);
|
|
|
|
|
+ out.flush();
|
|
|
|
|
+
|
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
|
+ log.error("写入响应错误: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ String url = "https://ip.cn/ip/" + ip + ".html";
|
|
|
|
|
+ ApiDetail apiDetail = new ApiDetail();
|
|
|
|
|
+ apiDetail.setIp(ip);
|
|
|
|
|
+ // 连接到目标网址并获取HTML文档
|
|
|
|
|
+ Document doc = Jsoup.connect(url)
|
|
|
|
|
+ .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") // 设置用户代理,模拟浏览器
|
|
|
|
|
+ .timeout(10000)
|
|
|
|
|
+ .get(); // 执行GET请求
|
|
|
|
|
+ Elements metaElements = doc.select("meta[name=description]");
|
|
|
|
|
+
|
|
|
|
|
+ // 通常一个标准HTML页面只有一个description的meta标签,取第一个即可
|
|
|
|
|
+ if (!metaElements.isEmpty()) {
|
|
|
|
|
+ Element metaDescription = metaElements.first();
|
|
|
|
|
+ String content = metaDescription.attr("content"); // 获取content属性的值
|
|
|
|
|
+ String result = content.split(",")[1];
|
|
|
|
|
+ result = result.replace(ip + "归属地为:", "");
|
|
|
|
|
+ String[] split = result.split(" ");
|
|
|
|
|
+ String country = split[0];
|
|
|
|
|
+ apiDetail.setCountry(country);
|
|
|
|
|
+ String province = split[1];
|
|
|
|
|
+ apiDetail.setProvince(province);
|
|
|
|
|
+ String carrier = split[split.length - 1];
|
|
|
|
|
+ apiDetail.setCarrier(carrier);
|
|
|
|
|
+ String city = result.replace(country, "").replace(province, "").replace(carrier, "").trim();
|
|
|
|
|
+ apiDetail.setCity(city);
|
|
|
|
|
+ return apiDetail;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.error("未找到meta标签");
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 设置HTTP状态码为400(Bad Request)
|
|
|
|
|
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
|
|
|
|
+ response.setContentType("application/json;charset=UTF-8");
|
|
|
|
|
+
|
|
|
|
|
+ // 构建错误响应JSON
|
|
|
|
|
+ String errorJson = "{\"code\": 404, \"message\": \"未找到对应结果\"}";
|
|
|
|
|
+
|
|
|
|
|
+ PrintWriter out = response.getWriter();
|
|
|
|
|
+ out.print(errorJson);
|
|
|
|
|
+ out.flush();
|
|
|
|
|
+
|
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
|
+ log.error("写入响应错误: {}", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ public boolean isValidIPAddress(String ipAddress) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // getByName方法会尝试解析字符串。如果它是IP地址,则直接返回InetAddress对象;
|
|
|
|
|
+ // 如果是域名,则会尝试进行DNS解析,这里通过检查是否抛出来排除域名。
|
|
|
|
|
+ InetAddress inet = InetAddress.getByName(ipAddress);
|
|
|
|
|
+ // 一个额外的检查:确保返回的IP地址字符串表示形式与输入一致,以避免将域名误判为IP。
|
|
|
|
|
+ return inet.getHostAddress().equals(ipAddress);
|
|
|
|
|
+ } catch (UnknownHostException e) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+// @GetMapping("/get/")
|
|
|
|
|
+// public ApiDetail getIpDetail(String ip, HttpServletResponse response) {
|
|
|
|
|
+// HttpClient client = HttpClient.newHttpClient();
|
|
|
|
|
+//
|
|
|
|
|
+// HttpRequest request = HttpRequest.newBuilder()
|
|
|
|
|
+// .uri(URI.create("https://rest.ipw.cn/api/ip/query?ip=" + ip + "&lang=zh"))
|
|
|
|
|
+// .GET()
|
|
|
|
|
+// .setHeader("accept", "application/json, text/plain, */*")
|
|
|
|
|
+// .setHeader("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
|
|
|
|
|
+// .setHeader("cache-control", "no-cache")
|
|
|
|
|
+// .setHeader("origin", "https://ipw.cn")
|
|
|
|
|
+// .setHeader("pragma", "no-cache")
|
|
|
|
|
+// .setHeader("priority", "u=1, i")
|
|
|
|
|
+// .setHeader("referer", "https://ipw.cn/")
|
|
|
|
|
+// .setHeader("sec-ch-ua", "\"Microsoft Edge\";v=\"143\", \"Chromium\";v=\"143\", \"Not A(Brand\";v=\"24\"")
|
|
|
|
|
+// .setHeader("sec-ch-ua-mobile", "?0")
|
|
|
|
|
+// .setHeader("sec-ch-ua-platform", "\"Windows\"")
|
|
|
|
|
+// .setHeader("sec-fetch-dest", "empty")
|
|
|
|
|
+// .setHeader("sec-fetch-mode", "cors")
|
|
|
|
|
+// .setHeader("sec-fetch-site", "same-site")
|
|
|
|
|
+// .setHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0")
|
|
|
|
|
+// .build();
|
|
|
|
|
+// HttpResponse<String> jsonResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
|
|
+// }
|
|
|
|
|
+}
|