I want to use Spring-boot WebClient to make restful API calls with a proxy server. This is what I did:
- I first created a
HttpClient
with proxy specified. - Then I created a
ReactorClientHttpConnector
. - Finally I created the
WebClient
using the above connector. And specified the default headerProxy_Authorization: [base64 of username:password]
When I made the restful call, the server has the error: status: 407 Proxy Authentication Required
. I logged the request, and find that the Proxy_Authorization
does exist there (You can see the detailed error logs at the bottom).
Would anyone know why the Proxy_Authorization
I specified doesn't work? What is the best way to configure a Proxy with Basic
auth schema with user name and password in Spring-boot webclient?
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import reactor.netty.transport.ProxyProvider;
@Bean
public WebClient webClient() {
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient());
return WebClient.builder()
.defaultHeader(HttpHeaders.PROXY_AUTHORIZATION, AUTH)
.clientConnector(connector)
.filters(
exchangeFilterFunctions -> {
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
})
.build();
}
@Bean
public HttpClient httpClient() {
return HttpClient.create()
.proxy(
proxy ->
proxy.type(ProxyProvider.Proxy.HTTP).host(HTTP_PROXY_URL).port(HTTP_PROXY_PORT));
}
Here is how I made the restful API call:
public Mono<List<CIIItem.Builder>> queryNGCAnnotationsInfo(List<Long> itemIds) {
List<String> itemIdList =
itemIds.stream()
.map(String::valueOf)
.collect(Collectors.toList());
String itemIdStr = String.join(ITEM_ID_SEPARATOR, itemIdList);
return webClient
.get()
.uri(
uriBuilder ->
uriBuilder
.path(ngcDBUrl)
.queryParam("itemId", itemIdStr)
.queryParam("tenantId", NGC_TENANT_ID)
.build(itemIdStr)
)
.retrieve()
.bodyToMono(NGCDatabaseQueryResponse.class)
.map(response -> buildItemInfo(itemIds, response));
}
Here are the error logs:
2022-07-18 18:26:19.931 INFO 36448 --- [ctor-http-nio-3] c.e.s.c.c.config.WebConfig : Request:
Proxy-Authorization: Basic *******************2xsbGN2Z3Z*************hucnVyaAo=
2022-07-18 18:26:20.469 WARN 36448 --- [ctor-http-nio-3] r.netty.http.client.HttpClientConnect : [cd896eb1-1, L:/10.236.91.22:51905 - R:c2sproxy.vip.ebay.com/10.119.106.91:8080] The connection observed an error
io.netty.handler.proxy.HttpProxyHandler$HttpProxyConnectException: http, none, c2sproxy.vip.ebay.com/10.119.106.91:8080 => ngccsserv.vip.ebay.com:80, status: 407 Proxy Authentication Required
at io.netty.handler.proxy.HttpProxyHandler.handleResponse(HttpProxyHandler.java:200) ~[netty-handler-proxy-4.1.78.Final.jar:4.1.78.Final]
at io.netty.handler.proxy.ProxyHandler.channelRead(ProxyHandler.java:257) ~[netty-handler-proxy-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:327) [netty-codec-4.1.78.Final.jar:4.1.78.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:299) [netty-codec-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.handler.proxy.HttpProxyHandler$HttpClientCodecWrapper.channelRead(HttpProxyHandler.java:272) [netty-handler-proxy-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) [netty-transport-4.1.78.Final.jar:4.1.78.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) [netty-common-4.1.78.Final.jar:4.1.78.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.78.Final.jar:4.1.78.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-common-4.1.78.Final.jar:4.1.78.Final]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_242]