java - 为什么 RestTemplate 不对“+”符号进行 urlencode 而是对其他所有内容进行 urlencode?
问题描述
我发现了一个奇怪的问题,即 urlencoding 的行为不一致。
更新
Spring MVC 版本 4.3 和 5.1 之间存在差异:
// FAIL in MVC 4.x
@Test
public void test2() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x/y");
Assert.assertEquals("http://localhost/expr=x%2Fy", savedUri.toString());
}
// FAIL in MVC 4 or 5
@Test
public void test3() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x+y");
Assert.assertEquals("http://localhost/expr=x%2By", savedUri.toString());
}
// ok in MVC 4.x, FAIL in MVC 5
@Test
public void test4() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x+y");
Assert.assertEquals("http://localhost/expr=x+y", savedUri.toString());
}
这可能是 Spring MVC 的更大重构的一部分,因为它在这里也表现在一个完全不同的地方
问题详情
下面的独立测试最好地说明了我的问题。不要被吓倒ClientHttpRequestFactory
- 重要的部分是最后两种测试方法。
package com.stackoverflow.questions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URI;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.io.output.WriterOutputStream;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;
public class RestTemplateTest {
StringWriter stringWriter = new StringWriter();
WriterOutputStream writerOutputStream = new WriterOutputStream(stringWriter);
HttpHeaders headers = new HttpHeaders();
URI savedUri;
ClientHttpRequestFactory rf = new ClientHttpRequestFactory() {
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
savedUri = uri;
return new ClientHttpRequest() {
@Override
public OutputStream getBody() throws IOException {
return writerOutputStream;
}
@Override
public HttpHeaders getHeaders() {
return headers;
}
@Override
public URI getURI() {
return uri;
}
@Override
public String getMethodValue() {
return httpMethod.name();
}
@Override
public ClientHttpResponse execute() throws IOException {
writerOutputStream.close();
return new ClientHttpResponse() {
@Override
public HttpHeaders getHeaders() {
return new HttpHeaders();
}
@Override
public InputStream getBody() throws IOException {
return new ReaderInputStream(new StringReader("test"));
}
@Override
public String getStatusText() throws IOException {
return "OK";
}
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return 200;
}
@Override
public void close() {
}
};
}
};
}
};
RestTemplate rt = new RestTemplate(rf);
@Test
public void test1() {
String resp = rt.getForObject("http://whatever", String.class);
Assert.assertEquals("test", resp);
}
@Test
public void test2() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x/y");
Assert.assertEquals("http://localhost/expr=x%2Fy", savedUri.toString());
}
@Test
public void test3() {
rt.getForObject("http://localhost/expr={expr}", String.class, "x+y");
Assert.assertEquals("http://localhost/expr=x%2By", savedUri.toString());
}
}
发生了什么:
除法符号
/
被正确编码为%2F
- test2() 通过加法符号
+
未编码为 a%2B
- 它仍然存在+
并且 test3() 失败
应该发生什么:
test3() 应该通过。+
应该编码为 %2B,因为它+
是 URL 中的特殊字符,并且被许多服务器端 Web 框架解释为空格。
这里发生了什么,是否有通用修复?
解决方案
推荐阅读
- python - 如何将数据框从字典导出到 Excel
- python - 根据 GUI 中的条目计算总计
- c# - 将websocket c#数据写入nodejs中的json文件
- node.js - 使用带有电子 gui 的不和谐 js,图像发送不起作用
- github - 更改 Github 托管的 React 应用主页
- java - 是否有任何等效于 C 联合或 C++ std::variant 的内存高效 Java?
- java - 如何从命令行运行 Saxon
- sqlite - SQLite 查询不在 cmd 中打印
- c# - AggregateFluent 和聚合查询
- javascript - 当我在 Hyper cmd 上将 app.js 作为节点服务器运行时,会出现“events.js:377”