解析URI查询丢失超出英镑符号的值

时间:2017-03-19 22:22:40

标签: java uri

当传递包含#的URI查询时,该函数似乎停止迭代查询并返回到#

之前

示例URI:/test.php?hello=Hello+World ljlksjlkdja(#*!!!!()**!&world=Venus

将输出:Hello World ljlksjlkdja(

预期输出:Hello World ljlksjlkdja(#*!!!!()**! from Venus

我已尝试在query.replace("#", "%23")之后用tokens替换英镑符号,但问题仍然存在,所以我不确定。

它所基于的主要功能可以在这里找到:Parse a URI String into Name-Value Collection

或者我注意到作者提到这可以在数组上工作,但它只捕获第一个结果,例如?hello=Hello+World&world[]=Venus&world[]=Mars&world[]=Eartth输出一个数组[world]=>Array([0] => Venus)

private static Map<String, List<String>> splitQuery(String query) throws UnsupportedEncodingException {
    final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
    String[] tokens = query.split("\\?", 2);
    if (tokens.length == 2) {
        query = tokens[1];
        final String[] pairs = query.split("&");
        for (String pair : pairs) {
            final int idx = pair.indexOf("=");
            final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair;
            if (!query_pairs.containsKey(key)) {
                query_pairs.put(key, new LinkedList<String>());
            }
            final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null;
            query_pairs.get(key).add(value);
        }
    }
    return query_pairs;
}

1 个答案:

答案 0 :(得分:1)

您提供的代码和示例为我编译和运行:

System.out.print(splitQuery("asdfasdfadsf?hello=Hello+World"));
System.out.print(splitQuery("asdfasdfadsf?hello=Hello%20World"));
# output: {hello=[Hello World]}{hello=[Hello World]}

一个建议是使用split()来查找key = value对,而不是根据字符索引手动拆分。

更好的是,我考虑使用第三方库来完成这项工作,如Parse a URI String into Name-Value Collection中所述。

已更新以解决问题更新

网址中的#字符会引入fragment identifier。根据{{​​3}}:

  

片段标识符组件由数字符号(&#34;#&#34;)字符的存在表示,并以URI的结尾终止。

因此,当遇到#字符时,查询参数处理结束是有意义的。为了在查询参数中接受这些类型的字符,必须对它们进行编码。 # 编码为%23,但此编码必须在您将请求实际发送到服务器之前进行。使用您的示例,以下内容应按您的意图运行:

/test.php?hello=Hello%2BWorld%20ljlksjlkdja(%23*!!!!()**!&world=Venus

有关有效网址字符的讨论,另请参阅RFC 3986, Section 3.5: Fragment