Does anyone know if there's a way to disable cookie management in Spring WebClient using Reactor Netty HttpClient?
I noticed both WebClient.Builder and HttpClient APIs provide a means to add cookies to an outbound request but I am looking for a way to inhibit them altogether if such exists. That is akin to disableCookieManagement on Apache's HttpComponentClientBuilder.
It looks like there's no way to disable the cookie handling per se but this seems to work: Create your own HttpClient, then use HttpClient.doOnRequest to register a callback to be called before sending the request. In the callback, call HttpClientRequest.requestHeaders() to retrieve the request headers, then delete the Cookie header.
Sample code that removes User-Agent header before sending the request.
public class Main {
public static void main(String[] args) {
HttpClient httpClient = HttpClient.create().doOnRequest((request, connection) -> {
request.requestHeaders().remove("User-Agent");
});
WebClient client = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
Mono<String> r = client.get().uri("https://www.google.com").retrieve()
.bodyToMono(String.class);
System.out.println(r.block());
}
}
In my testing, I'm not seeing that Reactor Netty HttpClient is doing anything at all with the cookies that come back in the response. I was actually looking to enable a cookie store like the Apache HttpClient supports, but to all indications the Netty HttpClient has no such feature.
In the entire codebase of Reactor Netty, there is no usage of the "set-cookie" header except in one of their unit tests. This tells me cookies are ignored by default unless the client code chooses to look for them.
Related
I'm using OpenAPI Generator to generate a Java 11 HTTP Client for a swagger-compliant service.
The thing is: this service requires basic authentication but it doesn't challenge the client with a WWW-Authenticate header, so the Java 11 HTTP Client won't send the basic authentication configured with the builder. The workaround for this is to add the Authorization header directly in the request, as suggested in this thread.
Now: as of version 4.3.1, OpenAPI Generator won't expose me an interface to customize the HTTP requests, so I'm wondering if it would be best to override the responsible template (api.mustache:126) or if there is a cleaner alternative for this task.
I come with same issue as yours and solution for me was using generated ApiClient class and its RequestInterceptor field. It allows to customize request headers prior sending it to server:
ApiClient client = new ApiClient();
client.setRequestInterceptor(new Consumer<HttpRequest.Builder>() {
#Override
public void accept(HttpRequest.Builder builder) {
builder.header("Authorization", "Basic " + Base64.getEncoder().encodeToString("foo:bar"));
}
});
There is also a backing version of above called response interceptor if you need to capture reply headers.
I'm trying do some logging in my middleware application, where I want to log request and response of backend system. I would like to use Netty (because we have implemented difficult SslContext).
I'm trying to learn it by this tutorial: https://www.baeldung.com/spring-log-webclient-calls (chapter 4.2. Logging with Netty HttpClient).
For better looking logs, there is part of code:
HttpClient httpClient = HttpClient
.create()
.tcpConfiguration(
tc -> tc.bootstrap(
b -> BootstrapHandlers.updateLogSupport(b, new CustomLogger(HttpClient.class))))
.build()
but bootstrap(...) method is deprecated. What can I use instead?
If you need CustomLogger for request/response (as per comment above) then you can do the following:
CustomLogger customLogger = new CustomLogger(HttpClient.class);
HttpClient httpClient = HttpClient
.create()
.doOnRequest((request, connection) -> {
connection.addHandlerFirst(customLogger);
});
I am developing a jax-ws webservice that pushes messages asynchronously to the subscribed consumers using one-way operation.
Unfortunatelly with each notification, server awaits a HTTP202 response confirmation which blocks the thread for a fraction of a second. This is affecting the performance of the system and I am looking for a way around this.
Is there any way to execute a web-service one-way call and ignore the HTTP response status?
Ok, so after spending a lot of time on this I have found two solutions:
1) Using Apache HTTPComponents, which provide AsyncHTTPClient with nice API allowing us to build a HTTP response from the scratch.
2) More web-service oriented solution based on Apache CXF platform (which includes the HTTPClient implementation) - first we need to set the global Bus property:
Bus bus = BusFactory.getDefaultBus();
bus.setProperty(AsyncHTTPConduit.USE_ASYNC, Boolean.TRUE);
Then, we use custom interceptor to set the message exchange property to asynchronous:
final class SkipWaitInterceptor extends AbstractSoapInterceptor {
SkipWaitInterceptor() {
super(Phase.SETUP);
}
#Override
public void handleMessage(final SoapMessage message) throws Fault {
message.getExchange().setSynchronous(false);
}
}
Finally, we register the interceptor on our asynchronous Endpoint
org.apache.cxf.endpoint.Client client =
org.apache.cxf.frontend.ClientProxy.getClient(this.notificationConsumer);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
cxfEndpoint.getOutInterceptors().add(new SkipWaitInterceptor());
That's all, one-way operation responses no longer block the communication.
I'm trying to get access to the HTTP headers that are injected by Rest Assured. Spring's Mock MVC gives you access to pretty much everything via the MvcResult, and you can use this result to log pretty much anything you would like about the request and response. The only way I can see how to do this is in RestAssured is with a Filter. However, it gives you limited access to the request (you just get the RequestSpecification). I understand that it might be tricky to get access to headers that are added by the HttpClient, but it doesn't look like you can even get access to headers that are added by Rest Assured itself. For example, I can't see any OAuth related headers, nor content-type or content-length. The only headers that appear are those that were manually added using, for example, .contentType(ContentType.XML)
Is there any other way to get access to those headers? I don't need to modify the request, I just want to be able to log all of it and the headers that are injected by Rest Assured.
I found that it's possible to register your own HttpClientFactory with RestAssured:
RestAssured.config().httpClient(
HttpClientConfig.httpClientConfig().httpClientFactory(
new CustomHttpClientFactory())
So I created a new factory that returns an HTTP client into which I inject some request and response interceptors.
public class CustomHttpClientFactory extends HttpClientConfig.HttpClientFactory {
#Override
public HttpClient createHttpClient() {
DefaultHttpClient client = new DefaultHttpClient();
client.addRequestInterceptor((request, ctx) -> {
// do what you will
});
client.addResponseInterceptor((response, ctx) -> {
// do what you will
});
return client;
}
}
This gives you almost full access to manipulate the request and response. One thing to remember is that if you're going to read from the response's entity, you should first wrap it in a BufferedHttpEntity to make it re-readable:
if (response.getEntity() != null && !response.getEntity().isRepeatable()) {
response.setEntity(new BufferedHttpEntity(response.getEntity()));
}
Another problem I ran into is when trying to see the OAuth related information. When using RestAssured's OAuth functionality, it adds its own OAuthSigner interceptor to the HTTP client right before executing the request. This means that it will always be the last interceptor to be called and any interceptor you may have already injected will be called before the request ever gets signed. Because I don't really need to see the signature for now, I didn't investigate this further and I'm leaving it as an exercise for the reader. ;)
I am presuming that GWT RPC actually uses RequestBuilder.
Is there a way to extract the RequestBuilder instance used by my RPC service async requestor?
Actually, my question is, how do you extract the RequestBuilder instance to insert the authentication token as a http header? Is there a way to insert http headers into an RPC service request?
Even if I could insert a http header into the request, how then would the remote servlet be told to expect that auth token? Therefore, in fact, does GWT RPC provide a framework for secure authentication at all?
I am thinking the answer is NO, or at least not in a convenient way. Am I right?
I am coming from having used RestEasy in combination with RestyGWT over SSL, where we can insert headers anytime we wish. BTW, RestyGWT constructs its request to use RequestBuilder.
My actual motivation is comparing the security effectiveness between GWT RPC and GWT JAX-RS (RestyGWT + RestEasy). So if you, as the answerer, have an alternative detailed discourse comparing the security effectiveness of RPC with direct use of RequestBuilder or REST (rather than answering this question directly) please feel free to elaborate.
Am I right to presume that GWT RPC is not security friendly/effective and I should avoid using GWT RPC for secure authenticated requests?
You can have your async method return a Request or a RequestBuilder instead of void. Request allows you to abort() a pending request, whereas RequestBuilder allows you to modify the request before its sent (if you declare the return-type as RequestBuilder, you're responsible for calling send() to actually make the request).
Alternately, you can use an RpcRequestBuilder to customize the RequestBuilder for each and every call made with a specific async service proxy.
As far as I know there is no built in security solution for gwt rpc.
But If I need such authentication I would make the following steps:
1) To be able to set http headers you can make your custom request builder, as I do myself:
MyServiceAsync myService = GWT.create(MyService.class);
MyRequestBuilder myRequestBuilder = new MyRequestBuilder();
myRequestBuilder.addHeader("header", "value");
((ServiceDefTarget) serviceInstance).setRpcRequestBuilder(myRequestBuilder);
MyRequestBuilder extends RpcRequestBuilder. And inside MyRequestBuilder I override method doFinish(RequestBuilder rb) where I put my headers.
Maybe it is not a super solution, but I haven't yet found anything better.
2) For the server side I would implement the AuthenticationFilter for checking the headers and perform server side auth functions prior calling the Servlet.