背景
最近开了个新项目,项目中需要使用RestTemplate调用gitlab的api,获取文件内容
gitlab给的例子是这样的
--header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw?ref=master"
也就是说file_path是需要encode的。文档看过代码写好,开始自测,结果返回404。日志片段如下
/api/v4/projects/13083/repository/files/app%252Fmodels%252Fkey%252Erb/raw?ref=master"
原来RestTemplate把我encode过的url又给我encode了一次,%2F变成了%252F,我真是谢谢你了。。。搜索一下RestTemplate能不能关闭encode吧。
以下代码来自https://stackoverflow.com/questions/47422472/how-to-disable-url-encoding-in-spring-resttemplate
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
DefaultUriBuilderFactory defaultUriBuilderFactory = new DefaultUriBuilderFactory();
defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(defaultUriBuilderFactory);
return restTemplate;
}
}
很好很强大,那就照方抓药吧,代码改好自测,我去怎么还是404。这次日志里打印的url是正常的了,把url拷贝到 postman里也能调用成功的。这下郁闷了,期间换了n种姿势,从RestTemplate到httpclient,到部门内外大家自己写的http调用的util包,通通试了个遍,结果都是一样,404,那个恼火啊。
冷静下来之后想想,RestTemplate底层实际也是使用了httpclient,所以问题实际上应该是出在httpclient上,于是把httpclient的debug log给打印出来了看看
14:32:52.578 [main] DEBUG org.apache.http.wire - >> "Connection: Keep-Alive[\r][\n]"
14:32:52.578 [main] DEBUG org.apache.http.wire - >> "User-Agent: Apache-HttpClient/4.5.7 (Java/1.8.0_131)[\r][\n]"
14:32:52.578 [main] DEBUG org.apache.http.wire - >> "[\r][\n]"
14:32:52.579 [main] DEBUG org.apache.http.headers - >> GET /api/v4/projects/13325/repository/files/app/models/key.rb/raw?ref=master HTTP/1.1
14:32:52.579 [main] DEBUG org.apache.http.headers - >> PRIVATE-TOKEN: 此处为token
14:32:52.579 [main] DEBUG org.apache.http.headers - >> Host: 此处为host
14:32:52.579 [main] DEBUG org.apache.http.headers - >> Connection: Keep-Alive
14:32:52.579 [main] DEBUG org.apache.http.headers - >> User-Agent: Apache-HttpClient/4.5.7 (Java/1.8.0_131)
14:32:52.591 [main] DEBUG org.apache.http.wire - << "HTTP/1.1 404 Not Found[\r][\n]"
猜猜看我发现了啥,原来我给encode掉的file_path,在httpclient调用的时候,又给我decode回来了。。。,真特么的shit啊。立马把httpclient版本改成之前惯用的4.5.3,再看看接口调用
14:34:07.002 [main] DEBUG org.apache.http.wire - >> "Connection: Keep-Alive[\r][\n]"
14:34:07.002 [main] DEBUG org.apache.http.wire - >> "User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_131)[\r][\n]"
14:34:07.002 [main] DEBUG org.apache.http.wire - >> "[\r][\n]"
14:34:07.002 [main] DEBUG org.apache.http.headers - >> GET /api/v4/projects/13325/repository/files/app%252Fmodels%252Fkey%252Erb/raw?ref=master HTTP/1.1
14:34:07.002 [main] DEBUG org.apache.http.headers - >> PRIVATE-TOKEN: 此处为token
14:34:07.002 [main] DEBUG org.apache.http.headers - >> Host: 此处为host
14:34:07.002 [main] DEBUG org.apache.http.headers - >> Connection: Keep-Alive
14:34:07.002 [main] DEBUG org.apache.http.headers - >> User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_131)
14:34:07.065 [main] DEBUG org.apache.http.wire - << "HTTP/1.1 200 OK[\r][\n]"
这时心里已是五味杂陈,你看看人家4.5.3,人家多么诚信啊,把我打包好的货老老实实的给送出去了,4.5.7你咋这么不诚信呢,我呸。
知道是怎么回事之后,google一下吧,原来已经有人提过bug了
HTTPCLIENT-1968
httpclient 4.5.8就修复了这个bug,我为啥这么倒霉刚好踩到这个雷呢。。。