Appearance
SetRequestHeader GatewayFilter Factory
概述
SetRequestHeader 是 Spring Cloud Gateway 中的一个重要过滤器工厂,用于设置请求头信息。它能够在请求转发到下游服务之前,动态地添加或替换 HTTP 请求头,这在微服务架构中非常有用,特别是在需要传递认证信息、跟踪信息或其他元数据时。
IMPORTANT
SetRequestHeader 过滤器会替换(而不是添加)具有给定名称的所有请求头。如果需要添加多个同名请求头,请考虑使用其他方式。
核心功能
解决的问题
在微服务架构中,经常需要:
- 为下游服务添加认证令牌
- 传递用户身份信息
- 添加请求跟踪 ID
- 设置特定的服务标识
- 传递业务上下文信息
工作原理
基本配置
参数说明
SetRequestHeader 过滤器接受两个参数:
name:请求头的名称value:请求头的值
基础配置示例
yaml
spring:
cloud:
gateway:
routes:
- id: setrequestheader_route
uri: https://example.org
filters:
- SetRequestHeader=X-Request-Red, Bluekotlin
import org.springframework.cloud.gateway.route.RouteLocator
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class GatewayConfig {
@Bean
fun customRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("setrequestheader_route") { r ->
r.path("/api/**")
.filters { f ->
f.setRequestHeader("X-Request-Red", "Blue")
}
.uri("https://example.org")
}
.build()
}
}实际业务场景
场景 1:添加认证令牌
在微服务架构中,Gateway 通常负责统一认证,然后将认证信息传递给下游服务:
yaml
spring:
cloud:
gateway:
routes:
- id: user_service_route
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- SetRequestHeader=Authorization, Bearer ${jwt.token}
- SetRequestHeader=X-User-Id, ${user.id}kotlin
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory
import org.springframework.stereotype.Component
@Component
class AuthenticationHeaderFilter : AbstractGatewayFilterFactory<AuthenticationHeaderFilter.Config>() {
override fun apply(config: Config): GatewayFilter {
return GatewayFilter { exchange, chain ->
val request = exchange.request.mutate()
// 从JWT中提取用户信息
.header("X-User-Id", extractUserId(exchange))
.header("X-User-Role", extractUserRole(exchange))
.header("X-Request-Time", System.currentTimeMillis().toString())
.build()
chain.filter(exchange.mutate().request(request).build())
}
}
private fun extractUserId(exchange: ServerWebExchange): String {
// 实际业务中从JWT或Session中提取用户ID
return "user123"
}
private fun extractUserRole(exchange: ServerWebExchange): String {
// 提取用户角色
return "ADMIN"
}
class Config {
// 配置参数
}
}场景 2:请求链路追踪
为每个请求添加唯一的追踪 ID,方便日志分析和问题排查:
yaml
spring:
cloud:
gateway:
routes:
- id: order_service_route
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- SetRequestHeader=X-Trace-Id, ${T(java.util.UUID).randomUUID().toString()}
- SetRequestHeader=X-Service-Name, order-service在生产环境中,建议使用专门的链路追踪工具如 Spring Cloud Sleuth 或 Zipkin,而不是手动设置追踪 ID。
URI 变量支持
SetRequestHeader 过滤器支持 URI 变量,可以动态地根据请求路径或主机信息设置请求头值。
基于路径变量
yaml
spring:
cloud:
gateway:
routes:
- id: dynamic_header_route
uri: https://example.org
predicates:
- Path=/api/{version}/users/**
filters:
- SetRequestHeader=X-API-Version, {version}基于主机变量
yaml
spring:
cloud:
gateway:
routes:
- id: tenant_based_route
uri: https://example.org
predicates:
- Host={tenant}.myhost.org
filters:
- SetRequestHeader=X-Tenant-Id, {tenant}
- SetRequestHeader=foo, bar-{tenant}复杂变量示例
yaml
spring:
cloud:
gateway:
routes:
- id: complex_variable_route
uri: lb://backend-service
predicates:
- Host={tenant}.api.{env}.example.com
- Path=/api/{version}/{service}/**
filters:
- SetRequestHeader=X-Tenant, {tenant}
- SetRequestHeader=X-Environment, {env}
- SetRequestHeader=X-API-Version, {version}
- SetRequestHeader=X-Service-Name, {service}kotlin
@Configuration
class DynamicHeaderConfig {
@Bean
fun dynamicRouteLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("dynamic_header_route") { r ->
r.host("{tenant}.api.example.com")
.and()
.path("/api/{version}/users/**")
.filters { f ->
f.setRequestHeader("X-Tenant", "{tenant}")
.setRequestHeader("X-API-Version", "{version}")
.setRequestHeader("X-Request-Source", "gateway")
}
.uri("lb://user-service")
}
.build()
}
}高级用法
条件性设置请求头
结合谓词条件,可以根据不同的条件设置不同的请求头:
yaml
spring:
cloud:
gateway:
routes:
# 移动端请求
- id: mobile_route
uri: lb://mobile-service
predicates:
- Header=User-Agent, .*Mobile.*
filters:
- SetRequestHeader=X-Client-Type, mobile
- SetRequestHeader=X-Feature-Flag, mobile-optimized
# 桌面端请求
- id: desktop_route
uri: lb://web-service
predicates:
- Header=User-Agent, .*(?!Mobile).*
filters:
- SetRequestHeader=X-Client-Type, desktop
- SetRequestHeader=X-Feature-Flag, full-features与其他过滤器组合使用
yaml
spring:
cloud:
gateway:
routes:
- id: comprehensive_route
uri: lb://backend-service
predicates:
- Path=/api/**
filters:
# 限流
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
# 设置请求头
- SetRequestHeader=X-RateLimit-Applied, true
- SetRequestHeader=X-Gateway-Version, v2.0
# 重试机制
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY,GATEWAY_TIMEOUT注意事项和最佳实践
重要提醒
WARNING
SetRequestHeader 会替换(而不是添加)所有具有给定名称的请求头。如果下游服务返回了 X-Request-Red:1234,它将被替换为 X-Request-Red:Blue。
最佳实践
TIP
- 命名规范:使用有意义的请求头名称,建议使用
X-前缀表示自定义请求头 - 避免覆盖:避免覆盖标准 HTTP 请求头,如
Content-Type、Authorization等 - 性能考虑:避免设置过多的请求头,每个请求头都会增加网络传输开销
- 安全性:不要在请求头中传递敏感信息,如密码或完整的认证令牌
常见错误
DANGER
避免以下常见错误:
- 覆盖关键的 HTTP 标准请求头
- 在请求头中传递敏感信息
- 设置过长的请求头值
- 忘记处理特殊字符和编码问题
调试和监控
启用日志
yaml
logging:
level:
org.springframework.cloud.gateway: DEBUG
org.springframework.cloud.gateway.filter: TRACE自定义日志过滤器
kotlin
@Component
class RequestHeaderLoggingFilter : GlobalFilter, Ordered {
private val logger = LoggerFactory.getLogger(RequestHeaderLoggingFilter::class.java)
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
val request = exchange.request
// 记录所有请求头
logger.info("Request headers for ${request.path}: ${request.headers}")
return chain.filter(exchange)
}
override fun getOrder(): Int = -1 // 确保在其他过滤器之前执行
}总结
SetRequestHeader 过滤器是 Spring Cloud Gateway 中一个简单但强大的工具,它能够:
- ✅ 动态设置请求头信息
- ✅ 支持 URI 变量替换
- ✅ 与其他过滤器良好配合
- ✅ 满足微服务间通信需求
通过合理使用 SetRequestHeader 过滤器,可以有效地实现服务间的信息传递、认证授权、链路追踪等功能,是构建健壮微服务架构的重要组件。
在实际项目中,建议结合业务需求和安全考虑,制定统一的请求头命名和使用规范,确保系统的可维护性和安全性。