美文网首页
Feign @RequestParams & 符号未转义

Feign @RequestParams & 符号未转义

作者: 蓝笔头 | 来源:发表于2021-07-28 15:58 被阅读0次

    feign-core 版本

            <!-- https://mvnrepository.com/artifact/io.github.openfeign/feign-core -->
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-core</artifactId>
                <version>10.4.0</version>
            </dependency>
    
    调用路径

    源码分析

    1. Template 类

    package feign.template;
    
    ...
    public class Template {
      protected String resolveExpression(Expression expression, Map<String, ?> variables) {
        String resolved = null;
        Object value = variables.get(expression.getName());
        // 1. 调用 SimpleExpression 的 expand() 方法
        return expression.expand(value, this.encode.isEncodingRequired());
      }
    }
    
    public final class Expressions {
    
      static class SimpleExpression extends Expression {
    
        private final FragmentType type;
    
        String encode(Object value) {
          // 2. 调用 UriUtils.encodeReserved() 方法,type 参数是 FragmentType.PATH_SEGMENT
          return UriUtils.encodeReserved(value.toString(), type, Util.UTF_8);
        }
    
        @Override
        String expand(Object variable, boolean encode) {
          StringBuilder expanded = new StringBuilder();
          expanded.append((encode) ? encode(variable) : variable);
          String result = expanded.toString();
          return result;
        }
      }
    }
    
    public class UriUtils {
      
      public static String encodeReserved(String value, FragmentType type, Charset charset) {
        return encodeChunk(value, type, charset);
      }
      
      private static String encodeChunk(String value, FragmentType type, Charset charset) {
        byte[] data = value.getBytes(charset);
        ByteArrayOutputStream encoded = new ByteArrayOutputStream();
    
        for (byte b : data) {
          if (type.isAllowed(b)) {
          // 3.1 如果不需要转义,则不进行转义操作
            encoded.write(b);
          } else {
            /* percent encode the byte */
            // 3.2 否则,进行编码
            pctEncode(b, encoded);
          }
        }
        return new String(encoded.toByteArray());
      }
      
      enum FragmentType {
        URI {
          @Override
          boolean isAllowed(int c) {
            return isUnreserved(c);
          }
        },
        PATH_SEGMENT {
          @Override
          boolean isAllowed(int c) {
            return this.isPchar(c) || (c == '/');
          }
        }
        abstract boolean isAllowed(int c);
    
        protected boolean isAlpha(int c) {
          return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
        }
    
        protected boolean isDigit(int c) {
          return (c >= '0' && c <= '9');
        }
    
        protected boolean isSubDelimiter(int c) {
          return (c == '!') || (c == '$') || (c == '&') || (c == '\'') || (c == '(') || (c == ')')
              || (c == '*') || (c == '+') || (c == ',') || (c == ';') || (c == '=');
        }
    
        protected boolean isUnreserved(int c) {
          return this.isAlpha(c) || this.isDigit(c) || c == '-' || c == '.' || c == '_' || c == '~';
        }
    
        protected boolean isPchar(int c) {
          return this.isUnreserved(c) || this.isSubDelimiter(c) || c == ':' || c == '@';
        }
    
      }
    }
    

    从源码上可以看出,& 字符属于 isSubDelimiter(),所以不会被转义。

    测试

    package feign.template;
    
    import feign.Util;
    
    public class UriUtilsDemo {
        public static void main(String[] args) {
            String str = "aa&aa";
    
            // 输出:aa&aa
            System.out.println(UriUtils.encodeReserved(str, UriUtils.FragmentType.PATH_SEGMENT, Util.UTF_8));
    
            // 输出:aa%26aa
            System.out.println(UriUtils.encodeReserved(str, UriUtils.FragmentType.URI, Util.UTF_8));
        }
    }
    

    解决方案:

    • (一)升级 feign-core 版本,feign-core-10.12 已经没有这个问题。
    • (二)使用 @RequestBody 替换 @RequestParam

    参考

    相关文章

      网友评论

          本文标题:Feign @RequestParams & 符号未转义

          本文链接:https://www.haomeiwen.com/subject/jrmzmltx.html