apollo icon indicating copy to clipboard operation
apollo copied to clipboard

2.2.0 版本 apollo中,值文本修改中,历史或者新的参数有\n 的值,会转换成换行符

Open jesusys opened this issue 11 months ago • 15 comments

重现该行为的步骤 在 apollo文本中输入key,answer = (?:。\n\n|。 \n|。\n|\n\n|\n|。|\n) value转换成 (?:。

|。 |。 |

| |。|
)

2.2.0 版本 apollo中,值文本修改中,历史或者新的参数有\n 的值,会转换成换行符。 历史版本也存在这种情况。

jesusys avatar Feb 10 '25 06:02 jesusys

在 Apollo 2.2.0 版本中,值文本修改中将历史或新参数中的 "\n" 转换为换行符的行为是在 PropertyResolver 类的 handleNormalLine 方法中实现的。具体代码如下:

String newValue = kv[1].replace("\\n", "\n"); //handle user input \n

这行代码将键值对中值部分的字符串字面量 "\n" 替换为实际的换行符。这是为了处理用户输入中 "\n" 代表换行的情况。

要重现这种行为,可以创建一个包含键值对的配置文本,其中值包含字符串 "\n"。当 PropertyResolver 处理这些文本时,它们将被转换为实际的换行符。

例如:

String configText = "key1=value1\\nvalue2";

当调用 resolve 方法处理这个 configText 时,key1 的值将被转换为:

value1
value2

这种行为在历史版本中也存在 [1]

To continue talking to Dosu, mention @dosu.


Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Other

dosubot[bot] avatar Feb 10 '25 06:02 dosubot[bot]

可以在 apollo demo 站点( http://81.68.181.139/ )重现该问题吗?我刚试了下没遇到这个问题

Image

nobodyiam avatar Feb 12 '25 01:02 nobodyiam

@nobodyiam 也会有这个问题, http://81.68.181.139/config.html?#/appid=01test 要是properties的格式

jesusys avatar Feb 12 '25 11:02 jesusys

可以在 apollo demo 站点( http://81.68.181.139/ )重现该问题吗?我刚试了下没遇到这个问题

Image

@nobodyiam 老哥看看http://81.68.181.139/config.html?#/appid=01test的 application namespace,我没提交

jesusys avatar Feb 13 '25 10:02 jesusys

@jesusys 我这边仍然没法重现,看历史提交记录,你提交的值本身没有 \n,而最近的一条是我提交的有 \n,是否你的编辑器/浏览器做了转义?

Image

nobodyiam avatar Feb 16 '25 03:02 nobodyiam

先在文本中输入answer = (?:。\n\n|。 \n|。\n|\n\n|\n|。|\n),点击表格,就会看到输入的和表格中显示的不同了

直接找表格中输入answer = (?:。\n\n|。 \n|。\n|\n\n|\n|。|\n),就是正确的。

一般生产中有一次录入很多配置的话,会选择文本中粘贴配置,这样就会导致,原来answer = (?:。\n\n|。 \n|。\n|\n\n|\n|。|\n)的数据变了。 @nobodyiam

jesusys avatar Feb 20 '25 11:02 jesusys

复现了,直接在表格那里新增配置项不会出现问题,但是在文本模式新增就会出现问题,甚至会让原本正常的表格配置也出问题。

可能是文本模式的某一步转换出现了问题。

spaceluke avatar Feb 21 '25 02:02 spaceluke

Image

spaceluke avatar Feb 21 '25 02:02 spaceluke

@spaceluke 在比较老的 0.8 版本的 apollo 也同样有这个情况。是不是可以打补丁或者,升级新版本优化。

jesusys avatar Feb 21 '25 05:02 jesusys

晚上排查一下看看

spaceluke avatar Feb 21 '25 06:02 spaceluke

主要原因是 后端 portal 的PropertyResolver 的 handleNormalLine 方法有一步把用户输入的\n转成字符串转成真正的换行符


  private void handleNormalLine(Long namespaceId, Map<String, ItemDTO> keyMapOldItem, String newItem,
                                int lineCounter, ItemChangeSets changeSets) {

    String[] kv = parseKeyValueFromItem(newItem);

    if (kv == null) {
      throw new BadRequestException("line:" + lineCounter + " key value must separate by '='");
    }

    String newKey = kv[0];
    String newValue = kv[1].replace("\\n", "\n"); //handle user input \n

    ItemDTO oldItem = keyMapOldItem.get(newKey);

    //new item
    if (oldItem == null) {
      changeSets.addCreateItem(buildNormalItem(0L, namespaceId, newKey, newValue, "", lineCounter));
      //update item
    } else if (!StringUtils.equals(newValue, oldItem.getValue()) || lineCounter != oldItem.getLineNum()) {
      changeSets.addUpdateItem(buildNormalItem(oldItem.getId(), namespaceId, newKey, newValue, oldItem.getComment(), lineCounter));
    }
    keyMapOldItem.remove(newKey);
  }

Image

@nobodyiam 这边原本这样设计的初衷是什么?

因为是对用户的输入和输出进行不对等的修改了,是否可以把这个逻辑去掉,让用户输入什么就能获得什么输出我认为会比较好。👀

spaceluke avatar Feb 21 '25 13:02 spaceluke

最快复现方式 for developer:

在com.ctrip.framework.apollo.portal.component.txtresolver.PropertyResolverTest 中添加下面的测试方法并运行


  @Test
  public void testUserInputNewLine() {
    String configText = "answer = (?:。\\n\\n|。 \\n|。\\n|\\n\\n|\\n|。|\\n)\na=b";
    System.out.println(configText);
    
    ItemChangeSets changeSets = resolver.resolve(1, configText, null);
    List<ItemDTO> createItems = changeSets.getCreateItems();
    createItems.forEach(itemDTO -> {
      System.out.println(itemDTO.getKey() + " " + itemDTO.getValue());
    });
  }

spaceluke avatar Feb 21 '25 13:02 spaceluke

看了下是非常早期的一个 commit 实现的 - https://github.com/apolloconfig/apollo/commit/d250cd20732b5b90aa330a7d855dcc2b8e37f861

看了下应该是为了支持用户在文本模式时输入换行符,所以加入了把 \n 替换为换行符的逻辑。考虑到这个逻辑已经存在很久了,不太建议直接修改这个逻辑。

nobodyiam avatar Feb 22 '25 03:02 nobodyiam

@nobodyiam @spaceluke 两位也帮忙看看有没有其他办法可以解决,\n是有不合理的地方?

jesusys avatar Feb 26 '25 05:02 jesusys

@nobodyiam @spaceluke 两位也帮忙看看有没有其他办法可以解决,\n是有不合理的地方?

\n 从原本的两个字节'\' + 'n'被apollo server端转成一个字节的 '\n' 了,解决方案可以是在client端拿到配置项的Value之后,做一层转换 把 '\n' 替换成两个字节 '\' + 'n'

spaceluke avatar Feb 26 '25 05:02 spaceluke