Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java 10 httpclient incubator GET request fails on node.js server

I've been experimenting with the HttpClient stuff in the Java 9/10 incubator, and have the following trivial code (virtually stolen from the project home page!):

URI uri = URI.create("http://192.168.1.102:8080/");

HttpRequest getRequest = HttpRequest.newBuilder()
    .uri(uri)
    .GET()
    .build();

HttpResponse<String> response = client.send(getRequest,
    HttpResponse.BodyHandler.asString());
System.out.println("response to get: " + response.body());

I find it works fine if it's pointed at a URL that is not the localhost, but fails if I ask for the localhost (whether by the name "localhost", by 172.0.0.1, or by the actual IP address of the local host). The error is very strange, and the entire stack trace does not mention any of my code.

WARNING: Using incubator modules: jdk.incubator.httpclient
Exception in thread "main" java.io.EOFException: EOF reached while reading
    at jdk.incubator.httpclient/jdk.incubator.http.Http1AsyncReceiver$Http1TubeSubscriber.onComplete(Http1AsyncReceiver.java:507)
    at jdk.incubator.httpclient/jdk.incubator.http.SocketTube$InternalReadPublisher$ReadSubscription.signalCompletion(SocketTube.java:551)
    at jdk.incubator.httpclient/jdk.incubator.http.SocketTube$InternalReadPublisher$InternalReadSubscription.read(SocketTube.java:728)
    at jdk.incubator.httpclient/jdk.incubator.http.SocketTube$SocketFlowTask.run(SocketTube.java:171)
    at jdk.incubator.httpclient/jdk.incubator.http.internal.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at jdk.incubator.httpclient/jdk.incubator.http.internal.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at jdk.incubator.httpclient/jdk.incubator.http.internal.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at jdk.incubator.httpclient/jdk.incubator.http.SocketTube$InternalReadPublisher$InternalReadSubscription.signalReadable(SocketTube.java:675)
    at jdk.incubator.httpclient/jdk.incubator.http.SocketTube$InternalReadPublisher$ReadEvent.signalEvent(SocketTube.java:829)
    at jdk.incubator.httpclient/jdk.incubator.http.SocketTube$SocketFlowEvent.handle(SocketTube.java:243)
    at jdk.incubator.httpclient/jdk.incubator.http.HttpClientImpl$SelectorManager.handleEvent(HttpClientImpl.java:769)
    at jdk.incubator.httpclient/jdk.incubator.http.HttpClientImpl$SelectorManager.run(HttpClientImpl.java:731)

There is a server running locally, and I can connect to it just fine using a simple request from a web browser.

Any thoughts?

[EDIT]I found, I beleive, the mail list for this project. It's "obfuscated" (which fooled me completely!) but shown as: net dash dev at openjdk dot java dot net I'll post there too, and see if they have any input.

[EDIT 2]I'm pretty sure that this has nothing to do with localhost (per original title) but is something in the protocol negotiation with node.js/express (which is the server I'm using because it's easy to experiment with). Node occasionally (e.g. with a last line of text that's not LF terminated) seems to report the wrong content-length, but this isn't the problem, as the failure still occurs with correct length. I think it's possibly a bug in the attempt to upgrade the connection to HTTP/2.0 but don't know yet...

[EDIT 3]After wasting way too much of my life experimenting, I'm fairly sure that there's something in the way node.js 8.11.1 (and express 4.13.4 and body-parser 1.15.1) handle a request to upgrade a to HTTP 2.0 that's causing the problem. But I have no idea what. I'm giving up, and will continue the learning process for httpClient using a different server.

like image 701
Toby Eggitt Avatar asked May 14 '18 20:05

Toby Eggitt


2 Answers

Updated. I finally got curl built with http 2.0 support, and the blame is entirely on node/express. When this server sees an upgrade request (node 8.something) it simply fails to create any output.Consequently, the client correctly fails with an EOF error.

As a side note, node/express also sets the content-length header "off by one" on occasions (not always!?)

like image 167
Toby Eggitt Avatar answered Nov 08 '22 11:11

Toby Eggitt


try this

HttpRequest request = HttpRequest.newBuilder()
                    .uri(new URI("http://localhost:3000"))
                    .POST(BodyPublisher.fromString("hello"))
                    .version(Version.HTTP_1_1).build();
like image 1
钱宇豪 Avatar answered Nov 08 '22 09:11

钱宇豪