Verständnisfrage zu HttpUtils_NonblockingGet

Begonnen von xasher, 06 Mai 2022, 16:37:42

Vorheriges Thema - Nächstes Thema

xasher

Hallo zusammen,

ich komme gerade an meinem Modul nicht weiter. Ich brauche für eine Abfrage ein erzeugtes Antiforgerycookie
Ich komme mit der Reihenfolge der Verarbeitung aber nicht klar. Was ich bisher habe - hier zum Debuggen:


...
}elsif( $cmd eq "TEST" ) {
   
print "1\n";

    my $saunaid  = AttrVal($name, "saunaid", "");
    my $aspxauth = $hash->{KLAFS}->{cookie};

   
         my $header = "Cookie: $aspxauth";
         my $datauser = "s=$saunaid";
         HttpUtils_NonblockingGet({
             url        => ENTERPIN,
             timeout    => 5,
             hash        => $hash,
             method      => "GET",
             header      => $header, 
             data => $datauser,
             callback    => \&Klafs_GETantiforgery1,
         }); 
         
         # RequestVerificationToken  aus dem Header auslesen fuer das Cookie
         sub Klafs_GETantiforgery1($) {
           my ($param, $err, $data) = @_;
           my $hash = $param->{hash};
           my $name = $hash->{NAME};
           my $header = $param->{httpheader};
           Log3 $name, 5, "header: $header";
           Log3 $name, 5, "Data: $data";
           Log3 $name, 5, "Error: $err";
print "AntiForgery GET\n";
           foreach my $cookie ($header =~ m/set-cookie: ?(.*)/gi) {
               $cookie =~ /([^,; ]+)=([^,;\s\v]+)[;,\s\v]*([^\v]*)/;
               my $antiforgery  = $1 . "=" .$2 .";";
               Log3 $name, 4, "AntiforgeryGet: $antiforgery";
               Log3 $name, 5, "$name: Antiforgery found: $antiforgery";
               $hash->{KLAFS}->{antiforgery}    = $antiforgery;
           }
         }
   

   
    print "2\n";
}


Als Ausgabe im Log kommt die Reihenfolge:


1
2
AntiForgery GET
2022.05.06 16:28:07 4: AntiforgeryGet: __RequestVerificationToken=uXch_rxxxxxxxxxxxxxxxx......


An Position 2 muss ich das neue Cookie ($hash->{KLAFS}->{antiforgery) verwenden. Es ist dort aber noch nicht vorhanden. Kommt laut Log erst später.

Was muss ich denn hier beachten?

Grüße
Alex

rudolfkoenig

Klassisches Callback-Muster:
Code ab Position 2 in die interne Funktion (Klafs_GETantiforgery1) verlagern.

Alternative, falls man hintereinander mehrere nonblocking Aufrufe hat:
- jeden Aufruf in einem separaten if, der prueft, ob dieser Aufruf an der Reihe ist
- direkt nach dem nonblocking Aufruf ein return (noch im if)
- Im Callback eine Variable setzen, damit der gleiche Aufruf nicht wieder erfolgt, und die urspruengliche Funktion wieder aufrufen
=> Statt eine tiefe Schachtelung der Funktionen hat man damit nur eine Funktion mit mehreren If-Bloecken.

Generell muss man sich davon verabschieden, dass die urspruengliche Funktion das Ergebnis zurueckliefert.
Im FHEMWEB Kontext ist deswegen asyncOutput interessant.

xasher

Hallo Rudolf,

ja das mit dem Async erklärt es. Ich habe 3 Anrfagen, die genau getaktet werden müssen.
Deine Alternative finde ich daher besser. Leider hab ichs noch nicht ganz verstanden.
Wie kann ich das zeitlich prüfen, wann welche Abfrage an der Reihe ist, wenn sie untereinander stehen klappt ja nicht.

Hast du mir da im Ansatz ein Beispiel? Hoffentlich verlang ich da nicht zu viel.

Auf jeden Fall schon mal Danke!

Grüße
Alex

Beta-User

Wenn ich das richtig erinnere, macht der TvHeadend-code so was. Habe aber grade keinen link parat.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

rudolfkoenig

ZitatHast du mir da im Ansatz ein Beispiel?

Variante 1, Aufruf aus telnet oder Browser mit { nb_1($cl) }
sub
nb_1($)
{
  my ($cl) = @_;

  HttpUtils_NonblockingGet({
    url=>"http://fhem.de/MAINTAINER.txt",
    callback=>sub($$$){
      Log 1,"MAINTAINER.txt LEN:".length($_[2]);
      my $len = length($_[2]);

      HttpUtils_NonblockingGet({
        url=>"http://fhem.de/CHANGED",
        callback=>sub($$$){
          Log 1,"CHANGED LEN:".length($_[2]);
          $len += length($_[2]);
          asyncOutput($cl, "TOTAL LEN IS: $len");
        }
      });
    }
  });
}


Variante 2, Aufruf mit { nb_2({cl=>$cl}) }
sub
nb_2($;$$)
{
  my ($hash,$err,$data) = @_;

  if(!$hash->{gotMaintainer}) {
    $hash->{gotMaintainer} = 1;
    $hash->{callback} = \&nb_2;
    $hash->{url} = "http://fhem.de/MAINTAINER.txt";
    HttpUtils_NonblockingGet($hash);
    return;
  }

  if(!$hash->{gotChanged}) {
    $hash->{gotChanged} = 1;
    Log 1,"MAINTAINER.txt LEN:".length($data);
    $hash->{len} = length($data);
    $hash->{url} = "http://fhem.de/CHANGED";
    HttpUtils_NonblockingGet($hash);
    return;
  }

  Log 1,"CHANGED LEN:".length($data);
  $hash->{len} += length($data);
  asyncOutput($hash->{cl}, "TOTAL LEN IS: ".$hash->{len});
}

xasher

Hallo zusammen,

vielen Dank, ich bin begeistert. Ich habe deine Variante 1 gewählt Rudolf.
@BetaUser. Danke für den Hinweis. Ich glaube das Modul gibt es nicht mehr.

Viele Grüße,
Alex

rudolfkoenig

ZitatIch habe deine Variante 1 gewählt Rudolf.
Ich habe auch so angefangen :)

justme1968

nur der vollständigkeit halber noch ein dritter vorschlag da ich meine das die beiden ansätze von oben bei längeren ketten von anfragen an ihre grenzen kommen bzw. der code recht unübersichtlich wird:

- im $hash des HttpUtils_NonblockingGet aufrufs kann man auch zusätzliche wertepaare mitgeben. z.b. key => xxx die für jeden aufruf unterschiedlich sein können.

- in der callback routine kann man so ganz einfach die antworten den anfragen zuordnen und in der behandlung der jeweiligen antwort die nächste nötige anfrage absetzen.

- das lässt sich auch weiter ausbauen z.b. durch eine queue in die die anfragen eingereiht werden und jeweils bei einer antwort die nächste abgeschickt wird

- es gibt fehler bei denen es sinnvoll sein kann eine anfrage zu wiederholen. das lässt sich mit den oberen drei punkten recht einfach machen in dem man am anfang des callbacks die fehlerhafte anfrage einfach erneut sendet und mit zählt wie oft das passiert ist so das man dann bei n >2 oder >3 abbrechen kann.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Beta-User

Zitat von: justme1968 am 09 Mai 2022, 10:32:31
nur der vollständigkeit halber noch ein dritter vorschlag da ich meine das die beiden ansätze von oben bei längeren ketten von anfragen an ihre grenzen kommen bzw. der code recht unübersichtlich wird:

- im $hash des HttpUtils_NonblockingGet aufrufs kann man auch zusätzliche wertepaare mitgeben. z.b. key => xxx die für jeden aufruf unterschiedlich sein können.

- in der callback routine kann man so ganz einfach die antworten den anfragen zuordnen und in der behandlung der jeweiligen antwort die nächste nötige anfrage absetzen.

- das lässt sich auch weiter ausbauen z.b. durch eine queue in die die anfragen eingereiht werden und jeweils bei einer antwort die nächste abgeschickt wird

- es gibt fehler bei denen es sinnvoll sein kann eine anfrage zu wiederholen. das lässt sich mit den oberen drei punkten recht einfach machen in dem man am anfang des callbacks die fehlerhafte anfrage einfach erneut sendet und mit zählt wie oft das passiert ist so das man dann bei n >2 oder >3 abbrechen kann.
Klingt interessant, muss ich mir ggf. für TvHeadend auch mal anschauen, da wird das über einen Zähler im Devicehash gemacht...

Zitat von: xasher am 09 Mai 2022, 10:18:26
@BetaUser. Danke für den Hinweis. Ich glaube das Modul gibt es nicht mehr.
Das war noch nie offiziell, hatte das mal als "Fingerübung" aktualisiert/modernisiert, weil im Ursprungscode manches "gefährlich" war. (package)-Code ist z.B. hier zu finden: https://forum.fhem.de/index.php/topic,123117.msg1176443.html#msg1176443
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files