Spring Cloud Gateway加号被替换为%20的原因及解决方法
问题原因
HTTP的application/x-www-form-urlencoded编码规则中,查询参数里的+会被默认解析为空格。Spring Cloud Gateway在处理请求转发时,会先对原始URL的查询参数进行解码(把+转成空格),之后再重新编码转发给后端,此时空格就会被转成%20,最终导致后端收到的时间参数里的+变成了%20。
解决方案
1. 全局禁用URL自动编码
在Spring Cloud Gateway的配置文件中添加以下配置,关闭网关对URL的自动编码处理,保留原始查询参数的编码状态:
spring: cloud: gateway: httpclient: encode-url: false
2. 自定义过滤器修复单个路由的参数
如果不想全局修改编码策略,可以自定义一个网关过滤器,在转发前手动将查询参数中的%20替换回+:
自定义过滤器代码
@Component public class PreservePlusFilter implements GatewayFilterFactory<PreservePlusFilter.Config> { @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest(); URI originalUri = request.getURI(); String rawQuery = originalUri.getRawQuery(); if (rawQuery != null && rawQuery.contains("%20")) { // 把转义后的空格替换回加号 String fixedQuery = rawQuery.replace("%20", "+"); URI newUri = UriComponentsBuilder.fromUri(originalUri) .replaceQuery(fixedQuery) .build(true) .toUri(); ServerHttpRequest modifiedRequest = request.mutate().uri(newUri).build(); return chain.filter(exchange.mutate().request(modifiedRequest).build()); } return chain.filter(exchange); }; } public static class Config {} }
在路由中添加过滤器
修改路由配置,把自定义过滤器加到过滤器列表里:
- id: api-challenge uri: ${local.api} predicates: - Path=/v1/api/challenge filters: - SetPath=/api/challenge - SecureHeaders - JwtAddGatewayTokenFilter=xxx - PreservePlusFilter
3. 客户端预先编码加号
让请求发起方在构造URL时,把时间参数里的+预先编码为%2B,这样网关解码后会得到正确的+,转发时也会保留正确的编码。示例请求URL:
/v1/api/challenge?time=2023-04-07T11:10:06.763%2B02:00
内容的提问来源于stack exchange,提问作者clsbartek
相关产品推荐
相关产品推荐

