WebClient max header size - spring-webflux

Is there any way I can configure the max header size for a response?
I get the following error from the netty framework :
io.netty.handler.codec.TooLongFrameException: HTTP header is larger than 8192 bytes.
at io.netty.handler.codec.http.HttpObjectDecoder$HeaderParser.newException(HttpObjectDecoder.java:983)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Apparently reactor added an API for this, but I don't see how is this controllable in the WebClient of spring Web Flux. I am using the following version
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
Any ideas?

You can configure reactor's reactor.netty.http.client.HttpClient to have custom maxHeaderSize and plug this preconfigured HttpClient in your WebClient instance.
HttpClient httpClient =
HttpClient.create().httpResponseDecoder(spec -> spec.maxHeaderSize(32 * 1024));
WebClient webClient =
WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient))
.build();

In a Spring Boot app, the max HTTP header size is configured using:
server.max-http-header-size=65536
I have found this solved the above issue on spring cloud gateway, so worth a try.

Related

Will Roku WebDriver setup work with my Java framework

I know Roku Webdriver repository comes with python and Postman sample scripts but I was wondering if I could use my Java scripts - not javascript - to connect to go and automate. If so, does anyone have any examples how to setup the driver in Java?
https://developer.roku.com/en-ca/docs/developer-program/dev-tools/automated-channel-testing/web-driver.md
You can give a try Rokuality.
From README: it is one of the first projects to provide support for the Roku WebDriver API.
If it is not up-to-date, you can take a core as a basis for your test framework
My recommendation would be to download the solution that Roku provides, read the API documentation, use their sample solution for Python, JavaScript and/or Postman to get familiar with the technology, then write your own solution for Java.
The core of the Roku WebDriver solution is an HTTP server which sends ECP commands (remote control primarily) and is able to query the XML source of the Roku channel under test to responses in JSON wire protocol format. Using the documentation and the sample libraries, it will be a straight forward task to write a class for your Java solution which can send GET and POST requests to the WebDriver HTTP server. You can use the Roku provided Go language solution to compile binaries for the HTTP server on the platform(s) you want to support (Mac/Linux/Windows, etc.) and then include the binaries in your solution. You will also want to write a class to to launch and manage the state of the HTTP server and likely extend the solution further to do other things like parsing the responses of the JSON responses from the server, capturing logs from devices and saving screenshots.
Though I have not used Java with Roku WebDriver, I started working with Roku WebDriver shortly after it was released. We wanted to use JavaScript and at the time, Roku had not yet released their JavaScript library, so I wrote one for the project I am working on. It was a pretty straight forward task with Roku's API documentation and Robot Framework library to reference. I see no reason you couldn't do the same in Java, C# or comparable languages.
Note: another user pointed out the Rokuality solution. While it certainly wouldn't hurt to review their implementation to learn from it, it would seem to have a lot of complexity which you don't likely need. A lot of the solution seems designed to interact with the Rokuality cloud service offering and at this point their domain doesn't go anywhere, so I'm not sure they are still up and running.
I figured it out. If anyone is interested in automating it in Java, this code will work as a starting point. Make sure to connect to Go server first. The steps are on https://developer.roku.com/en-ca/docs/developer-program/dev-tools/automated-channel-testing/automated-testing-overview.md . Dont forget to update bash or zshrc with
export GOPATH=/Users/$USER/eclipse-workspace/automated-channel-testing-master
Once the server is running, run the code. Make sure you add your own IP. Thats located in settings on the Roku device. Also add a close method so that you wont get any errors that the "session is already running". If you do get that, just reset the server.
Again this is just a starting point - use the APIs in https://developer.roku.com/en-ca/docs/developer-program/dev-tools/automated-channel-testing/web-driver.md to really start automating.
String ip ;
JSONObject json;
String cookie;
public RokuDriver(String IP) {
this.ip = IP;
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
RequestBody body = RequestBody.create("{\n\t\"ip\": \""+ip+"\"\n}", MediaType.parse("application/json"));
Request request = new Request.Builder()
.url("http://localhost:9000/v1/session")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.build();
try {
Response response = client.newCall(request).execute();
JSONObject jsonBody = new
JSONObject(response.body().string());
cookie = jsonBody.getString("sessionId");
System.out.println(jsonBody.toString(4));
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
close();
}
}
public void down() {
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create("{\n\t\"button\": \"down\"\n}", MediaType.parse("application/json"));
Request request = new Request.Builder()
.url("http://localhost:9000/v1/session/"+cookie+"/press")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.build();
try {
Response response = client.newCall(request).execute();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
POM:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-urlconnection</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20200518</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>

register server wide javax.ws.rs.client.ClientRequestFilter on JBoss EAP 7

Is it possible to register a javax.ws.rs.client.ClientRequestFilter server wide on JBoss EAP 7? I would like to intercept all outbound JAX-RS calls to dynamically add some context information in HTTP headers.
For JAX-WS calls I was able to do this with https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/7.0/html-single/developing_web_services_applications/#jax_ws_handler_chains. I can't find any documentation on a similar mechanism for JAX-RS.
Or alternatively, is there maybe another way to intercept outbound HTTP calls in general?
For a per server solution, according to Using HttpHandler class in Undertow "you need to package your handler(s) into a module, and configure custom-filter in undertow subsystem."
The module.xml example and undertow configuration has been given as well as filter source code!
Update
There's an example of using the HTTPExchange here though I dont really care much for that site. SO also has this slightly related example - it does look like it can work similarly to the JAX-WS Handlers/Interceptor How to properly read post request body in a handler
Another good example file upload using httphandler I know they're different that dealing with JAX-RS but still may apply.
I implemented it by creating a module with the following contents:
package be.fgov.kszbcss.tracer.jaxrs;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
public class TracerResteasyClientBuilder extends ResteasyClientBuilder {
#Override
public ResteasyClient build() {
return super.build().register(TracerJaxRsClientRequestFilter.class);
}
}
/META-INF/services/javax.ws.rs.client.ClientBuilder
be.fgov.kszbcss.tracer.jaxrs.TracerResteasyClientBuilder
And registering it as a global module on JBoss EAP.

Can Spring Cloud Sleuth trace HTTP calls made through Async RestTemplate

I am trying to trace HTTP calls made through Async RestTemplate from a Spring Boot Application.
I have a ZipKin instance running locally to which the microservices in question point to.
I could see spans recorded at every service in ZipKin UI, however I am not able to see the trace covering all the spans.
With RestTemplate the trace is recorded as normal. i.e. I am able to see end-to-end via the UI.
Any pointers will help,
Thanks in advance.
I'm not sure this is what you are expecting, you can add this dependancy in pom.xml if you are using maven:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
and a AlwaysSampler #Bean in your SpringBootApplication class
#Bean
public AlwaysSampler defaultSampler(){
return new AlwaysSampler();
}
This will help you to sample your inputs in zipkin all time.

Apache Camel Restlet - Unable to set Authorization parameter in Header

We are trying to initiate a REST webservice call Using Apache Camel Restlet Component and it was successful.
But we are not able to retrieve the Authorization header property value from request object which we have set in Apache Camel Exchange Header.
exchange.getIn().setHeader("Authorization", "abcde");
Actually we are making this REST call through Camel's Dynamic router.
Can someone suggest how to set the Authorization header in Apache Camel Exchange.
I have found a solution. It might help someone. For adding custom headers in restlet,
Map<String, Object> headers = new HashMap<>();
Series<Header> customHeaders = new Series<Header>(Header.class);
customHeaders.add(new Header("Authorization", "abcde"));
headers.put(HeaderConstants.ATTRIBUTE_HEADERS, customHeaders);

Camel CXF producer basic auth

I'm new to Apache Camel and CXF, and I'm trying to create a route for querying a remote WS which requires Basic Authentication and to specify the SoapAction header. I achieved it with the spring-ws component but I was wondering if I could do the same with the cxf component.
My current configuration is:
RouteBuilder
from("file:src/test/resources/data?noop=true")
.to("xquery:transform/search.xquery")
.to("cxf:-----")
.to("log:TestApp");
I've read something about conduits but I don't know how to configure it in my current camel context.
CamelContext
<camel:camelContext xmlns="http://camel.apache.org/schema/spring">
<package>my.package</package>
</camel:camelContext>
Thanks in advance
You can accomplish this with the Camel HTTP component:
http://server.com?authMethod=Basic&authUsername=user&authPassword=password
However, you probably want to take advantage of the functionality that CXF offers.
You can set up a CXF bean in camel and then set up a HTTP conduit to provide the Basic Auth:
http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html#ClientHTTPTransport%28includingSSLsupport%29-BasicAuthentication
<conduit name="https://localhost:.*""
xmlns:sec="http://cxf.apache.org/configuration/security"
xmlns="http://cxf.apache.org/transports/http/configuration">
<authorization>
<sec:UserName>myuser</sec:UserName>
<sec:Password>mypasswd</sec:Password>
<sec:AuthorizationType>Basic</sec:AuthorizationType>
</authorization>
</conduit>
The HTTP Conduit links to the Camel CXF bean using the 'name' parameter. You set it to a URL like I did above or check the documentation for setting it to a URI matching your service.
Thanks,
Yogesh