From b5ecdde2abd25ac29468c262e9c9af52df13cd51 Mon Sep 17 00:00:00 2001 From: Niko <1377382065@qq.com> Date: Tue, 5 May 2026 15:31:34 +0800 Subject: [PATCH] Add import test and fix Bearer token format - Add ImportTest to verify Excel import via ets-proxy API - Fix authorization header: use raw token without Bearer prefix (UserInterceptor reads authorization header directly, not Bearer-prefixed) - Rename downloaded file to date-based naming style Co-Authored-By: Claude Opus 4.7 --- src/main/java/com/ets/scraper/EtsScraper.java | 2 +- src/test/java/com/ets/scraper/ImportTest.java | 110 ++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/ets/scraper/ImportTest.java diff --git a/src/main/java/com/ets/scraper/EtsScraper.java b/src/main/java/com/ets/scraper/EtsScraper.java index 5ef6911..b8f2404 100644 --- a/src/main/java/com/ets/scraper/EtsScraper.java +++ b/src/main/java/com/ets/scraper/EtsScraper.java @@ -512,7 +512,7 @@ public class EtsScraper { java.net.http.HttpRequest request = java.net.http.HttpRequest.newBuilder() .uri(uri) .header("Content-Type", "multipart/form-data; boundary=" + boundary) - .header("Authorization", "Bearer " + token) + .header("authorization", token) .POST(java.net.http.HttpRequest.BodyPublishers.ofByteArray(entityBytes)) .build(); diff --git a/src/test/java/com/ets/scraper/ImportTest.java b/src/test/java/com/ets/scraper/ImportTest.java new file mode 100644 index 0000000..9a64f21 --- /dev/null +++ b/src/test/java/com/ets/scraper/ImportTest.java @@ -0,0 +1,110 @@ +package com.ets.scraper; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.File; +import java.io.FileInputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.*; + +class ImportTest { + + private static final String PROXY_HOST = "https://api.ets.niko.red"; + private static final String USERNAME = "admin"; + private static final String PASSWORD = "123456"; + + @TempDir + Path tempDir; + + @Test + void testImportExcel() throws Exception { + File testFile = tempDir.resolve("三联单列表_20260504.xls").toFile(); + Path source = Path.of("downloads/三联单列表_20260504.xls"); + if (source.toFile().exists()) { + java.nio.file.Files.copy(source, testFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING); + } else { + System.out.println("[!] Test file not found at " + source + ", using temp file as fallback"); + } + assertTrue(testFile.exists(), "Test file must exist"); + + String token = proxyLogin(testFile); + assertNotNull(token); + + String result = proxyImport(testFile, token); + assertNotNull(result); + System.out.println("[+] Import result: " + result); + assertTrue(result.contains("\"code\""), "Response should contain code field"); + } + + private String proxyLogin(File testFile) throws Exception { + String loginUrl = PROXY_HOST + "/api/auth/login?username=" + USERNAME + "&password=" + PASSWORD; + HttpClient client = HttpClient.newBuilder() + .connectTimeout(java.time.Duration.ofSeconds(10)) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(loginUrl)) + .POST(HttpRequest.BodyPublishers.noBody()) + .header("Content-Type", "application/json") + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + String body = response.body(); + System.out.println("[+] Login response: " + body); + + int tokenIdx = body.indexOf("\"accessToken\""); + if (tokenIdx < 0) { + throw new AssertionError("No accessToken in login response: " + body); + } + int colonStart = body.indexOf("\":", tokenIdx); + int quoteStart = body.indexOf("\"", colonStart + 2); + int quoteEnd = body.indexOf("\"", quoteStart + 1); + return body.substring(quoteStart + 1, quoteEnd); + } + + private String proxyImport(File file, String token) throws Exception { + String boundary = "----FormBoundary" + System.currentTimeMillis(); + String boundaryLine = "--" + boundary; + java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); + OutputStream os = out; + + os.write((boundaryLine + "\r\n").getBytes()); + os.write(("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"\r\n").getBytes()); + os.write("Content-Type: application/octet-stream\r\n\r\n".getBytes()); + os.flush(); + + try (FileInputStream fis = new FileInputStream(file)) { + byte[] buf = new byte[8192]; + int n; + while ((n = fis.read(buf)) > 0) { + os.write(buf, 0, n); + } + } + os.flush(); + + os.write(("\r\n" + boundaryLine + "--\r\n").getBytes()); + os.flush(); + + byte[] entityBytes = out.toByteArray(); + + HttpClient client = HttpClient.newBuilder() + .connectTimeout(java.time.Duration.ofSeconds(60)) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(PROXY_HOST + "/api/bill/import")) + .header("Content-Type", "multipart/form-data; boundary=" + boundary) + .header("authorization", token) + .POST(HttpRequest.BodyPublishers.ofByteArray(entityBytes)) + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + System.out.println("[+] Import response (" + response.statusCode() + "): " + response.body()); + assertEquals(200, response.statusCode(), "Import request should succeed"); + return response.body(); + } +}