今天早上看这个,是的...... HTTP API 和 URL 编码的索引名称和索引值存在问题。
问题是这样的:标头名称和值不是URL 解码的,并且在您 POST 时按原样存储,但是当您发出 GET 请求时,URL 的分层部分(包含索引名称和值)被解码。此外,+
不是%20
任何一个都是一个问题。
如果您使用%20
GET 并对其进行 URL 转义,它实际上可以工作(注意我替换£
为%A3
):
curl -X POST -H 'x-riak-index-Indexed%20field%20name%20%40%24%40%24%40%20%40%24%20not%20url%20safe%23%40%C2%A3%21_bin: index%20%40%24%20value' -d 'Some Value' http://localhost:8098/buckets/test_bucket/keys/my_key
然后
curl localhost:8098/buckets/test_bucket/index/Indexed%2520field%2520name%2520%2540%2524%2540%2524%2540%2520%2540%2524%2520not%2520url%2520safe%2523%2540%25C2%25A3%2521_bin/index%2520%2540%2524%2520value
结果是:
{"keys":["my_key"]}
另一方面,协议缓冲区不会遇到这些问题。如果您将 Java 客户端与协议缓冲区一起使用,则以下操作可以正常工作(请注意,客户端不会像键和存储桶那样自动对索引参数进行 url 编码):
IRiakClient client = RiakFactory.pbcClient();
Bucket b = client.fetchBucket("test_bucket").execute();
String s = "Indexed field name @$@$@ @$ not url safe#@£!";
String s2 = URLEncoder.encode(s, "UTF-8");
System.out.println(s2);
String v = "index @$ value";
String v2 = URLEncoder.encode(v, "UTF-8");
System.out.println(v2);
IRiakObject ro = RiakObjectBuilder.newBuilder("test_bucket", "key")
.addIndex(s2, v2)
.withValue("Some value")
.build();
b.store(ro).execute();
List<String> index = b.fetchIndex(BinIndex.named(s2))
.withValue(v2)
.execute();
System.out.println(index);
client.shutdown();
输出:
indexed+field+name+%40%24%40%24%40+%40%24+not+url+safe%23%40%C2%A3%21
index+%40%24+value
[key]
事实上,协议缓冲区根本不需要您进行 URL 编码……它会通过 UTF8 字节发送并愉快地将它们用作索引名称和值。您可以从上面的示例中删除 URL 编码并查看它是否有效。
不幸的是,如果您尝试在其他地方使用 HTTP,这肯定会出现问题。因为URLEncoder
java 中包含的类 uses +
,所以使用不同的 URL 编码器使用%20
(或做 a String.replaceAll()
)会有所帮助,但您仍然必须处理 HTTP 查询的 URL 转义。
归根结底,如果您使用 HTTP API,2i 的非 US-ASCII(或特殊字符)会出现问题。
更新:我认为这很容易解决并有一个 PR:https ://github.com/basho/riak_kv/pull/543 - 最后讨论了一个问题,因此可能需要额外的工作。我们目前将冻结 riak 1.4 的代码,因此可能要到下一个版本才能使用。