Michi: simpler Web Service mit ein paar Feinheiten

Hallo PHP-Gemeinde,

möchte demnächst eine vom Umfang her eher kleine Funktionsschnittstelle entwickeln, die einem (aufgrund vorhandenen Interesses) eher kleinen Programmiererkreis zur Verfügung gestellt werden soll.
Nun weiß ich noch nicht so recht, WIE ich das ganze anbieten soll - als Bibliothek zum Downloaden und Einbinden (wovon ich grundsätzlich kein großer Fan bin, da jede Änderung am Projekt an sich einen neuen Download durch den User erforderlich macht) oder stets aktuell als Web Service (was die Sache jedoch zunächst etwas komplizierter macht), was mir lieber wäre und im Regelfall auch ohne Anpassungen auf der Clientseite machbar sind, solang sich an der Methodenstruktur nichts ändert.

1. Kennt jemand eine simple Technik, Web Services in PHP anzubieten, ohne großartig weitere Bibliotheken wie PEAR (was auch nicht überall standardmäßig installiert ist bzw. installiert werden kann) für die RPC-Aufrufe einbinden zu müssen?

Na ok, reines HTTP gibts natürlich auch, aber das ist ja schon wieder etwas arg primitiv und fehleranfällig, wenn man die URL selber aufbauen muss. :)

2. Und gibts da weiterhin noch einen Trick, sodass auch jederzeit die URL des Web Services geändert werden kann und die aufrufenden Seiten dennoch funktionieren (wie eine solche DHCP-ähnliche Zuständigkeitsermittlung im Web zuverlässig funktionieren soll, weiß ich allerdings auch nicht...), ohne, dass ich alle aufrufenden Programmierer einzeln informieren muss, sofern ich sie überhaupt kenne? :) Da wär so was wie ein Weiterleitungsserver ganz recht, wenn es für solche Zwecke welche gibt.

Gruß Michi

  1. Hallo,

    möchte demnächst eine vom Umfang her eher kleine Funktionsschnittstelle entwickeln, die einem (aufgrund vorhandenen Interesses) eher kleinen Programmiererkreis zur Verfügung gestellt werden soll.
    Nun weiß ich noch nicht so recht, WIE ich das ganze anbieten soll - als Bibliothek zum Downloaden und Einbinden (wovon ich grundsätzlich kein großer Fan bin, da jede Änderung am Projekt an sich einen neuen Download durch den User erforderlich macht) oder stets aktuell als Web Service (was die Sache jedoch zunächst etwas komplizierter macht), was mir lieber wäre und im Regelfall auch ohne Anpassungen auf der Clientseite machbar sind, solang sich an der Methodenstruktur nichts ändert.

    Da du leider keinen konkreten Informationen gibts, hier so ein paar generelle Anregungen

    1. Mach dir Gedanken was das System können soll und schreib es auf.
      2. Mach dir Gedanken ob es Bereiche gibt, die an dem System sporadisch geändert werden sollen (die müssen nämlich auch in der API variabel sein).
      (2a. Mach dich schlau über schon existierende Techniken wie z.B. RPC, REST, SOAP, CORBA etc)
      3. Arbeite die API aus (und dokumentiere sie).
      4. Mach dich anhand von diesen Informationen auf die Suche nach einem geeigneten Werkzeug (aka Programmiersprache).
      5. Bastle einen Proof-of-Concept anhand der API und der Spezifikationen (nicht anhand des Werkzeugs) und beginne bei Problemen wieder bei 1
      (5a. Lasse Benutzer diesen testen und benutzen, geht meistens auch schnell wieder zu Punkt 1)
      (5b. Schreibe geeignete Tests die bei Änderungen die bis jetzt garantierte Funktionalität erhalten, kann auch schon nach Punkt 4 folgen)
      6. Überprüfe ob du erreicht hast was du wolltest, wenn nicht schmeiss es über den Haufen und fang von vorne an ;)
      7. Ausarbeitung des Gesamtkonzepts mit Punkt 5a und 5b

    1. Und gibts da weiterhin noch einen Trick, sodass auch jederzeit die URL des Web Services geändert werden kann und die aufrufenden Seiten dennoch funktionieren (wie eine solche DHCP-ähnliche Zuständigkeitsermittlung im Web zuverlässig funktionieren soll, weiß ich allerdings auch nicht...), ohne, dass ich alle aufrufenden Programmierer einzeln informieren muss, sofern ich sie überhaupt kenne? :) Da wär so was wie ein Weiterleitungsserver ganz recht, wenn es für solche Zwecke welche gibt.

    so macht es ein Tauschbörsenopa

    gruss

    --
    no strict;
    no warnings;
    79.78 cups of Coffee (Brewed) + Me = Death
    Terrorific!
    1. Hi Eternius,

      so macht es ein Tauschbörsenopa

      die Info:

      _______________________________________________________________________________________________________________

      Das Gnutella-Netzwerk ist ein vollständig dezentrales Netzwerk. Das bedeutet, dass jeder Benutzer eine gleichwertige Software verwendet und es keine zentralen Server gibt, welche die Suchanfragen bearbeiten. Um zu funktionieren muss das Client-Programm mindestens einen anderen Benutzer (sogenannten node) finden. Um dies zu erreichen gibt es diverse Methoden, wie vordefinierte Serverlisten, Gbwebcache-Seiten im Internet oder auch der Austausch von Host-Listen über IRC. Wird eine Verbindung aufgebaut, tauschen die Programme Listen erreichbarer Nodes aus, welche dann wiederrum kontaktiert werden bis die eingestellte Anzahl an Verbindungen erreicht wurde.

      Startet ein Benutzer des Netzwerkes eine Suchanfrage, so wird diese zunächst nur an benachbarte Systeme weitergeleitet. Diese leiten dann ihrerseits die Anfrage an ihre benachbarten Systeme weiter, bis die angeforderte Datei gefunden wurde. Anschließend kann eine direkte Verbindung zwischen suchendem und anbietendem Benutzer für die Datenübertragung hergestellt werden.

      Der besondere Vorteil dieser Netzwerkstruktur ist die Ausfallsicherheit, da Suchanfragen selbst dann weitergeleitet werden können, wenn einzelne Teile des Netzwerkes zeitweise unerreichbar sind. Nachteilig dagegen ist die lange Dauer der Suchanfrage, da es keine zentralen Index-Server gibt, und die hohe Netzwerkbelastung durch die teils ziellosen Weiterleitungen der Suchanfragen.

      _______________________________________________________________________________________________________________

      Klingt (bis auf den - zu erwartenden - Nachteil der langen Dauer der Suchanfrage natürlich :)) gut und ist für die weitere Entwicklung vorgemerkt. ;)

      Dank und Gruß
      Michi

  2. Hallo PHP-Gemeinde,

    Hallo PHPler ;)

    Nun weiß ich noch nicht so recht, WIE ich das ganze anbieten soll - als Bibliothek zum Downloaden und Einbinden (wovon ich grundsätzlich kein großer Fan bin, da jede Änderung am Projekt an sich einen neuen Download durch den User erforderlich macht) oder stets aktuell als Web Service (was die Sache jedoch zunächst etwas komplizierter macht), was mir lieber wäre und im Regelfall auch ohne Anpassungen auf der Clientseite machbar sind, solang sich an der Methodenstruktur nichts ändert.

    Deine Frage nach dem "WIE" ist mir noch nicht klar geworden. Wenn Du einen Service anzubieten hast, dann vergib dafür einen freien Port (z. B. 1100), denke Dir ein Protokollverfahren aus und setze es in Client und Serversoftware um. Eine als Server konfigurierbare TCP-Classe gibts schon mal von mir:

      
    <?php  
    declare(ticks=1);  
    define(PID,posix_getpid());  
      
    class tcp{  
     public function tcp($host){  
      $this->connect =stream_socket_server('tcp://'.$host);  
      $this->docroot ='/tmp';  
      $this->user ='nobody';  
      $this->lib ='';  
      
      posix_setsid();  
      posix_setgid(PID);  
      posix_setpgid(PID,PID);  
     }  
     public function child($zahl){  
      $a=posix_getpwnam($this->user);  
      posix_setuid($a['uid']);  
      posix_setgid($a['gid']);  
      chdir($this->docroot);  
      chroot($this->docroot);  
      
      for($i=0;$i<$zahl;$i++){  
       $this->pid[$i]=pcntl_fork();  
       if($this->pid[$i]==0){  
        include($this->lib.'.obj');  
        while(1){  
         $a=new $this->lib($this->connect);  
         if(memory_get_usage()>200000)  
          exit;  
        }  
        exit;  
       }  
      }  
      $this->wait();  
     }  
     private function wait(){  
      if(PID==posix_getpid()){  
       $s=array(SIGQUIT,SIGHUP,SIGTERM,SIGCHLD);  
       foreach($s as $v)  
        pcntl_signal($v,array(&$this,"signal"));  
      }  
      
      while(1){  
       foreach($this->pid as $k=>$v)  
        if(pcntl_waitpid($v,$i,WNOHANG)==-1){  
         unset($this->pid[$k]);  
         $this->child(1);  
        }  
       sleep(1);  
      }  
     }  
     public function signal($s){  
      $c=count($this->pid);  
      foreach($this->pid as $v)  
       posix_kill($v,SIGTERM);  
      
      if($s==SIGTERM || $s==SIGQUIT)  
       exit(0);  
      else{  
       $this->pid=array();  
       $this->child($c);  
      }  
     }  
    }  
    $a=new tcp('localhost:80');  
    $a->user ='Servicedeamon';  
    $a->docroot ='/opt/neuerService/data';  
    $a->lib  ='http';  
    $a->child(5);  
    ?>  
    
    

    Na ok, reines HTTP gibts natürlich auch, aber das ist ja schon wieder etwas arg primitiv und fehleranfällig, wenn man die URL selber aufbauen muss. :)

    Wie gesagt, denk Dir Dein eigenes Protokoll aus... hilfe, wenn es nicht weiter geht, bekommst Du hier.

    1. Und gibts da weiterhin noch einen Trick, sodass auch jederzeit die URL des Web Services geändert werden kann und die aufrufenden Seiten dennoch funktionieren (wie eine solche DHCP-ähnliche Zuständigkeitsermittlung im Web zuverlässig funktionieren soll, weiß ich allerdings auch nicht...), ohne, dass ich alle aufrufenden Programmierer einzeln informieren muss, sofern ich sie überhaupt kenne? :) Da wär so was wie ein Weiterleitungsserver ganz recht, wenn es für solche Zwecke welche gibt.

    Auch dort werden Informationen über die Ablage von Informationen von (einer) zentralen Stelle(n) abgerufen. Eine feste IP-Adresse brauchst Du also.

    Gruß aus Berlin!
    eddi

    1. Hi Eddi,

      Deine Frage nach dem "WIE" ist mir noch nicht klar geworden. Wenn Du einen Service anzubieten hast, dann vergib dafür einen freien Port (z. B. 1100), denke Dir ein Protokollverfahren aus und setze es in Client und Serversoftware um.

      Ich habe mich nun doch für HTTP als einfaches, weitverbreitetes und von PHP unmittelbar unterstütztes Protokoll entschieden.

      Ich hoff mal, dass es hier sonst keine weiteren Probleme macht, aber überprüfen muss ich die übergebenen Daten ja so oder so, zumindest grob.

      Danke Dir! ;)
      Michi

  3. Hi,

    Na ok, reines HTTP gibts natürlich auch, aber das ist ja schon wieder etwas arg primitiv und fehleranfällig, wenn man die URL selber aufbauen muss. :)

    Reines HTTP hat ein paar Vorteile:

    • Du brauchst Dich um die Übertragung gar nicht zu kümmern, nur noch um die "Nutzlast" der Übertragung - sprich: was tatsächlich übertragen wird.
    • in vielen Firmen sind die Firewalls so konfiguriert, daß außer den "Standard"-Ports für E-Mail und eben HTTP so gut wie nichts durchgelassen wird; wenn Du also ein eigenes Protokoll auf einem eigenen Port benutzt, schließt Du viele potentielle Nutzer aus.

    Nur weil Du http benutzt, mußt Du ja nicht HTML-Seiten ausliefern, Du kannst ja auch x-michi/x-blablubb statt text/html ausliefern.

    1. Und gibts da weiterhin noch einen Trick, sodass auch jederzeit die URL des Web Services geändert werden kann und die aufrufenden Seiten dennoch funktionieren (wie eine solche DHCP-ähnliche Zuständigkeitsermittlung im Web zuverlässig funktionieren soll, weiß ich allerdings auch nicht...), ohne, dass ich alle aufrufenden Programmierer einzeln informieren muss, sofern ich sie überhaupt kenne? :) Da wär so was wie ein Weiterleitungsserver ganz recht, wenn es für solche Zwecke welche gibt.

    Wenn sich nur die URL innerhalb des Servers ändert: mod_rewrite oder ähnliches.
    Wenn sich der Server selbst ändert: einen Proxy dazwischen hängen, der jeweils auf den aktuellen Server greift. Damit verschiebst Du das Problem aber auch nur vom eigentlichen Server auf den Proxy (wenn sich der Proxy ändert ...)

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    Schreinerei Waechter
    Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
    1. Hi Andreas,

      Reines HTTP hat ein paar Vorteile:

      • Du brauchst Dich um die Übertragung gar nicht zu kümmern, nur noch um die "Nutzlast" der Übertragung - sprich: was tatsächlich übertragen wird.

      Bin mittlerweile auch zum Entschluss gekommen, dass HTTP doch wieder mal das beste, weil einfachste und zuverlässigste ist... nicht nur, weil die SOAP- wie RPC-Steuerung in PHP immer noch recht kompliziert (vor allem natürlich für den Schnittstellenuser, der sich mit dieser Technik dann auch mehr oder weniger auseinandersetzen und vor allem zuschauen muss, dass er es auf seinem Server auch zum Laufen bekommt...) einzubauen ist. ;)

      • in vielen Firmen sind die Firewalls so konfiguriert, daß außer den "Standard"-Ports für E-Mail und eben HTTP so gut wie nichts durchgelassen wird; wenn Du also ein eigenes Protokoll auf einem eigenen Port benutzt, schließt Du viele potentielle Nutzer aus.
        Wenn sich der Server selbst ändert: einen Proxy dazwischen hängen, der jeweils auf den aktuellen Server greift. Damit verschiebst Du das Problem aber auch nur vom eigentlichen Server auf den Proxy (wenn sich der Proxy ändert ...)

      Ja, auf dem Erkenntnisstand bin ich zuletzt auch steckengeblieben, aber sehen wir es mal eher realistisch und nicht so negativ: :)
      Es geht wohl ohne großen Aufwand nicht anders, als irgendeinen fixen Serverpunkt zu definieren, der entweder auf einen anderen verweist oder selber die Anfrage bearbeitet - was ja nachträglich zumindest jederzeit änderbar ist.
      Natürlich kann ich noch anbieten, dass der User beim Download seine Email-Adresse (oder gleich FTP-Daten? :D ) eingeben kann, damit er im Falle entscheidender Änderungen wie z.B. Serverwechsel benachrichtigt werden kann. ;)

      Dank und Gruß!
      Michi

  4. echo $begrüßung;

    1. Kennt jemand eine simple Technik, Web Services in PHP anzubieten, ohne großartig weitere Bibliotheken wie PEAR [...] für die RPC-Aufrufe einbinden zu müssen?

    XMLRPC. Das hat aber auch nicht jeder Provider freigegeben.

    [PEAR] (was auch nicht überall standardmäßig installiert ist bzw. installiert werden kann)

    Das Argument gilt nicht. PEAR-Klassen sind auch nur ganz normale "Include-Dateien". Du kannst die verwendeten Klassen einfach mit deinen anderen Projekt-Dateien ausliefern. Gegebenenfalls musst du noch den include_path auf dein Unterverzeichnis mit den PEAR-Dateien anpassen.

    echo "$verabschiedung $name";

    1. Hi dedlfix,

      XMLRPC. Das hat aber auch nicht jeder Provider freigegeben.

      [PEAR] (was auch nicht überall standardmäßig installiert ist bzw. installiert werden kann)

      Das Argument gilt nicht. PEAR-Klassen sind auch nur ganz normale "Include-Dateien". Du kannst die verwendeten Klassen einfach mit deinen anderen Projekt-Dateien ausliefern. Gegebenenfalls musst du noch den include_path auf dein Unterverzeichnis mit den PEAR-Dateien anpassen.

      Ok, so ganz genau hab ich mir da vorher keine Gedanken gemacht, was da für Anpassungen beim Client nötig werden könnten.
      Stimmt schon, die include-Files kann man natürlich mitliefern und SOAP liefe ja auch über Port 80, also auch schon mal keine Probleme mit Firewalls. Bei mir läuft das soweit auch ber SOAP prima, aber ob das auf jedem Client der Fall wäre...? Denn was darüberhinaus evtl. an Serverkonfigurationen (vor allem php.ini?) nötig werden könnte, kann ich mangels detaillierter Erfahrung mit den SOAP-Klassen auf div. Hosts nicht beurteilen.

      Was mich aber insgesamt letztenendes wieder mehr zur Verwendung reinen HTTP geneigt macht, ist die Einfachheit und die weitgehende Unabhängigkeit von Konfigurationen wie z.B. PHP-Version.
      Während der Service selbst objektorientiert in PHP 5 geschrieben wird und zur Hälfte bereits wurde, soll das Aufrufmodul natürlich nach Möglichkeit auch mit der die nächste Zeit weiterhin meistverbreiteten PHP-Version 4 laufen.

      Hier mal der bisherige Code des Aufrufmoduls, womits soweit natürlich hervorragend funktioniert: :)

      ____________________________________________________________________

      <?php

      // Testdaten:

      $aaf_datensatz = "#A93:*,Alberto,m,09.12.1868g,03:30,Cava Dei Tir -SA-,I" . chr (0x0D) .
         "#B93:*,*,*,*,m" . chr (0x0D) .
         "#COM:Frz. Maler. Pionier der modernen Malerei, auf den sich viele spätere Kunstrichtungen berufen. Für kurze Zeit Impressionist. Schuf jedoch einen völlig eigenen Malstil (Perspektive, Beleuchtung, Komposition, Kontraste, etc.) die z.T. vom Kubismus aufgegriffen wurden. Werke:'Mühle an der Couleuvre bei Pontoise' (1881)" . chr (0x0D) .
         "#CWORD:MI,Milit&auml;r" . chr (0x0D) .
         "#VIA:GAU&70,Gauquelin `Birth and Planetary Data' -Series A- 1970" . chr (0x0D) .
         "#ATTRB:B=Maler, K=5, N=Spanier" . chr (0x0D) .
         "#BPOS:Mo00n19:21,Me00n52:52,Ve05s05:54,Ma01n09:03,Ju00n57:09,Sa02s27:38,Ur00n39:46,Ne01n38:**,Pl15n24:**,Ch02n37:**" . chr (0x0D) .
         "#ASP:ER,SO tri MA 0+57:23,SO sex NN 0+18:16,MO sqr JU 0-33:44 s,MO con UR 2-52:25 s,MO 22:30 MC 1+41:52 ap,ME 127:25:02 VE 0-40:18 ak" . chr (0x0D);

      function vorliegende_aaf_daten_nach_xml ( $aaf_datensatz )
       {
        $service = "http://localhost/AAF-Bibliothek/aaf_schnittstelle3.php";
        $extension = $aaf_datensatz;
        $url = $service . "?aaf=" . urlencode ( $extension );

      return readfile ( $url );
       }

      echo vorliegende_aaf_daten_nach_xml ( $aaf_datensatz )

      ?>

      ____________________________________________________________________

      Dank und Gruß!
      Michi