一个奇怪的urlencode转码问题

问题现象

问题源自于使用tiger进行图查询时,要用到一个get请求,参数是复杂的json字符串,含有空格,逻辑运算符等若干字符。

当服务器端接收时,总是无法正常解析。

神奇的是使用httpclient原生的方式没有这个问题,使用postman也没问题。但是使用spring的restTemplate就偏偏有这问题。

反复调试也没有完全搞清楚。困扰了两三天。

具体问题

下面便是我要传入的json字符串:

http://192.168.1.101:9000/query/work_graph/graphKExpand?gdbQuery={"debug":true,"direction":"ANY","edgeTables":["all_to_skill","company_person"],"endVertices":[{"objectKey":"p2","schema":"persons"},{"objectKey":"222222222222222222","schema":"company"}],"filterExpression":"((t.type==\"company\" AND (t.city==\"sayan\" OR t.city==\"dongguan\")) OR (e.type==\"all_to_skill\" AND ((e.quadrant>1 AND e.quadrant<=800) OR (e.quadrant>=1000 AND e.quadrant<=3000))) OR ((t.type==\"persons\" AND (t.quadrant==\"4\" OR t.quadrant==\"5\")) AND (t.type==\"persons\" AND (t.quadrant==\"10\" OR t.quadrant==\"20\"))))","graph":"work_graph","internalOption":{"debug":true},"maxDepth":10,"maxSize":100,"offset":44,"size":100,"startVertices":[{"objectKey":"c4","schema":"company"},{"objectKey":"p3","schema":"persons"},{"objectKey":"c1","schema":"company"}],"type":"K_EXPAND","vertexTables":["persons","skill","company"]}

展开后的json是这样的:

{
  "debug": true,
  "direction": "ANY",
  "edgeTables": [
    "all_to_skill",
    "company_person"
  ],
  "endVertices": [
    {
      "objectKey": "p2",
      "schema": "persons"
    },
    {
      "objectKey": "222222222222222222",
      "schema": "company"
    }
  ],
  "filterExpression": "t.type==\"company\" AND (t.city==\"sayan\" OR t.city==\"dongguan\"",
  "graph": "work_graph",
  "internalOption": {
    "debug": true
  },
  "maxDepth": 10,
  "maxSize": 100,
  "offset": 44,
  "size": 100,
  "startVertices": [
    {
      "objectKey": "c4",
      "schema": "company"
    },
    {
      "objectKey": "p3",
      "schema": "persons"
    },
    {
      "objectKey": "c1",
      "schema": "company"
    }
  ],
  "type": "K_EXPAND",
  "vertexTables": [
    "persons",
    "skill",
    "company"
  ]
}

测试用例:

import org.junit.Test;

import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * Created by HaiyangHome on 2019/3/23.
 */
public class UrlEncodeTest {


    /**
    * urlencode转码不能随便用,因为她会把空格转换成+号,而不是标准的%20字符
     * 所以urlencode只适用于服务端支持的协议是RFC1738
     * 如果服务端只支持RFC 2396标准,那么服务端解码时,会把加号+当成保留字符,而不转码
    * */
    @Test
    public void test()throws Exception{
        String charset = "UTF-8";
        String str = "aabb ccddfff++++111";
        System.out.println(URLEncoder.encode(str, charset));

        String decodeStr = "aabb+ccddfff%2B%2B%2B%2B111";
        System.out.println(URLDecoder.decode(decodeStr, charset));

        String decodeStr2 = "aabb%20ccddfff%2B%2B%2B%2B111";
        System.out.println(URLDecoder.decode(decodeStr, charset));
    }

}

结论

根本原因是urlencode这个工具类不太完善。它在转码时不时按照最新的转码标准实现。

具体原因:

urlencode转码不能随便用,因为她会把空格转换成+号,而不是标准的%20字符
所以urlencode只适用于服务端支持的协议是RFC1738
如果服务端只支持RFC 2396标准,那么服务端解码时,会把加号+当成保留字符,而不转码。这会导致数据破坏,程序bug。

猜你喜欢

转载自www.cnblogs.com/geektcp/p/10589344.html