wiremock / wiremock

A tool for mocking HTTP services
https://wiremock.org/
Apache License 2.0
6.27k stars 1.42k forks source link

Cannot send 'large' SOAP requests with http2 #2585

Open uncl01 opened 7 months ago

uncl01 commented 7 months ago

Proposal

During the migration to cxf 3.6.1 from 3.5.6 wiremock tests start failing. After investigation we found that larger requests (> 6800 characters) to the wiremock (2.35.0) server fail with several different exceptions:

These all occured in the HTTPConduit of cxf, using the java.net.http/jdk.internal.net.http.Http2Connection.

Configuring cxf to use HTTP1.1 immediately resolved all these exceptions and our requests went through to the server as normal.

Reproduction steps

HTTP-Client

HTTPClient client = HTTPClient.newBuilder().version(HTTP_2).cookieHandler(...).build() client.send(request, responseBodyHandler); Test

@WireMockTest public class Testclass {

@Test public void test(WireMockRuntimeInfo info) { WireMock.stubFor(post(urlEqualTo(...)).withRequestBody(...).willReturn(...));

 // create client and send soap request (issues started at xml with at least 6800 characters)
 // Exception occurs

} }

References

The same issue has been reported in https://github.com/wiremock/wiremock/issues/2461 and https://github.com/wiremock/wiremock/issues/2459. Both were closed by the reporter because they found some workaround on the bug. But their issues are unresolved.

Note that these issues are for Wiremock 3.2.0, so this is not contained to the wiremock 2!

Stexxen commented 7 months ago

I also came across this problem while performing a java -> jakarta and spring Boot 2 -> 3 migration, which included the move from Wiremock 2 to Wiremock 3 Quite annoying how it only occurs once a certain payload size was met.

I got past the problem in Wiremock rather than CXF with the following new HttpServerFactory

public class JettyHttp11OnlyServerFactory implements HttpServerFactory {

  @Override
  public HttpServer buildHttpServer(Options options, AdminRequestHandler adminRequestHandler, StubRequestHandler stubRequestHandler) {
    return new JettyHttp11OnlyServer(options, adminRequestHandler, stubRequestHandler);
  }

  public static class JettyHttp11OnlyServer extends Jetty11HttpServer {

    public JettyHttp11OnlyServer(Options options, AdminRequestHandler adminRequestHandler, StubRequestHandler stubRequestHandler) {
      super(options, adminRequestHandler, stubRequestHandler);
    }

    @Override
    protected ServerConnector createHttpConnector(
      String bindAddress, int port, JettySettings jettySettings, NetworkTrafficListener listener) {

      HttpConfiguration httpConfig = createHttpConfig(jettySettings);

      return Jetty11Utils.createServerConnector(
        jettyServer,
        bindAddress,
        jettySettings,
        port,
        listener,
        new HttpConnectionFactory(httpConfig));
    }

  }
}

and set up the WireMockServer's in the following way

    WireMockConfiguration configuration = wireMockConfig()
      .httpServerFactory(new JettyHttp11OnlyServerFactory())
      .port(portNum);
    WireMockServer wireMockServer = new WireMockServer(configuration);

This extends the default Jetty11HttpServer but removes the http2 connectionFactory, so any wiremock Server only allows HTTP1 connections

It does not fix the problem of why large SOAP payloads over http2 breaks things, but TBH I just needed my tests to work properly once again.

tomakehurst commented 5 months ago

This looks like a distinct problem from #2637 where the JDK HTTP client doesn't correctly handle connection upgrades over plain text, rather than it being related to anything specific about the payload contents.

Please could you share a reproducer project so we can dig into this a bit?

One option is that we just provide an option to disable HTTP/2, or possibly separate options for disabling it in plain text and TLS.