Frage

Ich versuche, HTTP-Anfragen von Delphi mit den WinInet-Funktionen zu machen.

Bisher habe ich:

function request:string;
var
  hNet,hURL,hRequest: HINTERNET;
begin
  hNet := InternetOpen(PChar('User Agent'),INTERNET_OPEN_TYPE_PRECONFIG or INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if Assigned(hNet) then 
  begin
  try
    hURL := InternetConnect(hNet,PChar('http://example.com'),INTERNET_DEFAULT_HTTP_PORT,nil,nil,INTERNET_SERVICE_HTTP,0,DWORD(0));
    if(hURL<>nil) then
      hRequest := HttpOpenRequest(hURL, 'POST', PChar('param=value'),'HTTP/1.0',PChar(''), nil, INTERNET_FLAG_RELOAD or INTERNET_FLAG_PRAGMA_NOCACHE,0);
    if(hRequest<>nil) then
      HttpSendRequest(hRequest, nil, 0, nil, 0);
    InternetCloseHandle(hNet);
  except
    on E : Exception do
      ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
  end;
  end
end;

Aber das tut nichts (ich Sniffing Netzwerk HTTP-Verkehr, um zu sehen, ob es funktioniert). Ich habe InternetOpenURL erfolgreich eingesetzt, aber ich brauche auch POST-Anforderung und die Funktion nicht zu senden, die nicht tun.

Könnte jemand zeigen Sie mir ein einfaches Beispiel? Das Ergebnis, das ich will, ist die HTTP-Antwort-Seite in einem var als String zu erhalten.

War es hilfreich?

Lösung

Ich habe alle die URL / Dateiname Teil mit dem vorherigen Code durcheinander. Ich verwende diesen von Jeff DeVore jetzt und es funktioniert gut:

function request(const AUrl, AData: AnsiString; blnSSL: Boolean = True): AnsiString;
var
  aBuffer     : Array[0..4096] of Char;
  Header      : TStringStream;
  BufStream   : TMemoryStream;
  sMethod     : AnsiString;
  BytesRead   : Cardinal;
  pSession    : HINTERNET;
  pConnection : HINTERNET;
  pRequest    : HINTERNET;
  parsedURL   : TStringArray;
  port        : Integer;
  flags       : DWord;
begin
  ParsedUrl := ParseUrl(AUrl);

  Result := '';

  pSession := InternetOpen(nil, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);

  if Assigned(pSession) then
  try
    if blnSSL then
      Port := INTERNET_DEFAULT_HTTPS_PORT
    else
      Port := INTERNET_DEFAULT_HTTP_PORT;
    pConnection := InternetConnect(pSession, PChar(ParsedUrl[0]), port, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);

    if Assigned(pConnection) then
    try
      if (AData = '') then
        sMethod := 'GET'
      else
        sMethod := 'POST';

      if blnSSL then
        flags := INTERNET_FLAG_SECURE or INTERNET_FLAG_KEEP_CONNECTION
      else
        flags := INTERNET_SERVICE_HTTP;

      pRequest := HTTPOpenRequest(pConnection, PChar(sMethod), PChar(ParsedUrl[1]), nil, nil, nil, flags, 0);

      if Assigned(pRequest) then
      try
        Header := TStringStream.Create('');
        try
          with Header do
          begin
            WriteString('Host: ' + ParsedUrl[0] + sLineBreak);
            WriteString('User-Agent: Custom program 1.0'+SLineBreak);
            WriteString('Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'+SLineBreak);
            WriteString('Accept-Language: en-us,en;q=0.5' + SLineBreak);
            WriteString('Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7'+SLineBreak);
            WriteString('Keep-Alive: 300'+ SLineBreak);
            WriteString('Connection: keep-alive'+ SlineBreak+SLineBreak);
          end;

          HttpAddRequestHeaders(pRequest, PChar(Header.DataString), Length(Header.DataString), HTTP_ADDREQ_FLAG_ADD);

          if HTTPSendRequest(pRequest, nil, 0, Pointer(AData), Length(AData)) then
          begin
            BufStream := TMemoryStream.Create;
            try
              while InternetReadFile(pRequest, @aBuffer, SizeOf(aBuffer), BytesRead) do
              begin
                if (BytesRead = 0) then Break;
                BufStream.Write(aBuffer, BytesRead);
              end;

              aBuffer[0] := #0;
              BufStream.Write(aBuffer, 1);
              Result := PChar(BufStream.Memory);
            finally
              BufStream.Free;
            end;
          end;
        finally
          Header.Free;
        end;
      finally
        InternetCloseHandle(pRequest);
      end;
    finally
      InternetCloseHandle(pConnection);
    end;
  finally
    InternetCloseHandle(pSession);
  end;
end;

ParseURL ist eine Funktion, die eine URL in „Hostname / Dateiname“ aufspaltet und TStringArray ist ein Array von Strings. Ich habe immer noch den Code morgen überprüfen, aber es sieht gut aus und in meinem Sniffer sah ich die Post-Daten und Header gesendet werden.

Andere Tipps

Persönlich bevorzuge ich die Synapse rel="nofollow Bibliothek für alle meine TCP / IP Arbeit. Zum Beispiel kann eine einfache HTTP-Post kodiert werden:

uses
  httpsend;

function testpost;
begin
  stm := tStringstream.create('param=value');
  try
    HttpPostBinary('http://example.com',Stm);
  finally
    stm.free;
  end;
end;

Die Bibliothek ist gut geschrieben und sehr einfach zu ändern, um Ihre spezifische Anforderungen anpassen. Die neueste Subversion Release funktioniert ohne Probleme sowohl für Delphi 2009 und Delphi 2010. Dieser Rahmen nicht Komponente basiert, sondern ist eine Reihe von Klassen und Verfahren, die auch in einer Multi-Threaded-Umgebung.

Der dritte Parameter (lpszObjectName) an HttpOpenRequest sollte die URL Sie möchten beantragen. Deshalb ist die Dokumentation des fünften Parameter (lpszReferer) beschreibt als „ein Zeiger auf einen nullterminierten String, der die URL des Dokuments angibt, von dem die URL in der Anfrage (lpszObjectName) erhalten.“

Die eingestellten Daten werden mit HttpSendRequest gesendet; der LpOptional Parameter wird wie folgt beschrieben:

  

Zeiger auf einen Puffer alle optionalen Daten enthalten, unmittelbar nachdem die Anfrage-Header gesendet werden sollen. Dieser Parameter wird für POST und PUT-Operationen verwendet. Die optionalen Daten können die Ressource oder Informationen werden an den Server gesendet. Dieser Parameter kann NULL sein, wenn es keine optionalen Daten zu senden.

Der zweite Parameter an InternetOpen sollte nur der Servername ; es sollte nicht das Protokoll enthalten. Das Protokoll, das Sie mit dem sechsten Parameter angeben.

Nachdem Sie die Anfrage gesendet haben, können Sie die Antwort mit InternetReadFile und InternetQueryDataAvailable .

Sie nicht nur prüfen, ob die API-Funktionen Null zurück und dann in der nächsten Zeile fort. Wenn sie versagen, nennen GetLastError um herauszufinden, warum. Der Code, den Sie geschrieben haben, werden Ausnahmen nicht erhöhen, so ist es sinnlos jeder zu fangen. (Und es ist dumm zu „behandeln“, um sie so, wie Sie sind so ohnehin tun. Sie eine Ausnahme nicht fangen, die Sie nicht bereits wissen, wie sie zu beheben. Lassen Sie alles andere an den Anrufer gehen, oder der Anrufer des Anrufers, usw. ).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top