Spring Cloud Gateway 动态修改请求参数解决 # URL 编码错误传参问题
Spring Cloud Gateway 动态修改请求参数解决 # URL 编码错误传参问题
继实现动态修改请求 Body 以及重试带 Body 的请求之后,我们又遇到了一个小问题。最近很多接口,收到了错误的参数,在接口层报的错是:
class org.springframework.web.method.annotation.MethodArgumentTypeMismatchException, Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: "10#scrollTop=8178"
例如上面这个报错即本来应该是一个数字,结果收到的是 10#scrollTop=8178 导致转换异常。
正常的请求,是可以带 # 的,# 后面的部分属于 fragment。一个 URI 包括:

但是对于这些报错的请求,我们发现,发送的请求的原始 URI 中, # 被错误的 URL 编码了,变成了 %23,例如上面的请求,发到后端的是:
https://zhxhash@example.com:8081/test/service?id=test&number=10%23segment1
这样,后端解析到的 number 的值,就是 number=10#segment1,这样就会发生开头提到的报错。
由于前端没能复现这个问题,并且问题集中于某几个系统的浏览器版本,这个问题只能通过后台网关做修改解决。
我们的网关使用的是 Spring Cloud Gateway,我们可以针对全局请求添加全局 Filter,动态修正 URI,解决这个问题,代码如下:
@Log4j2
@Component
public class QueryNormalizationFilter implements GlobalFilter, Ordered {
@Override
@SneakyThrows
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String originUriString = exchange.getRequest().getURI().toString();
if (originUriString.contains("%23")) {
//将编码后的 %23 替换为 #,重新用这个字符串生成 URI
URI replaced = new URI(originUriString.replace("%23", "#"));
return chain.filter(
exchange.mutate()
.request(
new ServerHttpRequestDecorator(exchange.getRequest()) {
/**
* 这个是影响转发到后台服务的 uri
*
* @return
*/
@Override
public URI getURI() {
return replaced;
}
/**
* 修改这个主要为了后面的 Filter 获取查询参数是准确的
*
* @return
*/
@Override
public MultiValueMap<String, String> getQueryParams() {
return UriComponentsBuilder.fromUri(replaced).build().getQueryParams();
}
}
).build()
);
} else {
return chain.filter(exchange);
}
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
注意点是:
- 我们需要将这个 Filter 放在最开始的位置,保证后续的 Filter 的 URI 是正确的,以免有的 Filter 拿 Fragment 做文章。
- 如果我们只关心转发的请求是正确的,那我们只替换 URI 即可,即覆盖 getURI 方法。
- 连 getQueryParams 也覆盖的原因,是后续的 Filter 可能也会对 QueryParams 做一些操作,我们要保证准确性。
- 只覆盖 getQueryParams,并不会修改后续转发到具体的微服务的请求的 QueryParams,这个只能通过覆盖 getURI 修改。
微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer:

Spring Cloud Gateway 动态修改请求参数解决 # URL 编码错误传参问题的更多相关文章
- Spring Cloud Gateway 之获取请求体(Request Body)的几种方式
Spring Cloud Gateway 获取请求体 一.直接在全局拦截器中获取,伪代码如下 private String resolveBodyFromRequest(ServerHttpReque ...
- springcloud3(五) spring cloud gateway动态路由的四类实现方式
写这篇博客主要是为了汇总下动态路由的多种实现方式,没有好坏之分,任何的方案都是依赖业务场景需求的,现在网上实现方式主要有: 基于Nacos, 基于数据库(PosgreSQL/Redis), 基于Mem ...
- Spring @Scheduled定时任务动态修改cron参数
在定时任务类上增加@EnableScheduling注解,并实现SchedulingConfigurer接口.(注意低版本无效) 设置一个静态变量cron,用于存放任务执行周期参数. 另辟一线程,用于 ...
- Spring Cloud之ZuulFilter拦截请求参数
过滤器放到网关: package com.toov5.filter; import javax.servlet.http.HttpServletRequest; import org.apache.c ...
- Spring Cloud Gateway修改请求和响应body的内容
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 微服务网关实战——Spring Cloud Gateway
导读 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用.本文对Spring Clou ...
- Spring Cloud实战: 基于Spring Cloud Gateway + vue-element-admin 实现的RBAC权限管理系统,实现网关对RESTful接口方法权限和自定义Vue指令对按钮权限的细粒度控制
一. 前言 信我的哈,明天过年. 这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT ...
- Spring Cloud实战 | 第十一篇:Spring Cloud Gateway 网关实现对RESTful接口权限控制和按钮权限控制
一. 前言 hi,大家好,这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT实现的统 ...
- 快速突击 Spring Cloud Gateway
认识 Spring Cloud Gateway Spring Cloud Gateway 是一款基于 Spring 5,Project Reactor 以及 Spring Boot 2 构建的 API ...
随机推荐
- 关于Ubuntu18.04 linux系统使用搜狗输入法 出现乱码
解决: 执行下面的命令即可!无需重启系统 killall fcitx
- (2)hadoop之-----配置免密码登录
ssh-keygen -t rsa 然后一路回车 在家目录下会生成 .ssh 目录 ls -la 查看 进入 .ssh cd .ssh cp ~/.s ...
- js之window对象(慕课网学习笔记)
javaScript定义了一个变量一个函数都会变成window中的一个成员 var a=1; alert(window.a) //会输出a的值 window基础 创建窗口.调整窗口.移动窗口.关闭窗口 ...
- MZY项目笔记:session歧路
from my typora MZY项目笔记:session歧路 文章目录 MZY项目笔记:session歧路 那该怎么办? 1. 手动加上cookie的header. 2.自己模拟一个Session ...
- Vivado实战—单周期CPU指令分析
引言 不知道你是否和我有过同样的感受,<计算机组成原理>这门学科学起来如此的艰难:一节课下来,教室黑板上留下了满满的 "足迹",看上去也挺简单的,不就是 0 和 1 ...
- for循环操作(for...in、forEach)
1.for...in语句用于对数组或者对象的属性进行循环操作,是for循环的一种. 注意:该方法可用于数组或对象. 语法: for(变量 in 对象/数组){} 如: var obj = { nam ...
- Elasticsearch集群搭建教程及生产环境配置
Elasticsearch 是一个极其强大的搜索和分析引擎,其强大的部分在于能够对其进行扩展以获得更好的性能和稳定性. 本教程将提供有关如何设置 Elasticsearch 集群的一些信息,并将添加一 ...
- Windows系统一些好用的办公工具
在日常办公过程中,总有一些工具令人觉得方便,提高了工作效率.以下是根据我的习惯,收集了一些好用的工具,在此记录且不定期更新. 文件名 说明 Everything 文件搜索工具,搜索速度快 ALTRun ...
- 移动端ios上下滑动翻页事件失效
移动端开发过程中,在添加上下滑动事件时候,引入了最常用的移动端库zepto.js及其touch模块,有一种现象,安卓的手机没有问题,上下滑动翻页很正常 :但是到了ios上面,好啊,上下滑动会出现弹性滚 ...
- 注解@Component方式代替xml装配bean
一.@Component 用注解来装配bean 1. 2.对类使用注解,装配bean: 3.类中,注入其他对象: 二.bean.xml中配置@Componet方式装配bean 1.开启注解装配bean ...