pl: XML Rpc

Him ist eine solche Datenstruktur sinnvoll?

$VAR1 = {
          'params' => [
                      {
                        'param' => [
                                   {
                                     'value' => [
                                                {
                                                  'string' => [
                                                              '1'
                                                            ]
                                                }
                                              ]
                                   },
                                   {
                                     'value' => [
                                                {
                                                  'string' => [
                                                              'xmlrpc-example'
                                                            ]
                                                }
                                              ]
                                   },
                                   {
                                     'value' => [
                                                {
                                                  'string' => [
                                                              'example-password'
                                                            ]
                                                }
                                              ]
                                   },
                                   {
                                     'value' => [
                                                {
                                                  'struct' => [
                                                              {
                                                                'member' => [
                                                                            {
                                                                              'value' => [
                                                                                         {
                                                                                           'int' => [
                                                                                                    '41'
                                                                                                  ]
                                                                                         }
                                                                                       ],
                                                                              'name' => [
                                                                                        'post_id'
                                                                                      ]
                                                                            }
                                                                          ]
                                                              }
                                                            ]
                                                }
                                              ]
                                   }
                                 ]
                      }
                    ],
          'methodName' => [
                          'wp.getComments'
                        ]
        };

  1. Das Beispiel ist von hier, bekloppter gehts kaum.

    Sinnvoll wäre z.B.

    $params = {
        methodName => 'wp.getComments',
        Blog_Id    => 1,
        user       => 'xmlrpc-example'
        pass       => 'example-password',
        post_id    => 41 
    };
    

    da stecken dieselben Informationen drin und für eine Datenübertragung braucht dafür kein Mensch XML, das lässt sich auf einem stinknormalen Parameterstring abbilden.

    PS: Die unter o.g. Link gezeigte Response ist noch bescheuerter, aus <params> <param> <value> <array> <data> <value> <struct> <member>

    würden sich völlig unnütze Keys ergeben. So nach dem Motto, wer mit Referenzen nicht umgehen kann, verstecke seine Daten in XML.

    Nette Spielerei

    1. Das Beispiel ist von hier, bekloppter gehts kaum.

      Sinnvoll wäre z.B.

      $params = {
          methodName => 'wp.getComments',
          Blog_Id    => 1,
          user       => 'xmlrpc-example'
          pass       => 'example-password',
          post_id    => 41 
      };
      

      da stecken dieselben Informationen drin und für eine Datenübertragung braucht dafür kein Mensch XML, das lässt sich auf einem stinknormalen Parameterstring abbilden.

      Hast du die Usage-API gesehen? Als API-Nutzer kommt man mit der Verbosität von XML-RPC überhaupt nicht in Berühgung:

      <?php
      $status = $rpc->query(
          "wp.getComments",   // method name
          "1",                // blog id
          "xmlrpc-example",   // username
          "example-password", // password
          array(
              "post_id"   => 41
          )
      );
      
      1. Hast du die Usage-API gesehen? Als API-Nutzer kommt man mit der Verbosität von XML-RPC überhaupt nicht in Berühgung:

        Aber ja doch, das ändert jedoch auch nichts an der idiotischen Verpackung ;)

        Meine Güte, ich mach schon seit Jahren Rpc und Remote-Datenmanagement auf meinen Servern, es gibt weißgott andere Möglichkeiten Daten zu verpacken. Und sowas hier:

        <methodResponse>
          <params>
            <param>
              <value>
              <array><data>
          <value><string>system.multicall</string></value>
        

        Würde rein formal eine Datenstruktur wie folgt ergeben:

        $response = {
           params => {
               param => {
                  value => {
                     array => {
                        string => ['system.multicall','demo.sayHello', ...]
                     }
                  }
               }
           }
        };
        

        da frag ich mich schon was sich der Meister dabei gedacht hat: Da wird das Auspacken der Daten zu einer Sex-Orgie ;)

        Lachgas oder Reizgas, das ist hier die Frage....

        1. da frag ich mich schon was sich der Meister dabei gedacht hat

          Dann frag ihn anstatt hier über ihn herzuziehen.

        2. Tach,

          da frag ich mich schon was sich der Meister dabei gedacht hat

          er wollte ein explizit menschenlesbares XML-Format zum Transport von RPC schaffen. Dein Perl-Array ist zwar auch nett, aber erfüllt nicht die Anforderungen, die gestellt waren.

          mfg
          Woodfighter

          1. da frag ich mich schon was sich der Meister dabei gedacht hat

            er wollte ein explizit menschenlesbares XML-Format zum Transport von RPC schaffen. Dein Perl-Array ist zwar auch nett, aber erfüllt nicht die Anforderungen, die gestellt waren.

            Das Perl-Array (Hash) ist die Datenabstraktion und nicht eine Sequenz die gesendet wird. Ich hatte ja dazu geschrieben, dass zum Serialisieren dieser lächerlichen paar Werte (Methodname, Parameter) die Serialisierung in eine Sequenz mit dem Content-Type: application/x-www-form-urlencoded vollkommen reichen würde was einem stinknormalen HTTP-Request-Parameterstring entsprechen würde.

            Andererseits ist es sicher auch möglich, aus

            $params = {
                methodName => 'wp.getComments',
                Blog_Id    => 1,
                user       => 'xmlrpc-example'
                pass       => 'example-password',
                post_id    => 41 
            };
            

            einen XML-String zu erzeugen und diesen nicht so idiotisch zu verschachteln wie das die wp-Kollegen machen. Das ist einfach nur bekloppt. Und da ohnehin nur eine Liste von Werten zu übertragen sind, würde dazu sogar ein CSV-String genügen, mit oder ohne Percent-Encoding.

            1. Tach,

              Andererseits ist es sicher auch möglich, aus

              $params = {
                  methodName => 'wp.getComments',
                  Blog_Id    => 1,
                  user       => 'xmlrpc-example'
                  pass       => 'example-password',
                  post_id    => 41 
              };
              

              einen XML-String zu erzeugen und diesen nicht so idiotisch zu verschachteln wie das die wp-Kollegen machen. Das ist einfach nur bekloppt.

              nein, es ist nötig um es explizit menschenlesbar und von Menschen auf Fehler überprüfbarer zu machen. Dass XML im allgemeinen und im speziellen XML-RPC sehr verbose ist, ist bekannt (lt. Wikipedia ist diese Kritik an XML-RPC fast so alt wie das Format selber) aber kein Problem. Das ganze ist gut komprimierbar und solange alles funktioniert, muss sich niemand damit beschäftigen wie die Serialisierung aussieht, weil es genug fertige Implementierungen in allen verbreiteten Sprachen gibt. Ich würde niemandem empfehlen, heutzutage etwas in XML-RPC/SOAP zu bauen, aber das Protokoll, seine Vor- und Nachteile sind halt so wie sie sind und es wird ja auch immer mehr durch Dinge wie REST abgelöst.

              mfg
              Woodfighter

              1. nein, es ist nötig um es explizit menschenlesbar und von Menschen auf Fehler überprüfbarer zu machen.

                Absurd. Auf solche Ideen kommen wahrscheinlich nur Leute, die noch nie auch nur irgendeinen Serializer mal selbst entwickelt haben. CRC u.a. Checksummenverfahren sind da üblich um fehlerfreie Übertragungen abzusichern.

                DfÜ mit Sichtkontrolle, ymmd ;)

                1. Tach,

                  nein, es ist nötig um es explizit menschenlesbar und von Menschen auf Fehler überprüfbarer zu machen.

                  Absurd. Auf solche Ideen kommen wahrscheinlich nur Leute, die noch nie auch nur irgendeinen Serializer mal selbst entwickelt haben. CRC u.a. Checksummenverfahren sind da üblich um fehlerfreie Übertragungen abzusichern.

                  nein, außerdem hast du nicht verstanden, welche Fehler gemeint sind.

                  Ich greife mal auf dein Beispiel zurück, um Fehler aufzuzeigen, die in XML-RPC leicht und deiner Darstellung schwer zu sehen wären:

                  $params = {
                      methodName => 'wp.getComments',
                      Blog_Id    => 1,
                      user       => 'xmlrpc-example'
                      pass       => 'example-password',
                      post_id    => 41 
                  };
                  

                  In meiner Spec steht, dass Blog_Id ein String sein soll, aber sehe ich auf Anhieb, dass hier die Anführungszeichen fehlen? Und post_id soltle eigentlich ein Double sein, und hier fehlte der abschließende Punkt. In XML-RPC ist das ganze ausgeschrieben und viel leichter zu sehen.

                  mfg
                  Woodfighter

                  1. Datentypen in der Sequenz zu kodieren ist überflüssig, weil die Funktion, welche aufzurufen ist, die Datentypen kennt.

                    $r->update(blog_id => 1, title => ...);
                    

                    D.h., die Methode update() wird das Argument blog_id schon so verwenden, wie ich das will.

                    1. Tach,

                      Datentypen in der Sequenz zu kodieren ist überflüssig, weil die Funktion, welche aufzurufen ist, die Datentypen kennt.

                      das ist einer der Fälle, wo ich mir nicht sicher bin, ob du überhaupt versuchst zu verstehen, was andere dir antworten.

                      mfg
                      Woodfighter

                      1. Tach,

                        Datentypen in der Sequenz zu kodieren ist überflüssig, weil die Funktion, welche aufzurufen ist, die Datentypen kennt.

                        das ist einer der Fälle, wo ich mir nicht sicher bin, ob du überhaupt versuchst zu verstehen, was andere dir antworten.

                        Hier meine Antwort

                    2. Wenns unbeding sein muss: Meine Serializer können 255 Datentypen kodieren, von undef, über Leerstring bis float. Sowas braucht nicht unbedingt XML. CSV-kodiert sähe sowas z.B. so aus für einen Hash mit typisierten Werten:

                      methodname;str;update;articleid;int;123;preis;float;11.99;currency;str;EUR;descr;base64;ABCD==
                      

                      und siehe da, human ist das auch (außer base64). Einfache Prüfung: Die Anzahl der Array-Elemente nach dem Splitten an ; muss durch 3 teilbar sein.

                      1. Tach,

                        Wenns unbeding sein muss: Meine Serializer können 255 Datentypen kodieren, von undef, über Leerstring bis float. Sowas braucht nicht unbedingt XML. CSV-kodiert sähe sowas z.B. so aus für einen Hash mit typisierten Werten:

                        methodname;str;update;articleid;int;123;preis;float;11.99;currency;str;EUR;descr;base64;ABCD==
                        

                        und siehe da, human ist das auch (außer base64). Einfache Prüfung: Die Anzahl der Array-Elemente nach dem Splitten an ; muss durch 3 teilbar sein.

                        und jetzt mach noch XML draus und du bist schon fast wieder bei XML-RPC.

                        mfg
                        Woodfighter

                        1. und jetzt mach noch XML draus und du bist schon fast wieder bei XML-RPC.

                          Wieso das denn!? Wenn ich die Sequenz zum Übertragen fertig hab, müsste ich, um XML daraus zu erzeugen, die Sequenz wieder deserialisieren, also in einen Hash umwandeln und diesen Hash dann wieder so serialisieren, dass eine XML-Sequenz entsteht.

                          Also, nochmal die Rolle einer Sequenz:

                          Hash(Randon Acccess) <=> Sequenz(Transport) <=> Hash(Random Access)
                          
                          Wobei: Sequenz(Transport) ist 
                          
                          application/x-www-form-urlencoded 
                             ||  
                          multipart/form-data
                             ||
                          application/xml
                             ||
                          application/json
                             ||
                          eine/eigenentwicklung
                          

                          Aber nicht, dass ich das wieder jedem Einzelnen hier erklären muss ;)

                          PS: Statt libwww mit Dutzenden Objekten und Klassen ist die API meines Module einfacher:

                          my $r = HTTPRequest->common(
                              host => 'www.stadt-oppenheim.de',
                              uri  => '/xmlrpc.php',
                              method => 'POST',
                              content => do{local $/ = undef; <DATA>}
                          );
                          
                          print $r; # Object to_String()
                          
                          __DATA__
                          <?xml version="1.0"?>
                          <methodCall>
                              <methodName>system.listMethods</methodName>
                          </methodCall>
                          

                          Aber für WordPress mach ich das ja sowieso nicht. Und das Funktionsnamen Strings sind... in Perl dürfen die nichteinmal mit ner Ziffer beginnen.

                          1. Aber nicht, dass ich das wieder jedem Einzelnen hier erklären muss ;)

                            Ne, das will hier wirklich keiner.

                          2. Tach,

                            und jetzt mach noch XML draus und du bist schon fast wieder bei XML-RPC.

                            Wieso das denn!?

                            weil das eine der Forderungen an XML-RPC war.

                            mfg
                            Woodfighter

                            1. Tach,

                              und jetzt mach noch XML draus und du bist schon fast wieder bei XML-RPC.

                              Wieso das denn!?

                              weil das eine der Forderungen an XML-RPC war.

                              Lt. Spezifikation sind Name der remote aufzurufenden Methode und die zu übergebenden Parameter in XML zu verpacken und per HTTP zu übertragen. Nun, ich habe das mal ein bischen erweitert, statt Base64 für den Binary-Datentype, ermöglicht mein Serializer die Übertragung reiner Binaries (8 bit). Schließlich sind ja hin und wieder auch mal Dateien hochzuladen.

                              Da ich auch den serverseitig auszuführenden Code mitsende, braucht die Klasse auf dem Server nur noch ein paar Zeilen. Was nach Prüfung RequestMethod, Benutzername, Passwort übrigbleibt, siehe untenstehend (einschließlich einer ausführlichen Fehlerbehandlung).

                                      $self->param;
                                      my $bs = bSerialize->new; # Alternative XML::Simple
                                      my $binary = $self->{CGI}->rawdata;
                              
                                      # Deserialisierung, Rückgewinnung der Datenstruktur
                                      # ein simpler Hash
                                      # für den wahlfreien Zugriff
                                      my $in = $bs->bin2av( \$binary );
                                      
                                      my $code = delete $in->{code};
                                      eval $code or die "Error Compile Code: $@\n";
                              
                                      # der komplatte Code für die RPC Klasse
                                      # wurde mitgesendet, erstelle Instanz
                                      my $rpc = RPC->new;
                              
                                      my $methodname = delete $in->{methodname};
                                      my $coderef = $rpc->can($methodname) 
                                          or die "Unknown methodname\n";
                              
                                      # Mit in %$in verbleibenden Parametern
                                      # wird die namentlich übergebene Methode aufgerufen
                                      $self->{CONTENT} = $rpc->$coderef(%$in) 
                                          or die "Error execute method: $@\n";
                              

                              Zum Vergleich hab ich mir mal xmlrpc.php für wp angeguckt. Allein, was tausende WordPress-Kollegen an ungezählten Zeilen PHP-Code nur für den XML RPC Service entwickelt haben verdient meine Hochachtung ;)

                              Ebenfalls hochachtungsvolle Grüße ans Forum!

                              1. Tach,

                                Zum Vergleich hab ich mir mal xmlrpc.php für wp angeguckt. Allein, was tausende WordPress-Kollegen an ungezählten Zeilen PHP-Code nur für den XML RPC Service entwickelt haben verdient meine Hochachtung ;)

                                du wirst es eh nicht verstehen und ich vermute mal neutrale Leser werden inzwischen auch verstanden haben, wo hier im Thread die Probleme angesiedelt sind, deswegen enthalte ich mich weiterer Kommentare.

                                mfg
                                Woodfighter

                                1. Tach,

                                  Zum Vergleich hab ich mir mal xmlrpc.php für wp angeguckt. Allein, was tausende WordPress-Kollegen an ungezählten Zeilen PHP-Code nur für den XML RPC Service entwickelt haben verdient meine Hochachtung ;)

                                  du wirst es eh nicht verstehen und ich vermute mal neutrale Leser werden inzwischen auch verstanden haben, wo hier im Thread die Probleme angesiedelt sind, deswegen enthalte ich mich weiterer Kommentare.

                                  Nochwas zur Fehlerbehandlung, die scheint in der Legacy XML-Spezifikation überhaupt gar kein Thema zu sein, obwohl sie gerade bei automatisierten Prozessen lebensnotwendig ist.

                                  Meine Lösung:

                                  1. Fehlertext als Message Body in der HTTP Response
                                  2. Fehlercode als HTTP-Status Code 502

                                  Statuscode 502 ist legitim, weil es sich im weiteren Sinne um einen Gateway Error handelt, siehe auch CGI/1.1 Spec. Somit genügt eine Abfrage des HTTP Status zur Feststellung ob der Remote Procedure Call erfolgreich war oder nicht.

                                  Hochachtungsvoll, pl

                                  1. Tach,

                                    Nochwas zur Fehlerbehandlung, die scheint in der Legacy XML-Spezifikation überhaupt gar kein Thema zu sein, obwohl sie gerade bei automatisierten Prozessen lebensnotwendig ist.

                                    https://forum.selfhtml.org/self/2016/feb/8/xml-rpc/1660665#m1660665

                                    mfg
                                    Woodfighter

  2. Aufgrund einer selbstkritischen Situation hab ich das hier eröffnet. Mein bisheriges Rpc zum Content-Management ist überarbeitungsbedürftig, nach langer Hassliebe und Scheinfreundschaft hab ich mich von der Perl libwww getrennt und bei der Gelegenheit werde ich mein Rpc vereinfachen.

    Nach langer Überlegung habe ich mich nun für einen einfachen Hash (associative Array) als Datenstruktur entschieden und für die zu übertragende Sequenz wird es ein modifizierter Parameterstring.

    Da auch reine Binaries (Audio-, Video-, Grafik- und Textdateien) zu übertragen sind, werde ich die Werte Base64 kodieren anstelle Percent-Encoding. Die Schlüssel bleiben ASCII wie gehabt.

    Meine API, die es im Fall wp-xmlrpc übrigens auch als Perl Modul WordPress::XMLRPC gibt, wird ganz ähnlich aussehen und recht einfach anzuwenden sein. Die API kriegt Methodname und Parameter als Schlüssel-Werte-Paare und die werden ganz einfach serialisiert ohne das unnötig zu verschachteln (fürn Menschen ist key=value übrigens auch lesbar).

    Serverseitig gibts wie gehabt einfach nur eine an einen bestimmten URL gebundene Subklasse.

    Danke für Ihre Ausmerzamkeit ;)

    --
    Fliehende Stirn, fliehende Nase, fliehendes Kinn, Mensch der Kerl ist ein Flüchtling!