HTTP Respnse 400

ProtonM

Mitglied
Hallo

Seit dem Systemupdate am 13.03.2022 bekommt mein HTTP-Request POST
einen 400er Response. Der Request läft im Minutentakt seit Monaten.

In der Änderungsliste der Java-Packetes openjdk-11-* vom 25.01.2022 finde ich das:

- JDK-8269944: Better HTTP transport redux.

Kann dieser bugfix die 400er Respone aus lösen? Und wie löse ich das Problem?

Vielen Dank für jeden Tipp
 

LimDul

Top Contributor
Das Problem löst du indem du das Problem löst.

Deine Frage ist ungefähr auf dem Level

Seit dem Wetterwechsel am 13.3.2022 fährt mein Auto nicht mehr. Kann anderer Sprit das Problem lösen.

Sprich, es fehlen sämtliche Infos.

* Wer erzeugt den Request wie
* Wer nimmt den Request entgegen
* Ist der Request überhaupt korrekt? (Debugging anschalten und mit Postman den Request selber senden)

Und nein, ich glaube nicht das ein JDK Update da irgendwas löst. Das ist zu 99,9% ein clientseitiges Problem im Client-Code.
 

ProtonM

Mitglied
Hallo LimDul
Der HTTP-Request läuft seit Monaten einwandfrei. Serverseitig ist nichts feststellbar. Clientseitig erhält der Request aus dem Browser heraus die korrekte Antwort (200). Vermutung also, dass mit den neuen openjdk-11-* Paketen die Java Laufzeitumgebung verändert wurde, zumal in der Änderungshistorie ein Bugfix zum HTTP aufgeführt ist.
Das ist der Stand.
Wie kann ich Bugfix-Details herausbekommen, um zu klären, ob ich die richtige Spur verfolge?
Kann ich die alte Version installieren? Wie? Und wo finde ich so was?
Kann ich den Bug reporten? Wie macht man das? Macht das überhaupt Sinn?
 

LimDul

Top Contributor
Installier halt die alte Version. Sollte sich per Google finden lassen. Ansonsten - mit den Infos kann man dir nicht helfen. Es ist noch nicht mal klar ob Java hier der Client oder Server ist.

Wer erzeugt wie den Request. Wer meldet wie den Fehler. Es gibt ca. eine Million Frameworks die HTTP Requests absetzen oder verarbeiten.
 

ProtonM

Mitglied
Naja, der HTTP-Request kommt immer vom Client und der Server schickt die Response. Insofern ist gesetzt, wer was macht. Und in einem Java-Forum kommt nur ein Werkzeugkasten zur Anwendung: jdk und konkret bei mir openjdk-11.
 

LimDul

Top Contributor
Das ist keine Antwort. Ist Java der client oder der Server? Wie wird der Http Request oder Response verarbeitet? Auch mit einem JDK gibt es zig Möglichkeiten. Ohne Code und Fakten kann man nicht helfen.
 

mihe7

Top Contributor
@ProtonM, das kann natürlich ein Bug sein, davon würde ich aber nicht von vornherein ausgehen.

Die Requests müssen am Server ja im Access-Log stehen (wenn es denn ein solches gibt). Ist das der Fall?

Was spricht denn z. B. der Client, wenn Du diesen mit eingeschaltetem HTTP-Logging startest? (-Djdk.httpclient.HttpClient.log=all)
 

ProtonM

Mitglied
Wenn's hilft?

Java:
           HttpRequest request = (HttpRequest) HttpRequest.newBuilder()
            .uri(URI.create(strEndpoint))
            .header(strHeaderL, strHeaderR)
            .POST(HttpRequest.BodyPublishers.ofString(joMeter.toString ()))
            .build();

        HttpResponse<?> response = client.send(request, HttpResponse.BodyHandlers.ofString());

Request outpu:
Fri Mar 18 12:45:59 CET 2022 Requ: https://xxx.yyy.de/api/v1 POST
Fri Mar 18 12:45:59 CET 2022 Init: {"method":"init","id":"9","jsonrpc":"2.0","params":{"key":"ad84fd70-404a-baaf-c55297c10d16"}}

Response output:
Fri Mar 18 12:45:59 CET 2022 Resp-Head: java.net.http.HttpHeaders@51cac8f0 { {:status=[400], content-length=[150], content-type=[text/html; charset=utf-8], date=[Fri, 18 Mar 2022 11:45:59 GMT], server=[nginx]} }
Fri Mar 18 12:45:59 CET 2022 Resp-Body: <html> <head><title>400 Bad Request</title></head>
<body> <center><h1>400 Bad Request</h1></center> <hr><center>nginx</center> </body> </html>
 

ProtonM

Mitglied
Lt. Info vom Server-Admin wird der Request nicht an den Endpunkt durchgereicht, sondern bleibt beim Webserver hängen.
Der Output von einem Request und einer Response:

Java:
März 18, 2022 1:09:43 NACHM. jdk.internal.net.http.HttpClientImpl$SelectorManager run
INFO: CHANNEL: HttpClient-1-SelectorManager: starting
Obje: {"method":"object","id":"9","jsonrpc":"2.0","params":{"hks1":10,"aat":-15,"hgt1":15,"key":"ad84fd70-2e35-404a-baaf-c55297c10d16"}}
März 18, 2022 1:10:29 NACHM. jdk.internal.net.http.MultiExchange requestFilters
INFO: MISC: Applying request filters
März 18, 2022 1:10:29 NACHM. jdk.internal.net.http.MultiExchange requestFilters
INFO: MISC: Applying jdk.internal.net.http.AuthenticationFilter@5d949303
März 18, 2022 1:10:29 NACHM. jdk.internal.net.http.MultiExchange requestFilters
INFO: MISC: Applying jdk.internal.net.http.RedirectFilter@753b7a39
März 18, 2022 1:10:29 NACHM. jdk.internal.net.http.MultiExchange requestFilters
INFO: MISC: All filters applied
März 18, 2022 1:10:29 NACHM. jdk.internal.net.http.AbstractAsyncSSLConnection createSSLParameters
INFO: SSL: AbstractAsyncSSLConnection: Setting application protocols: [h2, http/1.1]
März 18, 2022 1:10:29 NACHM. jdk.internal.net.http.AbstractAsyncSSLConnection <init>
INFO: SSL: SSLParameters:
    cipher: TLS_AES_256_GCM_SHA384
    cipher: TLS_AES_128_GCM_SHA256
    cipher: TLS_CHACHA20_POLY1305_SHA256
    cipher: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    cipher: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    cipher: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
    cipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    cipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    cipher: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
    cipher: TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    cipher: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
    cipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
    cipher: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
    cipher: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
    cipher: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
    cipher: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
    cipher: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    cipher: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
    cipher: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
    cipher: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
    cipher: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
    cipher: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
    cipher: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
    cipher: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
    cipher: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
    cipher: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
    cipher: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
    cipher: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
    cipher: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
    cipher: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    cipher: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
    cipher: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
    cipher: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
    cipher: TLS_DHE_RSA_WITH_AES_256_CBC_SHA
    cipher: TLS_DHE_DSS_WITH_AES_256_CBC_SHA
    cipher: TLS_DHE_RSA_WITH_AES_128_CBC_SHA
    cipher: TLS_DHE_DSS_WITH_AES_128_CBC_SHA
    cipher: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
    cipher: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
    cipher: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
    cipher: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
    cipher: TLS_RSA_WITH_AES_256_GCM_SHA384
    cipher: TLS_RSA_WITH_AES_128_GCM_SHA256
    cipher: TLS_RSA_WITH_AES_256_CBC_SHA256
    cipher: TLS_RSA_WITH_AES_128_CBC_SHA256
    cipher: TLS_RSA_WITH_AES_256_CBC_SHA
    cipher: TLS_RSA_WITH_AES_128_CBC_SHA
    cipher: TLS_EMPTY_RENEGOTIATION_INFO_SCSV
    application protocol: h2
    application protocol: http/1.1
    protocol: TLSv1.3
    protocol: TLSv1.2
    endpointIdAlg: HTTPS
    server name: type=host_name (0), value=xxx.yyy.zz

März 18, 2022 1:10:29 NACHM. jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription handleSubscribeEvent
INFO: CHANNEL: Start reading from java.nio.channels.SocketChannel[connected local=/192.168.144.101:56088 remote=xxx.yyy.zz/157.90.153.195:443]
März 18, 2022 1:10:29 NACHM. jdk.internal.net.http.SocketTube$InternalWriteSubscriber startSubscription
INFO: CHANNEL: Start requesting bytes for writing to channel: java.nio.channels.SocketChannel[connected local=/192.168.144.101:56088 remote=service.thop.fit/157.90.153.195:443]
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection <init>
INFO: MISC: Connection send window size 65.535
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection sendConnectionPreface
INFO: MISC: /192.168.144.101:56088: start sending connection preface to xxx.yyy.zz/157.90.153.195:443
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection sendConnectionPreface
INFO: FRAME: OUT: SETTINGS: length=30, streamid=0, flags=0  Settings: HEADER_TABLE_SIZE=16384 ENABLE_PUSH=1 MAX_CONCURRENT_STREAMS=100 INITIAL_WINDOW_SIZE=16777216 MAX_FRAME_SIZE=16384
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection sendConnectionPreface
INFO: MISC: PREFACE_BYTES sent
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection sendConnectionPreface
INFO: MISC: Settings Frame sent
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection sendConnectionPreface
INFO: CHANNEL: Sending initial connection window update frame: 33.488.897 (33.554.432 - 65.535)
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection encodeFrame
INFO: FRAME: OUT: WINDOW_UPDATE: length=4, streamid=0, flags=0  WindowUpdate: 33488897
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection sendConnectionPreface
INFO: MISC: finished sending connection preface
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream sendHeadersAsync
INFO: REQUEST: https://xxx.yyy.zz/api/v1 POST
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection encodeHeaders
INFO: HEADERS: HEADERS FRAME (stream=1)
    :authority: xxx.yyy.zz
    :method: POST
    :path: /api/v1
    :scheme: https
    content-length: 130
    host: xxx.yyy.zz
    User-Agent: Java-http-client/11.0.14
    Content-Type: application/json

März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection lambda$encodeFrames$9
INFO: FRAME: OUT: HEADERS: length=76, streamid=1, flags=END_HEADERS
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection encodeFrame
INFO: FRAME: OUT: DATA: length=130, streamid=1, flags=END_STREAM
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream getResponseAsync
INFO: MISC: Response future (stream=1) is: jdk.internal.net.http.common.MinimalFuture@660b621a[Not completed] (id=43)
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection processFrame
INFO: FRAME: IN: SETTINGS: length=18, streamid=0, flags=0  Settings: MAX_CONCURRENT_STREAMS=128 INITIAL_WINDOW_SIZE=65536 MAX_FRAME_SIZE=16777215
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection encodeFrame
INFO: FRAME: OUT: SETTINGS: length=0, streamid=0, flags=ACK  Settings:
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection processFrame
INFO: FRAME: IN: WINDOW_UPDATE: length=4, streamid=0, flags=0  WindowUpdate: 2147418112
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection processFrame
INFO: FRAME: IN: SETTINGS: length=0, streamid=0, flags=ACK  Settings:
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection processFrame
INFO: FRAME: IN: HEADERS: length=57, streamid=1, flags=END_HEADERS
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream$HeadersConsumer onDecoded
INFO: MISC: RECEIVED HEADER (streamid=1): :status: 400
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream$HeadersConsumer onDecoded
INFO: MISC: RECEIVED HEADER (streamid=1): server: nginx
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream$HeadersConsumer onDecoded
INFO: MISC: RECEIVED HEADER (streamid=1): date: Fri, 18 Mar 2022 12:10:30 GMT
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream$HeadersConsumer onDecoded
INFO: MISC: RECEIVED HEADER (streamid=1): content-type: text/html; charset=utf-8
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream$HeadersConsumer onDecoded
INFO: MISC: RECEIVED HEADER (streamid=1): content-length: 150
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream incoming
INFO: MISC: handling response (streamid=1)
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream handleResponse
INFO: HEADERS: RESPONSE HEADERS:
    :status: 400
    content-length: 150
    content-type: text/html; charset=utf-8
    date: Fri, 18 Mar 2022 12:10:30 GMT
    server: nginx

März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream completeResponse
INFO: MISC: Completing response (streamid=1): jdk.internal.net.http.common.MinimalFuture@7c8bc6a7[Not completed, 1 dependents] (id=42)
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Exchange lambda$wrapForLog$11
INFO: RESPONSE: (POST https://xxx.yyy.zz/api/v1) 400 HTTP_2 Local port:  56088
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.MultiExchange responseFilters
INFO: MISC: Applying response filters
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.MultiExchange responseFilters
INFO: MISC: Applying jdk.internal.net.http.RedirectFilter@753b7a39
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.MultiExchange responseFilters
INFO: MISC: Applying jdk.internal.net.http.AuthenticationFilter@5d949303
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.MultiExchange responseFilters
INFO: MISC: All filters applied
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream readBodyAsync
INFO: MISC: Reading body on stream 1
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Http2Connection processFrame
INFO: FRAME: IN: DATA: length=150, streamid=1, flags=END_STREAM
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream schedule
INFO: MISC: responseSubscriber.onNext 150
März 18, 2022 1:10:30 NACHM. jdk.internal.net.http.Stream schedule
INFO: MISC: responseSubscriber.onComplete
Resp-Code: 400
Resp-Body: <html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>
 
Zuletzt bearbeitet:

mihe7

Top Contributor
D. h. da läuft nginx als reverse proxy? Du hast noch an einer Stelle Deinen Servernamen im Log stehen, vielleicht nimmst Du den noch raus. Ansonsten sieht der Request für mich zumindest auf den ersten Blick ok aus. Werten die ggf. den User-Agent aus?
 

LimDul

Top Contributor
ich würde jetzt wie gesagt es mal probieren, das mit postman zu senden. Exakt den gleichen Request (Inhalt, Header wie User-Agent etc.). Alternativ auch mit curl oder ähnlichem - aber postman finde ich am komfortablsten.

Damit kann man dann zumindest schon mal rausfinden, wo man weiter schauen muss.
 

ProtonM

Mitglied
Den Request aus dem Browser, also die selbe Maschine, aber ohne Java, liefert das erwartete Ergebnis: 200er Response und das richige JSON-Objekt. Damit konzentriert sich die Suche auf das Java-Laufzeitsystem, das bis zur Systemaktualsierung am 13.03. sauber arbeitete und danach nicht mehr. Aber in der Aktualisierung war das JDK 11.0.14 dabei. Und dort gibt es einen Bugfix mit dem Hinweis "Better HTTP-Transport ". Das lässt mich vermuten, dass ich mir da was eingefangen habe;-(
 

LimDul

Top Contributor
Problem ist halt - Browser sendet nicht den gleichen Request. Andere Header, andere User-Agents etc. Deswegen mal wirklich mit Postman mit den entsprechenden Headern testen.

Ich will nicht zu 100% ausschließen, dass es tatsächlich ein Bug im Openjdk ist. Aber in den meisten Fällen ist es irgendwas Clientseitiges wo ggf. eine Änderung im Openjdk dafür sorgt, dass dort was getriggert wird.

Du kannst folgendes versuchen:
* Alte Openjdk version installieren und damit testen
* Exakt den gleichen Request mit Postman oder ähnlichen Tools senden (und wie gesagt exakt den gleichen Request)
* Wenn machbar den Request unterwegs mitloggen (Bei SSL schwierig) um zu schauen, ob er wirklich so aussieht, wie er soll
* Den Request gegen einen lokalen Dummy Server senden wenn möglich - ob da das Problem auch auftritt.

Wichtig ist bei der Fehleranalyse - jede Vermutung verifizieren oder falsifizieren durch entsprechende exakte saubere Analysen. (Und ich weiß da wo von ich spreche - wir haben eine 1-monatige Fehleranalyse hinter uns, wo wir am Ende alles in Verdacht hatten für HTTP Error 503 zu sorgen, am Ende war es eine Firewall). Man lässt sich bei solchen Analysen sehr leicht durch zufällige zeitliche Zusammenhänge in die Irre führen. Wie gesagt, ausschließen will ich es nicht - ich würde mich aber nicht zu sehr drauf versteifen. Und durch ein simples downgrade des Openjdk ist das ja kein Akt zu probieren. Das sollte ja recht fix machbar sein.
 

ProtonM

Mitglied
Gleichartige Request aus anderen Client-Umgebungen (.net) laufen einwandfrei, sodass ich den Fehler serverseitig nicht sehe. Mit wireshark habe ich den Datenstrom mitgeschnitten, da jedoch alles verschlüsselt abläuft, konnte ich da nichts erkennen. Im Debugger habe ich mir jede Variable angeschaut. Wenn es aber in die Tiefen der Bibliotheksklassen geht, sind meine Möglichkeiten zu Ende.
Ich werde erst mal die JDK-Vorversion installieren. Ich hoffe, die irgendwo greifen zu können.
 

mrBrown

Super-Moderator
Mitarbeiter
Unabhängig davon, dass es mit der älteren Version noch funktioniert, würde ich an deiner Stelle trotzdem versuchen, den Grund dafür zu finden. Das kann gut sein, dass da trotzdem Client-Seitig ein Fehler im Anwendungscode oder Serverseitig irgendein Fehler vorliegt, der eben erst durch die Änderung im Update auffällt.

Dass da ein grundlegender Fehler in allen aktuellen JDK-Versionen steckt halte ich für relativ unwahrscheinlich, das dürfte nach einigen Wochen so große Wellen schlagen, dass man davon überall schon gehört hätte.
 

mihe7

Top Contributor
Unabhängig davon, dass es mit der älteren Version noch funktioniert, würde ich an deiner Stelle trotzdem versuchen, den Grund dafür zu finden.
Ja, es ist schade, dass sich der TE damit zufrieden gibt.

Wir hatten vor ein paar Monaten auch so einen Fall: Kunde meldet, dass Mails nicht mehr versandt werden. Da kamen noch verschiedene Begleitumstände dazu (wie z. B. ein selten genutztes Gmail-Konto), so dass die Fehlersuche sich äußerst aufwendig gestaltete und über mehrere Tage hinzog. Am Ende stellte sich heraus: Java Update, in dem irgendeine TLS-Version standardmäßig deaktiviert wurde... sehr geil.
 

mrBrown

Super-Moderator
Mitarbeiter
Was ich meinte war eher, dass ganze auf deiner Seite weiter zu „untersuchen“.
Requests mal gegen einen Server der einfach nur den Request logt laufen lassen und alt und neu vergleichen, das Ganze möglichst mit curl oder postman o.ä. nachstellen und versuchen den Fehler zu produzieren, sowas in der Art…
 

Ähnliche Java Themen

Neue Themen


Oben