AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte HTTPManager
Thema durchsuchen
Ansicht
Themen-Optionen

HTTPManager

Ein Thema von geskill · begonnen am 26. Aug 2012 · letzter Beitrag vom 15. Dez 2012
Antwort Antwort
Benutzerbild von geskill
geskill
Registriert seit: 17. Feb 2007
Hey zusammen,
ich würde auch gerne ein Modul von mir vorstellen, wo ich mir denken kann, dass dies auch für den ein oder anderen Interessant sein könnte!

Beschreibung
Der HTTPManager ist eine Klasse, die GET/POST Requests annimmt und diese im Hintergrund (einzeln) hintereinander bearbeitet. (Für Dateidownloads ist diese Klasse eher weniger gedacht!)

Das besondere am HTTPManager ist, dass es komplett auf Interfaces gestützt ist, die nur COM Datentypen verwenden und so ideal in einem Pluginsystem eingebunden werden kann. So wird z.B. die HTTPManager Klasse in dem Hauptprogramm erstellt und das Interface an die Plugins weitergegeben. Als Strukturmuster diente die HTTP Komponente von Indy. Der HTTPManager nutzt das Strategie-Pattern um die letztendliche Komponente welche die Requests übernimmt (z.B. Indy) flexibel auszutauschen. Die Hintergrundarbeit wird mit der OmniThreadLibrary erledigt.
Es war mir außerdem wichtig, dass der Benutzer sich so wenig wie nötig mit Cookies, Parameterkodierungen oder z.B. Socks Konfigurationen beschäftigen muss. Es wurden diverse wichtige Konfigurationen direkt integriert, sinnvolle Standardwerte gesetzt und z.B. bei den POST-Parametern ein automatische abstrakte Parameterklasse integriert (wählt selbstständig ContentType).

Da die Kommunikation mit dem Internet aus Anwendungen heraus immer wichtiger wird und dies besonders bei Delphi Einsteigern gerne probiert wird, bietet diese Komponente das Ideale Handwerkszeug zur Realisierung. Natürlich gibt es in Delphi auch fertige Klassen um damit beispielsweise XML Requests zu basteln; aber diese beschränken sich dann halt immer auch bestimmte Voraussetzungen.

Ein kleiner Bonus: der HTTPManager speichert alle Aktivitäten über den Programmverlauf, sodass man auch zu späteren Zeitpunkten an gezielte Requests kommt oder dem Nutzer z.B. über eine visuelle Oberfläche eine Art HTTP Logger bietet (siehe Demos).
Funktionsweise
Der Zugriff erfolgt über eine Interface:
Delphi-Quellcode:
  IHTTPManager = interface
    ['{DB7FBA4F-CE5C-454A-AA74-FB8EC7DFAB8E}']
    function GetImplementor: IHTTPImplementation; safecall;
    procedure SetImplementor(const AImplementor: IHTTPImplementation); safecall;
    function GetRequestDone: IHTTPProcessEvent; safecall;

    function Get(AURL: WideString; AFollowUp: Double; AHTTPOptions: IHTTPOptions = nil): Double; overload; safecall;
    function Get(AHTTPRequest: IHTTPRequest; AHTTPOptions: IHTTPOptions = nil): Double; overload; safecall;
    function Post(AURL: WideString; AFollowUp: Double; AHTTPParams: IHTTPParams; AHTTPOptions: IHTTPOptions = nil): Double; overload; safecall;
    function Post(AHTTPRequest: IHTTPRequest; AHTTPParams: IHTTPParams; AHTTPOptions: IHTTPOptions = nil): Double; overload; safecall;

    function HasResult(AUniqueID: Double): WordBool; safecall;
    function GetResult(AUniqueID: Double): IHTTPProcess; safecall;

    property Implementor: IHTTPImplementation read GetImplementor write SetImplementor;

    property OnRequestDone: IHTTPProcessEvent read GetRequestDone;
  end;
Die Funktionen erklären sich fast von selbst. Die Benutzung ist so gedacht, dass man einen GET/POST erstellt und dieser dann abgearbeitet wird. Der HTTPManager gibt dazu eine UniqueID zurück. Nun kommt auch die OmniThreadLibrary auf der Nutzerseite zum Einsatz. Durch einen einfachen Task wird in einer Schleife geprüft (HasResult) ob der Request bereits beendet wurde. Danach wird zum Hauptprogramm synchronisiert und über GetResult kommt man nun an die geladenen Daten.

Intern werden die GET/POST-Requests dupliziert, damit Zugriffe von einer DLL aus - nicht zu Problemen mit der Referenzzählung führen. Diese werden dann über ein ThreadPool (IOmniBackgroundWorker) abgearbeitet. Im Worker (IOmniWorkItem) wird dann eine Instanz der Indy HTTP Klasse erstellt und die Daten übergeben. Beim POST-Request wurden die Parameter in einer allgemeinen Klasse gesammelt. Diese werden dann noch auf die entsprechende Indy Klasse umgemapt.
Ist der Request abgeschlossen oder traten Fehler auf werden alle Informationen in einem IHTTPResult Interface zusammengefasst. Dieses und die eigentlichen Request Informationen werden dann gebündelt und als IHTTPProcess zusammengefasst. Somit hat man später nochmals Zugriff aus alle Daten, denn die Indy HTTP Klasse wird nach Ende des Requests wieder freigegeben.

Die IHTTPProcess-Interfaces speichert ein Array (welches über ein TOmniMREW gesichert ist).
Beispiele
GET-Request:
Delphi-Quellcode:
procedure
var
  // jeder Request hat eine eindeutige ID um diesen auch später wieder zu Identifizieren
  RequestID: Double;
begin
  // Basierend auf dem Singelton, wird hier die Instanz vom HTTPManager geholt
  HTTPManager := THTTPManager.Instance();

  // Der GET-Request wird erstellt und ausgeführt
  RequestID := HTTPManager.Get(THTTPRequest.Create('http://www.google.de/search?q=http+indy'));

  // In diesem Moment wird der GET-Request bereits beareitet

  Parallel.Async(
      procedure
        begin
          repeat
            sleep(50); // Einfache Schleife, die Prüft ob der Request bereits abgearbeitet wurde
          until HTTPManager.HasResult(RequestID);
        end,
        Parallel.TaskConfig.OnTerminated(
          procedure(const task: IOmniTaskControl)
          var
            HTTPProcess: IHTTPProcess;
          begin
            // Der Request ist vollständig und man hat nun Zugriff auf die Daten (dafür braucht man die ID)
            HTTPProcess := HTTPManager.GetResult(RequestID);
            // Den Quellcode könnte man nun weiterverarbeiten oder einfach in ein Textfeld ausgeben
            mGETResult.Lines.Text := HTTPProcess.HTTPResult.SourceCode;
          end
          ));
end;
GET-Request (FollowUp):
Nutzt man die HTTP-Komponente direkt, gehen die Cookies in dieser Sitzung nicht verloren (z.B. für ein Login). Beim HTTPManager müsste man alle Cookies und eventuell weitere Informationen aus dem vorherigen Request laden und dem neuen übergeben. Um den Arbeitsaufwand gering zu halten sind die GET und POST Methoden entsprechend überladen - somit reicht die Angabe der vorherigen RequestID um Cookies und Sitzungsspezifische Informationen automatisch zu übernehmen:
Delphi-Quellcode:
procedure
var
  PrevRequestID, RequestID: Double;
begin
  // ein GET-Request wird erstellt und ausgeführt - beendet mit <PrevRequestID>

  // Darauf aufbauend wird nun ein neuer Request erstellt:
  RequestID := HTTPManager.Get('http://www.google.de/search?q=neue+suche+mit+login', PrevRequestID);

  //...
end;
Diese Komponente basiert auch auf den http://www.delphipraxis.net/172339-a...astevents.html

DOWNLOAD: https://github.com/geskill/HTTPManager
Miniaturansicht angehängter Grafiken
httpmanager.png   interface-diagramm.jpg  

Geändert von geskill (18. Mai 2014 um 21:12 Uhr)
 
Benutzerbild von geskill
geskill

 
Delphi 2010 Professional
 
#2
  Alt 15. Dez 2012, 19:44
Nach einigen Monaten und dutzenden Erweiterungen und einem x-fachen davon an Tests, möchte ich an dieser Stelle - euch - nochmals darauf Aufmerksam machen.

Zu den Neuerungen gehört Proxy-Support, FollowUp-Requests**, RawData-Params*** sowie Zugriff auf den Response Stream (via ActiveX.IStream)!

** Aufbauende Requests (der Request nach einem Login baut beispielsweise auf dem Login Request auf, da dieser wichtige Cookies übermittelt hat)
*** Plain POST Parameter ohne Parametertypisches name=value Gebilde
Sebastian
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz