hsj преди 1 месец
ревизия
a2f8a8e888

+ 38 - 0
.gitignore

@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 7 - 0
.idea/encodings.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
+  </component>
+</project>

+ 13 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,13 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
+      <option name="ignoredErrors">
+        <list>
+          <option value="N801" />
+          <option value="N806" />
+        </list>
+      </option>
+    </inspection_tool>
+  </profile>
+</component>

+ 14 - 0
.idea/misc.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ExternalStorageConfigurationManager" enabled="true" />
+  <component name="MavenProjectsManager">
+    <option name="originalFiles">
+      <list>
+        <option value="$PROJECT_DIR$/pom.xml" />
+      </list>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>

+ 4 - 0
.idea/vcs.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings" defaultProject="true" />
+</project>

+ 49 - 0
pom.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>3.2.4</version>
+    </parent>
+
+    <groupId>com.tfw</groupId>
+    <artifactId>husj-api</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <properties>
+        <maven.compiler.source>21</maven.compiler.source>
+        <maven.compiler.target>21</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jsoup</groupId>
+            <artifactId>jsoup</artifactId>
+            <version>1.14.3</version> <!-- 请使用最新稳定版本 -->
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+        <plugin>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-maven-plugin</artifactId>
+        </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 11 - 0
src/main/java/xyz/hsj030208/ApiApplication.java

@@ -0,0 +1,11 @@
+package xyz.hsj030208;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ApiApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(ApiApplication.class, args);
+    }
+}

+ 131 - 0
src/main/java/xyz/hsj030208/controller/IPApiController.java

@@ -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());
+//    }
+}

+ 12 - 0
src/main/java/xyz/hsj030208/model/Vo/ApiDetail.java

@@ -0,0 +1,12 @@
+package xyz.hsj030208.model.Vo;
+
+import lombok.Data;
+
+@Data
+public class ApiDetail {
+    private String ip;
+    private String country;
+    private String province;
+    private String city;
+    private String carrier;
+}