HTTP Kann man den Raw HTTPS Request irgendwie ausgeben lassen?

Thallius

Top Contributor
Hi,

wir haben eine externe Firma die für uns eine REST API zu Ihrem Produkt programmiert. Leider sind die Kollegen nicht so richtig gut drauf und ich muss ihnen jeden Bug auf dem Silbertablett servieren bevor sie sich darum kümmern.

Nun habe ich etwas extrem seltsames:

Es gibt ein Kommando zum Erstellen eines Library Entriss in deren Datenbank. Dazu sende ich einen POST Request an eine URL mit einem JSON Body der den Eintrag enthält. Funktioniert soweit gut.
Ein Eintrag sieht dabei so aus:

Code:
{
    "location":
    {
        "stackID":1285
    },
    "questions":
    [
        {
            "text":"a-b-c",
            "complianceID": "Yes"
        }
    ],
    "answer":
    {
        "text":" ",
        "footnotes":[]
    },
    "tags":
    [
        "a-b-c",
        "d-e",
        "x",
        "y"
    ],
    "languageCode":"en"
}

Wenn ich diesen Request über Postman abschicke funktioniert er einwandfrei. Sende ich den gleichen Request aus meiner App heraus mit Java, dann bekomme ich einen ErrorCode 400. Ich konnte herausfinden, dass es an dem Bindestrich in questions -> text liegt. Steht in diesem Feld ein Bindestrich gibt es einen ErrorCode 400 entferne ich den Bindestrich geht es. Wie gesagt NUR aus meiner App heraus. Mit Postman ist es kein Problem.

Ich habe den erzeugten JSON-String in meiner App kopiert und in den Postman gepackt und es geht!

Ich müßte nun also irgendwie Debuggen können was an meinem JAVA Request anders ist.
Beim Header sehe ich keinen Unterschied. Postman:

Code:
Content-Type: application/json
Authorization: Bearer xxx
User-Agent: PostmanRuntime/7.26.5
Accept: */*
Postman-Token: 4b36f457-b429-40dd-ad1b-19a1bbf504e9
Host: apiurl
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 332

Mein Code zum Header erzeugen:

Code:
            con.setRequestMethod("POST");
            con.setRequestProperty("Authorization", token.type + " " + token.token);
            con.setRequestProperty("User-Agent", "PostmanRuntime/7.3.0");
            con.setRequestProperty("Accept", "*/*");
            con.setRequestProperty("Host", apiURL);
            con.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
            con.setRequestProperty("Connection", "keep-alive");
            con.setRequestProperty("Content-Type", "application/json");

und der Code zum Erzeugen des Body:

Code:
            con.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());

            wr.writeBytes(json);
            wr.flush();
            wr.close();

Wie komme ich hier also weiter?

Gruß

Thallius
 
In jedem Fall ist DataOutputStream nahezu immer die falsche Wahl, reicht es vielleicht schon, den nicht zu benutzten?
 
Habe auch schon

Code:
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(con.getOutputStream(), StandardCharsets.UTF_8));
            bw.write(json);
            bw.flush();
            bw.close();

versucht. Keine Änderung
 
Ok ich korrigiere mich. Nachdem ich es jetzt nochmal probiert habe geht es mit BufferWriter. Habe in der Zwischenzeit soviel rumprobiert das ich wohl noch etwas anderes geändert haben muss
 
Evtl. eine kleine Anmerkung bezüglich "Debugging / Prüfen von http Requests und Antworten":
Ein Tool, das ich in der Vergangenheit eingesetzt habe, ist Fiddler. Das agiert als Proxy und erlaubt die Analyse und Veränderung von Requests.
Dann reicht es, dass man die App mit dem entsprechenden Proxy aufruft (also -DproxyHost und -DproxyPort).

In dem Fall wäre meine Erwartungshaltung, dass man dann die "Protokoll Bytes" des DataOutputStreams gut hätte sehen können ...
 
Evtl. eine kleine Anmerkung bezüglich "Debugging / Prüfen von http Requests und Antworten":
Ein Tool, das ich in der Vergangenheit eingesetzt habe, ist Fiddler. Das agiert als Proxy und erlaubt die Analyse und Veränderung von Requests.
Dann reicht es, dass man die App mit dem entsprechenden Proxy aufruft (also -DproxyHost und -DproxyPort).

In dem Fall wäre meine Erwartungshaltung, dass man dann die "Protokoll Bytes" des DataOutputStreams gut hätte sehen können ...

danke das halte ich mal im Hinterkopf für das nächste Problem
 
Mit Bordmitteln kann man das Plattform-Logging verwenden. Um beispielsweise HttpURLConnection zu loggen muss man den Loglevel von sun.net.www.protocol.http.HttpURLConnection einstellen (man kann auch global das Loglevel des Root-Loggers ändern):

Java:
import java.net.*;
import java.util.*;
import java.util.logging.*;

public class Test {
    static void performRequest() throws Exception {
        HttpURLConnection con = (HttpURLConnection) 
                new URL("https://www.wikipedia.de").openConnection();
        con.setRequestProperty("User-Agent", "PostmanRuntime/7.3.0");
        System.out.println(con.getResponseCode());
    }

    public static void main(String[] args) throws Exception {
        performRequest();

        ConsoleHandler handler = new ConsoleHandler();
        handler.setLevel(Level.ALL);
        Logger log = LogManager.getLogManager().getLogger("sun.net.www.protocol.http.HttpURLConnection");
        log.addHandler(handler);
        log.setLevel(Level.FINE);

        performRequest();
    }
}

liefert etwa:
Code:
200
Sep 28, 2020 2:52:20 PM sun.net.www.protocol.http.HttpURLConnection writeRequests
FEIN: sun.net.www.MessageHeader@a484745 pairs: {GET / HTTP/1.1: null}{User-Agent: PostmanRuntime/7.3.0}{Host: www.wikipedia.de}{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}{Connection: keep-alive}
Sep 28, 2020 2:52:20 PM sun.net.www.protocol.http.HttpURLConnection getInputStream0
FEIN: sun.net.www.MessageHeader@1e8b4066 pairs: {null: HTTP/1.1 200 OK}{Server: nginx/1.6.2}{Date: Mon, 28 Sep 2020 12:52:20 GMT}{Content-Type: text/html; charset=UTF-8}{Transfer-Encoding: chunked}{Connection: keep-alive}
200

Für SSL-Debugging kann man die System-Property -Djavax.net.debug=all setzen. Das produziert sehr viel Output.
 

Neue Themen


Zurück
Oben