zoukankan      html  css  js  c++  java
  • 【线上问题】feign对get请求中大括号的处理

    问题场景

    现在服务上面有一个get请求,这个请求比较特殊,他的URL里面有一个属性的值包含大括号。现在这个请求通过postman把大括号进行一次encode然后调用到网关是没问题的。但是如果在内网环境通过ribbon去调用的话我进行一次encode以后网关这边会报400,也就是Bad Request。

    排查

    1. 先确定一下这个请求是否到了网关

      状态码为400的场景出现比较少,一般都会定性为网络问题,但是我们可以其他请求可以打过来,可以确定不是网络问题,但是网关没有任何日志输出,所以我们降低了网关输入日志的级别,发现在网关源码里面报错了,而且没有抛出来。但我们达到了目的,至少这个请求到了网关。

    2. 网关收到的请求有什么不一样的

      我们对比了Postman和ribbon请求的不同,发现ribbon请求的URL根本没有进行编码,那这个时候就怀疑是不是feign进行了一次解码操作,如果进行了一次解码操作我们进行两次编码即可,但是经过测试发现两次编码以后他传到网关的时候,feign就不在进行解码操作了,这个时候就比较奇怪了,feign是如何知道编码一次还是两次呢?幸好可以本地调试,于是打上断点开始调试,最主要查看URL是从什么时候发生改变的。

    3. 定位解码位置

      首先我们使用的feign的版本是8.18.0,最终定位到是在feign的RequestTemplate中的pullAnyQueriesOutOfUrl方法中

      我们首先看到在548行,在这里queryLine里面存放了请求地址问号以后的请求参数,而parseAndDecodeQueries方法就是先对这些内容进行了一次解密操作,然后通过&符号进行切割得到一个map。接着在566行的时候他会把key和value放到一个全局的变量中,也就是queries。但是这里的query方法最终对调用到encodeIfNotVariable方法

      我们可以看到如果value里面包含了大括号,他就不会进行再次编码了,这里就是我们上面现象的根本问题。

      但是为什么要这么处理呢?我看到github上面也有好几个人提了这个问题,不过我看最新的版本依然没有修复。后来我看到RFC6570里面有规定

      我们可以看到对于一些不安全字符是原封传递的。

  • 相关阅读:
    MongoDB的复合唯一索引
    MongoDB实战读书笔记(二):面向文档的数据
    MongoDB实战读书笔记(一):JavaScript shell操作MongoDB
    JAVA8的java.util.function包
    (转)mongoDB 禁用大内存页面 transparent_hugepage=never
    (转)Centos5.5安装MONO2.10.8和Jexus 5.0开启Linux平台.net应用新篇章
    (转)IIS7 优化-网站请发并发数
    (转)IIS设置优化(需根据服务器性能,调整具体参数值)
    逻辑架构和物理架构(转)
    (转)国内外三个不同领域巨头分享的Redis实战经验及使用场景
  • 原文地址:https://www.cnblogs.com/colin-xun/p/14273406.html
Copyright © 2011-2022 走看看