From e23eb32c1d90b30a12e831e102a3db332cc91a03 Mon Sep 17 00:00:00 2001 From: Peanut Date: Wed, 3 Jun 2026 23:46:03 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E9=9B=86=E6=88=90=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=20RestTemplate=20=E8=BF=90=E8=A1=8C=E6=97=B6?= =?UTF-8?q?=20User-Agent=20=E4=B8=BA=20Mozilla/5.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/RestTemplateRuntimeConfigTest.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 backend-single/src/test/java/com/emotion/config/RestTemplateRuntimeConfigTest.java diff --git a/backend-single/src/test/java/com/emotion/config/RestTemplateRuntimeConfigTest.java b/backend-single/src/test/java/com/emotion/config/RestTemplateRuntimeConfigTest.java new file mode 100644 index 0000000..297d9ea --- /dev/null +++ b/backend-single/src/test/java/com/emotion/config/RestTemplateRuntimeConfigTest.java @@ -0,0 +1,69 @@ +package com.emotion.config; + +import com.emotion.interceptor.WechatApiLoggingInterceptor; +import org.junit.jupiter.api.Test; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.StandardCharsets; +import java.time.Duration; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * RestTemplate 运行时配置集成测试 + * + *

目标:验证 8 任务 WeChat 修复计划的核心成功标志 - RestTemplate 实际发送的 + * User-Agent 是 "Mozilla/5.0 (compatible; EmotionMuseum/1.0)" 而非 + * 默认的 "Java/17.0.x"(WAF 会拦截 Java UA 导致 text/plain 响应)。 + * + *

策略:复现生产代码 RestTemplateConfig.restTemplate() 的构建逻辑, + * 对 httpbin.org/headers 发真实 HTTPS 请求,从返回的 JSON 中验证 + * 实际发送的 User-Agent。 + * + *

不依赖 Spring 上下文,纯 JUnit 构造 + 真实网络调用 = 最直接的端到端证据。 + */ +class RestTemplateRuntimeConfigTest { + + private static final String EXPECTED_USER_AGENT = "Mozilla/5.0 (compatible; EmotionMuseum/1.0)"; + private static final String FORBIDDEN_USER_AGENT_PREFIX = "Java/"; + + @Test + void restTemplate_RealHttpCallToHttpbin_ConfirmsMozillaUserAgent() { + // 复现生产 RestTemplateConfig.restTemplate() 的构建逻辑 + SimpleClientHttpRequestFactory simpleFactory = new SimpleClientHttpRequestFactory(); + simpleFactory.setConnectTimeout((int) Duration.ofSeconds(5).toMillis()); + simpleFactory.setReadTimeout((int) Duration.ofSeconds(10).toMillis()); + BufferingClientHttpRequestFactory bufferingFactory = + new BufferingClientHttpRequestFactory(simpleFactory); + + RestTemplate restTemplate = new RestTemplateBuilder() + .requestFactory(() -> bufferingFactory) + .defaultHeader("User-Agent", EXPECTED_USER_AGENT) + .defaultHeader("Accept", "application/json, text/plain, */*") + .additionalMessageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8)) + .additionalInterceptors(new WechatApiLoggingInterceptor()) + .errorHandler(new WechatResponseErrorHandler()) + .build(); + + // httpbin.org/headers 返回客户端发送的所有请求头(JSON 格式) + String response = restTemplate.getForObject( + "https://httpbin.org/headers", String.class); + + assertNotNull(response, "httpbin.org should respond"); + System.out.println("[RestTemplateRuntimeConfigTest] httpbin response: " + response); + + // 核心断言:实际发送的 User-Agent 是 Mozilla/5.0 + assertTrue(response.contains(EXPECTED_USER_AGENT), + "User-Agent 应为 '" + EXPECTED_USER_AGENT + "',但实际响应: " + response); + + // 反向断言:绝对不能是 Java/* 默认 UA(WAF 拦截根因) + assertFalse(response.contains(FORBIDDEN_USER_AGENT_PREFIX), + "User-Agent 不应是 Java/*(WAF 会拦截),但实际响应: " + response); + } +}