You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebClient自动添加请求头的位置排查及禁用方法咨询

问题:WebClient自动添加默认请求头的位置及禁用方法?

我发现WebClient会自动为请求添加默认头(比如HOST),想搞清楚这一行为的发生位置,同时需要禁用该功能。以下是复现问题的测试用例和依赖配置:

失败的测试用例

// 省略导入语句及pom基础配置
@Test
void testIfNoHeadersAreAddedToRequestImplicitly() {
    Mono<Map<String, Object>> responseMono = WebClient.builder()
            .baseUrl("https://httpbin.org")
            .build()
            .get()
            .uri("/headers")
            .retrieve()
            .bodyToMono(new ParameterizedTypeReference<>() {});
    StepVerifier.create(responseMono.map(m -> m.get("headers")).cast(Map.class))
            .expectNextMatches(Map::isEmpty)
            .verifyComplete();
}

项目依赖配置

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.5</version>
    <relativePath/> <!-- 从仓库查找父依赖 -->
</parent>
<!-- ... -->
<properties>
    <java.version>17</java.version>
    <spring-cloud.version>2022.0.4</spring-cloud.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter</artifactId>
    </dependency>
    <!-- ↓ 包含WebFlux starter -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.wiremock</groupId>
        <artifactId>wiremock-standalone</artifactId>
        <version>3.5.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

我调试了DefaultWebClient.exchange()但没找到问题,后来在org.springframework.http.client.reactive.ReactorClientHttpConnector.connect(..)的回调里发现请求已经带有默认头,深入后发现这些头在Netty层面就已经存在了,而且WireMock里也能复现,排除了httpbin的问题。


分析与解决

1. 默认请求头的来源

  • Netty底层自动填充:像Host这类头是HTTP/1.1及以上协议强制要求的,Netty的HttpClient在构建DefaultHttpRequest时会自动从请求URI中提取Host信息填充,这部分逻辑在Netty的HttpClientCodec或HttpRequestEncoder相关代码里,属于底层协议实现的一部分,不是WebClient主动添加的。
  • Spring生态的自动配置:如果依赖了Spring Cloud Gateway这类组件,其自动配置类(比如GatewayAutoConfiguration)可能会通过WebClientCustomizer给WebClient添加默认头(比如User-Agent、X-Forwarded-*等);另外Spring WebFlux的默认配置也可能会添加一些通用头。

2. 禁用/修改默认头的方法

针对Netty自动添加的Host头

HTTP协议要求必须携带Host头,完全禁用不符合规范,但可以手动设置自定义Host来覆盖Netty的自动填充:

WebClient webClient = WebClient.builder()
        .baseUrl("https://httpbin.org")
        .defaultHeader(HttpHeaders.HOST, "your-custom-host")
        .build();

如果一定要绕过Netty的自动填充(不推荐),可以自定义Netty的HttpClient配置,通过ReactorClientHttpConnector传入自定义的HttpClient,并设置自定义的HttpHeadersFactory来控制头的生成。

清除WebClient的所有默认头

可以通过过滤器拦截请求,清除所有自动添加的头,只保留手动设置的部分:

WebClient webClient = WebClient.builder()
        .baseUrl("https://httpbin.org")
        .filter((request, next) -> {
            ClientRequest filteredRequest = ClientRequest.from(request)
                    .headers(headers -> headers.clear())
                    // 这里可以手动添加需要的头
                    .header(HttpHeaders.HOST, "your-custom-host")
                    .build();
            return next.exchange(filteredRequest);
        })
        .build();

排查Spring自动配置的自定义器

检查项目中是否有WebClientCustomizer类型的Bean,这些Bean会自动修改WebClient的默认配置。可以通过@SpringBootApplication(exclude = {WebClientAutoConfiguration.class})排除WebClient的自动配置,完全自定义WebClient的构建逻辑。

3. 调试关键点

  • 在DefaultClientRequestBuilder.build()方法加断点,跟踪请求头的构建过程,看哪些代码在添加头。
  • 跟踪Netty的HttpClient.send()方法,查看HttpRequest对象的初始化流程,确认默认头的添加位置。

内容的提问来源于stack exchange,提问作者Powet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 15:47:52