Knut: Kann ich Javascript eine PHP-Exception mitteilen?

Hallo...

Ich versuche gerade, PHP und Javascript unter einen Hut zu bringen.

Und zwar habe ich clientseitig eine Ausgabe, die etwaige Fehler ausgeben soll.

Nun ist mir (denke ich) klar, wie ich PHP-seitig mit Exceptions umgehe, soll heißen, ich installiere einen try-Block, und wenn dieser eine Exception wirft, fange ich sie mit einem catch-Block. Das passiert aber alles serverseitig, schicke ich eine Antwort an den Client, dann immer mit ECHO (...?).

Wonach ich nun aber suche, ist eine Methode, mit der ich Javascript clientseitig mitteile, dass ein Fehler passiert ist, damit ich clientseitig die mitgesandte Fehlernachricht dann in die Ausgabe einspielen kann, etwa in die Richtung

// ACHTUNG DUMMYCODE ...

if (response.exception) {
	ausgabe.innerText = exception.message;
}
else {
	// WAS AUCH IMMER IM ERFOLGSFALL ZU TUN IST...
}

(Ich könnte natürlich auch z.B. ein Array zurückschicken, mit key Success oder Failure und Value mit der Nachricht, aber kann ich Javascript nicht prinzipiell mitteilen, welche Art von Antwort hier zurückkommt?)

P.S.: Achtung, ich rede hier NICHT von Statuscodes.

Ich gehe von einem prinzipiellen 200 - Success aus.

Danke euch, Knut.

  1. Moin Knut,

    Nun ist mir (denke ich) klar, wie ich PHP-seitig mit Exceptions umgehe, soll heißen, ich installiere einen try-Block, und wenn dieser eine Exception wirft, fange ich sie mit einem catch-Block. Das passiert aber alles serverseitig, schicke ich eine Antwort an den Client, dann immer mit ECHO (...?).

    Ja, eine andere (sinnvolle) Möglichkeit gibt es nicht.

    Wonach ich nun aber suche, ist eine Methode, mit der ich Javascript clientseitig mitteile, dass ein Fehler passiert ist, damit ich clientseitig die mitgesandte Fehlernachricht dann in die Ausgabe einspielen kann, etwa in die Richtung

    // ACHTUNG DUMMYCODE ...
    
    if (response.exception) {
    	ausgabe.innerText = exception.message;
    }
    else {
    	// WAS AUCH IMMER IM ERFOLGSFALL ZU TUN IST...
    }
    

    (Ich könnte natürlich auch z.B. ein Array zurückschicken, mit key Success oder Failure und Value mit der Nachricht, aber kann ich Javascript nicht prinzipiell mitteilen, welche Art von Antwort hier zurückkommt?)

    Die Response an sich kennt keine Fehler/Exceptions. Neben dem Content-Type oder einer entsprechenden Datenstruktur bleibt dir noch ein entsprechender HTTP-Statuscode mit der Exception im Response-Body.

    P.S.: Achtung, ich rede hier NICHT von Statuscodes.

    Ich gehe von einem prinzipiellen 200 - Success aus.

    Und das kann im Fehlerfall kein entsprechender anderer sein?

    Viele Grüße
    Robert

    1. Hallo Robert,

      Und das kann im Fehlerfall kein entsprechender anderer sein?

      Das sollte im Problemfall ein anderer sein. Man muss allerdings schauen, was der Grund für die Exception ist.

      Wenn am Server tatsächlich etwas gravierend schief gegangen ist, ist ein 5xx-er Status in Ordnung. Ein 4xx auch, falls der Client im Request Müll geschickt hat und die Exception deswegen flog.

      Wenn die Exception fachlicher Natur ist, ist ein Status 200 durchaus sinnvoll. Denn der HTTP Status meldet den technischen Erfolg des Requests, nicht den fachlichen Erfolg.

      Man muss dann aber die Rückgabe an den Client so gestalten, dass der Client bei Statuscode 200 (=technisch ok) zwischen "fachlich ok" und "fachlich fehlerhaft" unterscheiden kann.

      Wie man das gestaltet, hängt von der Natur des aufgerufenen Service ab. Was liefert er? JSON? In dem Fall kann man das JSON-Objekt so gestalten, dass es ein status-Property enthält, und damit weitermachen.

      Es gäbe auch noch die Möglichkeit, einen HTTP Header zu setzen. Der sollte dann mit einem "X-" beginnen, weil's ein custom header ist. Und man muss das PHP so schreiben, dass sämtliche Ausgaben gepuffert sind, damit man einen Header setzen kann. Und dann ist mit

      header("X-Errorcode: $myErrorCode");
      

      jede Schweinerei möglich. Die Response-Header kann man in JavaScript abfragen, bei fetch über die headers-Eigenschaft der Response und bei XMLHttpRequest über die getResponseHeader Methode.

      Je nach Errorcode kann man festlegen, dass der gelieferte Content unterschiedliche Bedeutungen hat. FehlerTEXTE in den Headern abzulegen ginge auch, sie müssen dann aber URI-codiert werden, soweit ich weiß. Und die Länge sollte unter 8K bleiben, nicht wegen HTTP, sondern wegen des Webservers.

      Rolf

      --
      sumpsi - posui - obstruxi
    2. Okay, du hast eigentlich recht.

      Die richtige Herangehensweise ist tatsächlich, das über den Status Code zu regeln. Bin davor etwas zurückgeschreckt, da in der Konsole dann ja (logischerweise) tatsächlich ein Fehler mit großem bösen roten Rufzeichen ausgewiesen wird, aber das ist ja dann eigentlich tatsächlich der Sinn der ganzen Übung...

      Gesetzt der Fall, ich hätte ein Eingabefeld, das clientseitig auf 12 chars beschränkt ist. Ein Client hebelt das in den Entwicklertools aus und sendet 24 chars durch den Äther. Welchen Statuscode hieltest du für angemessen?

      400 - Bad Request?

      406 - Not Acceptable?

      412 - Precondition Failed?

      (Anyway, werde mich wohl auch selber noch ein wenig mit der Thematik der Status Codes beschäftigen...)

      Danke für die Hilfe. Knut.

      1. P.S.: @Rolf B.

        Okay, also liege ich doch falsch -

        • dass die unerlaubte clientseitige Mutation z.B. eines Input Feldes NICHT über Status Codes vom Server zurückgewiesen werden sollte?
        1. Hallo Knut,

          doch, das schrieb ich doch. Wenn der Client Müll sendet, ist ein 4xx Statuscode korrekt.

          Feldlängenüberschreitungen, die nur durch Manipulation des Requests (oder einen Client-Bug) möglich sind, rechtfertigen HTTP 400 Bad Request.

          412 hat eine andere Bedeutung, 406 auch.

          Rolf

          --
          sumpsi - posui - obstruxi
      2. n'Abend Knut,

        Gesetzt der Fall, ich hätte ein Eingabefeld, das clientseitig auf 12 chars beschränkt ist. Ein Client hebelt das in den Entwicklertools aus und sendet 24 chars durch den Äther. Welchen Statuscode hieltest du für angemessen?

        400 - Bad Request?

        wäre aus meiner Sicht die beste Antwort.
        [EDIT: Zumindest dann, wenn man sich nicht die Mühe machen möchte zu erraten, was die User-Eingabe sinnvollerweise bedeuten könnte, und dann eine darauf angepasste Antwort senden will. Dann wäre 200 wieder okay. Das wäre dann die Google-Methode Meinten Sie vielleicht ...?]

        Möge die Übung gelingen
         Martin

        --
        Darmstadt? Ist das nicht da, wo immer der Urologen-Kongress tagt?
      3. Moin Knut,

        Die richtige Herangehensweise ist tatsächlich, das über den Status Code zu regeln. Bin davor etwas zurückgeschreckt, da in der Konsole dann ja (logischerweise) tatsächlich ein Fehler mit großem bösen roten Rufzeichen ausgewiesen wird, aber das ist ja dann eigentlich tatsächlich der Sinn der ganzen Übung...

        was für einen Content-Type erwartet denn dein Javascript normalerweise?

        Gesetzt der Fall, ich hätte ein Eingabefeld, das clientseitig auf 12 chars beschränkt ist. Ein Client hebelt das in den Entwicklertools aus und sendet 24 chars durch den Äther. Welchen Statuscode hieltest du für angemessen?

        400 - Bad Request?

        Nach der Beschreibung im Wiki diesen (400).

        406 - Not Acceptable?

        „Die Ressource kann nicht in einer vom Client angefragten Form geliefert werden.“ → passt nicht wirklich

        412 - Precondition Failed?

        „Eine vom Client vorgegebene Bedingung ist nicht erfüllbar.“ → Deine Bedingung ist aber vom Server vorgegeben.

        Viele Grüße
        Robert

      4. Tach!

        Die richtige Herangehensweise ist tatsächlich, das über den Status Code zu regeln.

        Generell solltest du nicht zu viel Aufmerksamkeit auf den Statuscode legen. Menschen lesen den Statuscode nicht, die lesen eine Fehlermeldung in der Response. Was in der Konsole steht, interessiert sie auch nicht. In aller Regel wird der Request ja gelesen und beantwortet werden können.

        HTTP-Statuscodes sind eher dann sinnvoll, wenn auch Maschinen die Antwort auswerten sollen. Zum Beispiel 404/410, um Suchmaschinen mitzuteilen, wenn eine Artikelnummer in einem Webshop nicht (mehr) verfügbar ist, oder ein Artikel in einem Blog.

        Die Frage ist nicht neu, es gibt dazu einige gute Antworten im Netz. Abschließend klären lässt sie sich nicht. Auch hat sich die Bedeutung der 400 im Laufe der Zeit geändert. Früher bezog sie sich nur auf den HTTP-Request, heutzutage auch auf den Payload. Aber es geht dabei immer noch um technische Aspekte des Requests, nicht um inhaltliche.

        dedlfix.

      5. Gesetzt der Fall, ich hätte ein Eingabefeld, das clientseitig auf 12 chars beschränkt ist. Ein Client hebelt das in den Entwicklertools aus und sendet 24 chars durch den Äther. Welchen Statuscode hieltest du für angemessen?

        400 - Bad Request?

        406 - Not Acceptable?

        412 - Precondition Failed?

        Je nach Gustus 403 oder 404. Man kann sich auch einen Spaß mit 418 machen. Grund: Es ist nicht mein Job, Angreifer genau, wahrheitsgemäß und umfassend auf die Ursache deren Scheiterns hinzuweisen. Angriffen geht regelmäßig ein Set von bekannten Penetrationstests voraus… Sperrt man die dann per Firewall aus suchen die sich einen woanders einen Idiot. (Freilich sollte man an eine „whitelist“ denken - etwa die IPs der Rechner/Netzwerke auf/in denen man gewöhnlich entwickelt.

        Auf bestimmte Versuche (e.g. Zugriffe auf /wp-admin/ oder /phpmyadmin/) reagiere ich ergo sogar, in dem ich die Angreifer-IP eine Weile lang sperre.

        1. Hallo Raketenwilli,

          warum nicht 402? Dann kann der Hacker gleich eine Ordnungsstrafe entrichten!

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Moin Rolf,

            warum nicht 402? Dann kann der Hacker gleich eine Ordnungsstrafe entrichten!

            bei manchen offensichtlichen Fehlern, die „dumme Bots“ auslösen, sende ich den sogar 😈

            Viele Grüße
            Robert

  2. Sowas geht im Kern etwa so: https://home.fastix.org/Tests/sysview.js.php

    Wenn es echte Fehler sind musst Du natürlich über deren Behandlung in PHP in PHP nachdenken, denn es nützt Dir nur wenig, wenn PHP abbricht.

    try ... catch und natürlich die Seiten über „Fehlerbehandlung und Protokollierung“ sind Deine „Freunde“.

    Was damit nicht geht: Syntax-Fehler abfangen. Du musst auf den Statuscode 500 reagieren, wenn Du das vollständig haben willst. Freilich kannst Du auf dem Server (z.B. per HTACCESS) eine spezielle Fehlerseite einrichten (von der niemand behauptet, dass es HTML sein muss, das kann also ach JSON sein) - die muss dann aber statisch sein.

    Ansonsten kannst Du natürlich noch prüfen, ob JSON.decode() funktioniert und, wenn nicht, annehmen, dass Du eine Fehlermeldung hast und diese in JS eben anders behandeln…