Amá: XML-RPC $HTTP_RAW_POST_DATA unter PHP 5.2.0

Hallo alle zusammen!

Ich wälze schon seit gestern Mittag Foren und zerbreche mir den kopf, aber ich komme einfach nicht darauf.

Ich habe eine Testclient.php und eine Testserver.php auf dem gleichen Server im gleichen Verzeichnis liegen (mittlerweile sogar nachweislich funktionierende Codebeispiele aus php.net). Die PHP-Version ist 5.2.0.

Mein Problem ist folgendes:

Ich bekomme beim Aufruf immer die Meldung 'faultString   server error. method not found.     faultCode   -32601'
Nach einigem hin und her konnte ich das Problem eingrenzen. Hier ist das Problem, dass die Variable $HTTP_RAW_POST_DATA nicht gefüllt ist. Dies ist allerdings ein allgemein bekannter bug. Allerdings brachten auch die Lösungsvorschläge always_populate_raw_post_data auf on zu setzen oder stattdessen file_get_contents('php://input'); zu verwenden kein brauchbares Ergebnis. Sowohl $HTTP_RAW_POST_DATA als auch file_get_contents('php://input')sind bei mir immer leer.

Hat vielleicht von euch jemand noch eine Idee oder sogar schon eine konkrete Lösung wie dieses Problem gefixed werden kann?

Die Dateien sehen wie folgt aus:

/* clienttest.php */
<?php
function do_call($host, $port, $request) {

$fp = fopen('/home/servertest.php', 'r');
    $query = "POST /home/servertest.php HTTP/1.0\nUser_Agent: My Egg Client\nHost: ".$host."\nContent-Type: text/xml\nContent-Length: ".strlen($request)."\n\n".$request."\n";

if (!fputs($fp, $query, strlen($query))) {
        $errstr = "Write error";
        return 0;
    }

$contents = '';
    while (!feof($fp)) {
        $contents .= fgets($fp);
    }

fclose($fp);
    return $contents;
}

$host = 'localhost';
$port = 80;
$request = xmlrpc_encode_request('cycle', 'egg');
$response = do_call($host, $port, $request);
/* do something with $response, e.g. print it */
?>

/* servertest.php */
<?php
function lifecycle($method, $params) {
/* $method = 'cycle', $params = (array of) request parameter(s); $data is also passed from xmlrpc_server_call_method, if we had any data to pass */
    switch($params[0]) {
        case 'egg':
            $reply = 'All eggs will be birds one day.';
        break;
        default:
            $reply = 'That must have been an otheregg';
    }
    return $reply;
}

$server = xmlrpc_server_create();

/* register the 'external' name and then the 'internal' name */
xmlrpc_server_register_method($server, "cycle", "lifecycle");

$request = $HTTP_RAW_POST_DATA; // no you don't need 'always on', and no $_POST doesn't work.

/* the parameters here are 'server, xml-string and user data'.  There's supposed to be an optional 'output options' array too, but I can't get it working :( hence header() call */
$response = xmlrpc_server_call_method($server, $request, null);
header('Content-Type: text/xml');
print $response;

xmlrpc_server_destroy($server);
?>

Vielen Dank schon mal für das Gedanken darüber machen :)

Liebe Grüße,

Amá

  1. Hi,

    function do_call($host, $port, $request) {

    $fp = fopen('/home/servertest.php', 'r');

    Was soll das bewirken - einen HTTP-Request?
    Waere mir neu, dass das so funktionieren wuerde.

    MfG ChrisB

    1. *lach*
      Nein, keine Sorge, bei mir im Skript steht da tatsächlich ne http erreichbare Adresse drin :)
      Nur kann ich die Adresse hier nicht wirklich posten also habe ich einfach mal den nicht funktionsfähigen Pfad reingeschreiben :)

      Das tut er auch alles, nur die Variable ist eben leer. Ich habe wirklich jeden fehler schon ausgeschlossen. Ich habe der Variablen auch schon einen XML-Aufruf gegeben mit dem alles einwandfrei funktionierte. Aber das ist natürlich nicht Sinn und Zweck der Sache, die Variable soll ja von mir nicht im Skript direkt von Hand gesetzt werden :9

      Hi,

      function do_call($host, $port, $request) {

      $fp = fopen('/home/servertest.php', 'r');

      Was soll das bewirken - einen HTTP-Request?
      Waere mir neu, dass das so funktionieren wuerde.

      MfG ChrisB

      1. Moin!

        Nein, keine Sorge, bei mir im Skript steht da tatsächlich ne http erreichbare Adresse drin :)
        Nur kann ich die Adresse hier nicht wirklich posten also habe ich einfach mal den nicht funktionsfähigen Pfad reingeschreiben :)

        Diese willkürliche Ersetzung erschwert uns aber die Fehlersuche.

        Wenn du keine reale Domain benutzen willst, nutze z.B. "example.com", beliebige Namen endend auf ".invalid" oder ".test" etc.

        Abgesehen davon öffnest du dann wohl die HTTP-Ressource zum Lesen (das unterstützt PHP mit seinem url_fopen_wrapper), dann kannst du aber keine POST-Daten dorthin SCHREIBEN (das geht mit fopen grundsätzlich nicht).

        Und dannn wunderst du dich, dass die POST-Variablen leer bleiben?

        - Sven Rautenberg

        --
        "Love your nation - respect the others."
        1. Nun ja, nach allem was ich gelesen habe ist es eine eigenständige Variable die mit POST, etc.. wenig zu tun hat sondern anders gesetzt wird. Kann natürlich auch sein das ich Rasmus, etc.. in den Listins falsch verstanden habe.

          Alles was gemacht wird ist, einen erzeugten XML-Code an eine vordefinierte Funktion zu übergeben die das ganze dann auswertet.

          Und das dies normalerweise funktioniert ist belegt. Als meine eigenen Dateien nämlich dasselbe Problem aufwiesen bin ich auf einen Beispielcode von php.net ausgewichen der nachweislich funktioniert und musste dann feststellen, dass es NICHT an meinem Script lag.

          Deshalb bin ich ja so ratlos. Sogar unser Fachinformatiker steht vor einem Rätsel :(

          Moin!

          Nein, keine Sorge, bei mir im Skript steht da tatsächlich ne http erreichbare Adresse drin :)
          Nur kann ich die Adresse hier nicht wirklich posten also habe ich einfach mal den nicht funktionsfähigen Pfad reingeschreiben :)

          Diese willkürliche Ersetzung erschwert uns aber die Fehlersuche.

          Wenn du keine reale Domain benutzen willst, nutze z.B. "example.com", beliebige Namen endend auf ".invalid" oder ".test" etc.

          Abgesehen davon öffnest du dann wohl die HTTP-Ressource zum Lesen (das unterstützt PHP mit seinem url_fopen_wrapper), dann kannst du aber keine POST-Daten dorthin SCHREIBEN (das geht mit fopen grundsätzlich nicht).

          Und dannn wunderst du dich, dass die POST-Variablen leer bleiben?

          • Sven Rautenberg
  2. echo $begrüßung;

    Ich wälze schon seit gestern Mittag Foren und zerbreche mir den kopf, aber ich komme einfach nicht darauf.

    Diese Information hilft uns aber nicht bei der Beantwortung der Frage. Interessanter wäre, ob du mit einem auf E_ALL gestellten error_reporting mehr hilfreiche Meldungen bekommst, ob du die Rückgabewerte der verwendeten Funktionen überprüft hast, und wie du Inhalte von Variablen testet (hoffentlich (auch) mit var_dump(), denn das erzeugt eine genauere Ausgabe).

    function do_call($host, $port, $request) {
        $fp = fopen('/home/servertest.php', 'r');
        $query = "POST /home/servertest.php HTTP/1.0\nUser_Agent: My Egg Client\nHost: ".$host."\nContent-Type: text/xml\nContent-Length: ".strlen($request)."\n\n".$request."\n";
        if (!fputs($fp, $query, strlen($query))) {

    Du öffnest hier eine "Datei" zum Lesen ('r') und möchtest dann etwas reinschreiben.

    $errstr = "Write error";
            return 0;

    Im Fehlerfall erzeugst du einen String, der aber nirgendwo abgefragt wird, weil du sofort die Funktion verlässt. Hast du mal explizit nachgesehen, ob du von do_call() eine 0 zurückbekommst?

    $request = xmlrpc_encode_request('cycle', 'egg');
    $response = do_call($host, $port, $request);
    /* do something with $response, e.g. print it */
    ?>

    Sieht nicht so aus, trotz des Hinweises im Kommentar.

    $request = $HTTP_RAW_POST_DATA; // no you don't need 'always on', and no $_POST doesn't work.

    Wieder eines dieser beliebten Ich-kopier-mir-die-Variable-mal-um-weil-$request-einfacher-zu-tippen-ist-als-$HTTP_RAW_POST_DATA-Spielchen? Und das obwohl im weiteren Verlauf nur ein einziges Mal auf $request Bezug genommen wird.

    echo "$verabschiedung $name";

    1. Hallo $name :D

      echo $begrüßung;

      Ich wälze schon seit gestern Mittag Foren und zerbreche mir den kopf, aber ich komme einfach nicht darauf.

      Diese Information hilft uns aber nicht bei der Beantwortung der Frage. Interessanter wäre, ob du mit einem auf E_ALL gestellten error_reporting mehr hilfreiche Meldungen bekommst, ob du die Rückgabewerte der verwendeten Funktionen überprüft hast, und wie du Inhalte von Variablen testet (hoffentlich (auch) mit var_dump(), denn das erzeugt eine genauere Ausgabe).

      Das sollte nur zeigen, dass ich mir vorher selbst den Kopf zerbrochen habe und nicht einfach hier reinschreibe damit ich weniger über das Problem nachdenken muss :D

      Var-Dump, etc... habe ich natürlich schon probiert. Er bekommt aber immer nur NULL zurück und error_reporting(E_ALL) hat mir auch keine Fehler aufgezeigt. Ich habe wirklich nur das Problem, dass diese Variable nicht gefüllt ist und er deshalb die gewünschte Anfrage nichtt ausführen kann.

      Du öffnest hier eine "Datei" zum Lesen ('r') und möchtest dann etwas reinschreiben.

      Hineinschreiben möchte ich auch nichts, vor allem da dies ja bei einem HTTP-Request meines Wissens auch nicht geht. Ich möchte diese Datei eigentlich nur lesen (wie es hier auch erledigt wird) und dann mit einem in der Clientdatei erzeugtem XML die Serverdatei dazu bringen eine Funktion auszuführen und mit das Ergebnis zu geben.

      Im Fehlerfall erzeugst du einen String, der aber nirgendwo abgefragt wird, weil du sofort die Funktion verlässt. Hast du mal explizit nachgesehen, ob du von do_call() eine 0 zurückbekommst?

      Ja, habe ich. Siehe letzte Zeile von clienttest.php (echo $response)
      Dort wird aber keine 0 ausgegeben sondern wie ich vorher schon geschrieben habe 'faultString   server error. method not found.     faultCode   -32601'

      Wieder eines dieser beliebten Ich-kopier-mir-die-Variable-mal-um-weil-$request-einfacher-zu-tippen-ist-als-$HTTP_RAW_POST_DATA-Spielchen? Und das obwohl im weiteren Verlauf nur ein einziges Mal auf $request Bezug genommen wird.

      Solange es funktioniert, wo liegt da das Problem?^^

      Aber trotzdem danke für die Antwort

      Liebe Grüße

      Amá

      1. Moin!

        Du öffnest hier eine "Datei" zum Lesen ('r') und möchtest dann etwas reinschreiben.

        Hineinschreiben möchte ich auch nichts

        Aber genau das hast du programmiert!

        vor allem da dies ja bei einem HTTP-Request meines Wissens auch nicht geht.

        Du kannst mit fopen keine POST-Requests machen, auch wenn allow_url_fopen erlaubt ist, und als Argument an fopen eine HTTP-URL übergeben wird.

        Ich möchte diese Datei eigentlich nur lesen

        Die Datei, die du öffnest, wie in deinem Quellcode dargestellt, enthält den Skriptcode der Server-PHP-Datei. Das kann nicht gewollt sein, weil der Servercode dadurch nicht ausgeführt wird.

        Was du aber tatsächlich tust, verrätst du uns bislang nicht.

        (wie es hier auch erledigt wird) und dann mit einem in der Clientdatei erzeugtem XML die Serverdatei dazu bringen eine Funktion auszuführen und mit das Ergebnis zu geben.

        Wie gesagt: Selbst wenn du an fopen() tatsächlich eine HTTP-URL übergeben würdest, würde das dadurch angestoßene Serverskript immer noch keine POST-Daten erhalten und kann deshalb nicht wie gewünscht funktionieren.

        - Sven Rautenberg

        --
        "Love your nation - respect the others."
        1. Moin!

          Du öffnest hier eine "Datei" zum Lesen ('r') und möchtest

          Ich habe mittlerweile meine Lösung. Das reinschreiben, etc... hat nichts zur Sache getan. Nach einer geringfügigen Änderung an meiner Variablen query funktionierte plötzlich alles...

          Es sind eben immer die kleinen Dinge die man gerne übersieht. Und da ich dies nur als Beispiel bauen musste und jetzt mit der eigentlich Aufgabe anfangen kann brauche ich es sowieso nicht mehr. Ab jetzt darf ich nämlich das richtige PEAR-Package benutzen.

          Azubi eben...immer erst so arbeiten bevor man die leichteren Hilfsmittel verwenden darf.

          Schönen Abend wünsche ich euch noch!

          Liebe Grüße,

          Amá

      2. echo $begrüßung;

        Ich wälze schon seit gestern Mittag Foren und zerbreche mir den kopf, aber ich komme einfach nicht darauf.
        Diese Information hilft uns aber nicht bei der Beantwortung der Frage.
        Das sollte nur zeigen, dass ich mir vorher selbst den Kopf zerbrochen habe und nicht einfach hier reinschreibe damit ich weniger über das Problem nachdenken muss :D

        Schön, aber diese einfache Aussage kann ja sowieso keiner nachprüfen. :-) Wenn du stattdessen verlinkt hättest, was du bereits gesehen hast, dann könnte man da hingehen und die dort gegebenene Tipps auch bewerten und ggf. auch nachvollziehen, was du bereits probiert hast.

        Du öffnest hier eine "Datei" zum Lesen ('r') und möchtest dann etwas reinschreiben.
        Hineinschreiben möchte ich auch nichts, vor allem da dies ja bei einem HTTP-Request meines Wissens auch nicht geht.

        Und fputs() ist keine Funktion zum Schreiben?

        Was ist denn, wenn du das Original mal ausführst? Da steht zwar auch das sinnlose $errstr = "Write error"; return 0; drin, aber wenigstens wird dort fsockopen() statt fopen() verwendet.

        Wieder eines dieser beliebten Ich-kopier-mir-die-Variable-mal-um-weil-$request-einfacher-zu-tippen-ist-als-$HTTP_RAW_POST_DATA-Spielchen? Und das obwohl im weiteren Verlauf nur ein einziges Mal auf $request Bezug genommen wird.
        Solange es funktioniert, wo liegt da das Problem?^^

        Das Problem ist, dass man einer $normalen_Variable ihre Herkunft nicht ansieht. Man muss erstmal nachforschen, woher der Wert denn kommt, der darin steht. Außerdem ist die implizite Benutzereingaben-sind-generell-als-gefährlich-zu-betrachten-Warnung bei den bekannten $_POST/$_GET usw. deutlich sichtbarer als bei der $normalen_Variable.

        echo "$verabschiedung $name";