Domanda

Sto provando a fare richieste HTTP da Delphi usando le funzioni WinInet.

Finora ho:

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;

Ma questo non fa nulla (sto annusando il traffico http di rete per vedere se funziona). Ho usato con successo InternetOpenURL ma devo anche inviare una richiesta POST e questa funzione non lo fa.

Qualcuno potrebbe mostrarmi un semplice esempio? Il risultato che voglio è ottenere la pagina di risposta http in una var come stringa.

È stato utile?

Soluzione

Ho inserito tutta la parte url / nomefile con il codice precedente. Sto usando questo di Jeff DeVore ora e funziona bene:

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 è una funzione che divide un URL in " nomehost / nomefile " e TStringArray è un array di stringhe. Domani devo ancora rivedere il codice ma sembra a posto e nel mio sniffer ho visto i dati dei post e le intestazioni inviate.

Altri suggerimenti

Personalmente preferisco utilizzare la synapse per tutto il mio TCP / IP lavoro. Ad esempio, un semplice post HTTP può essere codificato come:

uses
  httpsend;

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

La libreria è ben scritta e molto facile da modificare in base alle proprie esigenze specifiche. L'ultima versione di Subversion funziona senza problemi sia per Delphi 2009 che per Delphi 2010. Questo framework non è basato su componenti, ma piuttosto è una serie di classi e procedure che si adattano bene in un ambiente multi-thread.

Il terzo parametro (lpszObjectName) su HttpOpenRequest dovrebbe essere l ' URL che desideri richiedere. Ecco perché la documentazione descrive il quinto parametro (lpszReferer) come " un puntatore a una stringa con terminazione nulla che specifica l'URL del documento da cui è stato ottenuto l'URL nella richiesta (lpszObjectName). & Quot;

I dati pubblicati vengono inviati con HttpSendRequest ; il parametro lpOptional è descritto in questo modo:

  

Puntatore a un buffer contenente dati facoltativi da inviare immediatamente dopo le intestazioni della richiesta. Questo parametro viene generalmente utilizzato per le operazioni POST e PUT. I dati facoltativi possono essere la risorsa o le informazioni che vengono inviate al server. Questo parametro può essere NULL se non ci sono dati opzionali da inviare.

Il secondo parametro di InternetOpen dovrebbe essere solo il nome del server ; non dovrebbe includere il protocollo. Il protocollo specificato con il sesto parametro.

Dopo aver inviato la richiesta, puoi leggere la risposta con < code> InternetReadFile e InternetQueryDataAvailable .

Non limitarti a verificare se le funzioni API restituiscono zero e quindi procedi alla riga successiva. Se falliscono, chiama GetLastError per scoprire perché. Il codice che hai pubblicato non genererà eccezioni, quindi è inutile prenderne uno. (Ed è sciocco "gestirli" nel modo in cui lo fai comunque. Non cogliere un'eccezione che non sai già come risolvere. Lascia che tutto il resto salga al chiamante o al chiamante, ecc.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top