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;
}
}

注意点是:

  1. 我们需要将这个 Filter 放在最开始的位置,保证后续的 Filter 的 URI 是正确的,以免有的 Filter 拿 Fragment 做文章。
  2. 如果我们只关心转发的请求是正确的,那我们只替换 URI 即可,即覆盖 getURI 方法。
  3. 连 getQueryParams 也覆盖的原因,是后续的 Filter 可能也会对 QueryParams 做一些操作,我们要保证准确性。
  4. 只覆盖 getQueryParams,并不会修改后续转发到具体的微服务的请求的 QueryParams,这个只能通过覆盖 getURI 修改。

微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer

Spring Cloud Gateway 动态修改请求参数解决 # URL 编码错误传参问题的更多相关文章

  1. Spring Cloud Gateway 之获取请求体(Request Body)的几种方式

    Spring Cloud Gateway 获取请求体 一.直接在全局拦截器中获取,伪代码如下 private String resolveBodyFromRequest(ServerHttpReque ...

  2. springcloud3(五) spring cloud gateway动态路由的四类实现方式

    写这篇博客主要是为了汇总下动态路由的多种实现方式,没有好坏之分,任何的方案都是依赖业务场景需求的,现在网上实现方式主要有: 基于Nacos, 基于数据库(PosgreSQL/Redis), 基于Mem ...

  3. Spring @Scheduled定时任务动态修改cron参数

    在定时任务类上增加@EnableScheduling注解,并实现SchedulingConfigurer接口.(注意低版本无效) 设置一个静态变量cron,用于存放任务执行周期参数. 另辟一线程,用于 ...

  4. Spring Cloud之ZuulFilter拦截请求参数

    过滤器放到网关: package com.toov5.filter; import javax.servlet.http.HttpServletRequest; import org.apache.c ...

  5. Spring Cloud Gateway修改请求和响应body的内容

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. 微服务网关实战——Spring Cloud Gateway

    导读 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用.本文对Spring Clou ...

  7. Spring Cloud实战: 基于Spring Cloud Gateway + vue-element-admin 实现的RBAC权限管理系统,实现网关对RESTful接口方法权限和自定义Vue指令对按钮权限的细粒度控制

    一. 前言 信我的哈,明天过年. 这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT ...

  8. Spring Cloud实战 | 第十一篇:Spring Cloud Gateway 网关实现对RESTful接口权限控制和按钮权限控制

    一. 前言 hi,大家好,这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT实现的统 ...

  9. 快速突击 Spring Cloud Gateway

    认识 Spring Cloud Gateway Spring Cloud Gateway 是一款基于 Spring 5,Project Reactor 以及 Spring Boot 2 构建的 API ...

随机推荐

  1. commandBinding 的命令

    <Window x:Class="WpfApplication1.Window29" xmlns="http://schemas.microsoft.com/win ...

  2. QT中的对象模型――QPointer

    QPointer是一个模板类,为QObject对象提供了守卫指针(Guarded Pointer).什么是守卫指针?守卫指针QPointer<T>类似于普通C++指针T *,有且仅有一点不 ...

  3. linux 下文件的权限

  4. 今天突发奇想写了一个小工具,CSDN文章目录生成器

    Why 文章被遗忘 文章检索不好用 方便总结个人知识 What 根据文章分类生成文章目录 莫逸风文章目录 项目地址 gitee(地址)

  5. 关于Java for循环的注意点

    1 import java.util.ArrayList; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 ...

  6. Spring Mvc原理分析(一)

    Servlet生命周期了解 Servlet的生命(周期)是由容器(eg:Tomcat)管理的,换句话说,Servlet程序员不能用代码控制其生命. 加载和实例化:时机取决于web.xml的定义,如果有 ...

  7. Python实现GPU加速的基本操作

    技术背景 之前写过一篇讲述如何使用pycuda来在Python上写CUDA程序的博客.这个方案的特点在于完全遵循了CUDA程序的写法,只是支持了一些常用函数的接口,如果你需要自己写CUDA算子,那么就 ...

  8. Kickstart部署之HTTP架构

    原文转自:https://www.cnblogs.com/itzgr/p/10029527.html作者:木二 目录 一 准备 1.1 完整架构:Kickstart+DHCP+HTTP+TFTP+PX ...

  9. vue + WangEnduit

    components 注册组件 <template lang="html"> <div class="editor"> <div ...

  10. NOI2021 游记

    day -10 开始一天一场NoIP模拟赛,前几场每天挂分很厉害(这么说是因为后面的以前做过) 自省选惨挂以后国赛的知识点就几乎没怎么摸过了,考前发现连manacher都不会写了,反演?又陷入&quo ...