jetty.project icon indicating copy to clipboard operation
jetty.project copied to clipboard

Client: requests with MultiPartRequestContent take excessively long with some servers

Open mperktold opened this issue 8 months ago • 1 comments

Jetty version(s) 12.0.10

Jetty Environment core

Java version/vendor (use: java -version) openjdk version "21.0.3" 2024-04-16 LTS OpenJDK Runtime Environment Temurin-21.0.3+9 (build 21.0.3+9-LTS) OpenJDK 64-Bit Server VM Temurin-21.0.3+9 (build 21.0.3+9-LTS, mixed mode, sharing)

OS type/version Windows 11

Description Some of our requests take an excessively long, but only with some servers and not with others. It appears to be an issue with MultiPartRequestContent; when the same request is made with a StringRequestContent, everything works as expected.

How to reproduce?

I cannot reproduce this with a local Jetty server, but with some public servers that we are working with:

long t0 = System.nanoTime();
var multiPart = new MultiPartRequestContent();
try (multiPart) {
    multiPart.addPart(new MultiPart.ContentSourcePart(
        "action",
        null,
        HttpFields.EMPTY,
        new StringRequestContent("text/plain", "OTA_Ping:Handshaking")
    ));
}
var httpClient = new HttpClient();
httpClient.start();
ContentResponse response = httpClient.newRequest("https://api.iperbooking.net/alpinebits/2017-10/")
    .method(HttpMethod.POST)
    .accept("text/xml, application/xml")
    .body(multiPart)
    .timeout(5, TimeUnit.MINUTES)
    .idleTimeout(5, TimeUnit.MINUTES)
    .onRequestBegin(r -> System.out.println("request begin"))
    .onRequestHeaders(r -> System.out.println("request headers"))
    .onRequestContent((r, c) -> System.out.println("request content"))
    .onRequestSuccess(r -> System.out.println("request success"))
    .onRequestFailure((r, x) -> System.out.println("request failure"))
    .onResponseBegin(r -> System.out.println("response begin"))
    .onResponseHeaders(r -> System.out.println("response headers"))
    .onResponseContent((r, c) -> System.out.println("response content"))
    .onResponseSuccess(r -> System.out.println("response success"))
    .onResponseFailure((r, x) -> System.out.println("response failure"))
    .send();
long t1 = System.nanoTime();
System.out.println("got response after " + TimeUnit.NANOSECONDS.toSeconds(t1 - t0) + " seconds:");
System.out.println(response);
httpClient.stop();

The code above sends a request with multipart content to a specific server and waits for the response, which takes about two minutes to complete. Most of the request and response events are logged, so you can see that the request immediately goes to success, but processing of the response only begins after about two minutes.

However, when the body is first converted to a string, e.g. like this:

...
.body(new StringRequestContent(multiPart.getContentType(), Content.Source.asString(multiPart)))
...

The request completes in about one second.

mperktold avatar Jun 22 '24 05:06 mperktold