如何让Hoverfly拦截AWS CRT HTTP Client的请求?
问题分析与解决方案
核心原因
AwsCrtHttpClient基于AWS CRT原生C库实现,和Java原生HttpClient的代理处理逻辑完全独立:
- 它不读取Java系统属性(如
http.proxyHost),哪怕设置useSystemPropertyValues(true)也无效,因为底层C库不识别这些属性 - 优先读取环境变量(
HTTP_PROXY/HTTPS_PROXY),或必须显式配置代理参数 - HoverflyExtension默认仅设置Java系统属性代理,无法自动覆盖AWS CRT的代理逻辑
解决方案1:显式绑定Hoverfly动态端口
Hoverfly启动时会使用随机端口(日志中显示为50022),不能硬编码端口,需通过Hoverfly实例获取实际端口并配置给AwsCrtHttpClient:
@ExtendWith(HoverflyExtension.class) class AwsCrtHttpClientHoverflyTest { private SdkHttpClient httpClient; @BeforeEach void setUp(Hoverfly hoverfly) { ProxyConfiguration proxyConfig = ProxyConfiguration.builder() .host("localhost") .port(hoverfly.getProxyPort()) // 绑定Hoverfly实际运行端口 .protocol(Protocol.HTTP) // HTTPS请求也用HTTP代理(Hoverfly通过CONNECT处理) .build(); this.httpClient = AwsCrtHttpClient.builder() .proxyConfiguration(proxyConfig) .build(); } @Test void testHttpRequestIntercepted(Hoverfly hoverfly) { // 模拟目标端点 String testUri = "https://example.com/api"; hoverfly.simulate(dsl( service(testUri) .anyMethod() .willReturn(success().body("success")) )); // 构造并发送请求 SdkHttpRequest request = SdkHttpRequest.builder() .uri(URI.create(testUri)) .method(SdkHttpMethod.GET) .appendHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType()) .build(); HttpExecuteResponse response = httpClient.prepareRequest( HttpExecuteRequest.builder().request(request).build() ).call(); // 验证拦截结果 assertThat(response.httpResponse().statusCode()).isEqualTo(200); assertThat(EntityUtils.toString(response.httpResponse().content())).isEqualTo("success"); } }
解决方案2:通过环境变量配置代理
AWS CRT原生库会读取HTTP_PROXY/HTTPS_PROXY环境变量,可在测试初始化时设置:
@ExtendWith(HoverflyExtension.class) class AwsCrtHttpClientEnvProxyTest { private static SdkHttpClient httpClient; @BeforeAll static void setUpBeforeAll(Hoverfly hoverfly) { // 设置AWS CRT识别的环境变量 System.setProperty("HTTP_PROXY", "http://localhost:" + hoverfly.getProxyPort()); System.setProperty("HTTPS_PROXY", "http://localhost:" + hoverfly.getProxyPort()); // 无需显式配置proxyConfiguration,CRT会自动读取环境变量 httpClient = AwsCrtHttpClient.builder().build(); } // 测试逻辑同方案1 }
关键注意事项
- 避免硬编码端口:Hoverfly默认使用随机端口,必须通过
hoverfly.getProxyPort()获取实际运行端口 - HTTPS请求代理协议:即使目标是HTTPS端点,代理协议仍需设为
HTTP,Hoverfly通过CONNECT方法处理HTTPS代理请求 - 检查非代理主机配置:如果测试目标是本地地址,需添加
.nonProxyHosts(Collections.emptyList())到代理配置,避免CRT绕过代理
内容的提问来源于stack exchange,提问作者Flumenque
相关产品推荐
相关产品推荐

