existing "X-Forwarded-For" causes crash
tlzxsun opened this issue · comments
if there already has a "X-Forwarded-For" header, then in
CommonRequestProxyHeadersRewriter
void rewriteHeaders(HttpHeaders headers, URI uri, Consumer<HttpHeaders> headersSetter) {
HttpHeaders rewrittenHeaders = copyHeaders(headers);
List<String> forwardedFor = rewrittenHeaders.get(X_FORWARDED_FOR);
if (isEmpty(forwardedFor)) {
forwardedFor = new ArrayList<>(1);
}
forwardedFor.add(uri.getAuthority());
rewrittenHeaders.put(X_FORWARDED_FOR, forwardedFor);
rewrittenHeaders.set(X_FORWARDED_PROTO, uri.getScheme());
rewrittenHeaders.set(X_FORWARDED_HOST, uri.getHost());
rewrittenHeaders.set(X_FORWARDED_PORT, resolvePort(uri));
headersSetter.accept(rewrittenHeaders);
log.debug("Request headers rewritten from {} to {}", headers, rewrittenHeaders);
}
it will add "uri.getAuthority()" for a Collections.UnmodifiableRandomAccessList which will cause unsupportedOperationException
Collections.UnmodifiableCollection
public boolean add(E e) {
throw new UnsupportedOperationException();
}
the full route is from ReverseProxyFilter.doFilterInternal->HttpRequestMapper.map->RequestEntity(T body, MultiValueMap<String, String> headers, HttpMethod method, URI url, Type type)->
public HttpEntity(T body, MultiValueMap<String, String> headers) {
this.body = body;
HttpHeaders tempHeaders = new HttpHeaders();
if (headers != null) {
tempHeaders.putAll(headers);
}
this.headers = HttpHeaders.readOnlyHttpHeaders(tempHeaders);
}
Hi, thanks for spotting the bug and fixing it!
The build has failed thus, I'll investigate what's going on
There is already a test that checks this use case. The test is passing in both, webmvc and webflux modules. The list is not unmodifiable, it is a java.util.LinkedList
. What Spring version are you using?
Paste your Charon configuration.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
SpringBoot I am using is 1.4.3, after check the git history I found the issue. In newer versions, RestTemplate copies existing requestHeaders values instead of using the original collections.
spring-projects/spring-framework@73a81f9
The detail can be found in this commit.
Thanks for your time, this library is great~
Fixed in 4.6.0.
BTW I thought Charon won't work with Spring Boot 1+ but you're saying that you use Charon with Spring Boot 1.4.3. Well, that's good I guess.
Fixed in 4.6.0.
BTW I thought Charon won't work with Spring Boot 1+ but you're saying that you use Charon with Spring Boot 1.4.3. Well, that's good I guess.
It's better than good😁,it's great~