Question

J'essaie de faire des requêtes HTTP à partir de Delphi à l'aide des fonctions WinInet.

Jusqu'à présent, j'ai:

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;

Mais cela ne fait rien (je renifle le trafic réseau http pour voir si cela fonctionne). J'ai utilisé InternetOpenURL mais j'ai également besoin d'envoyer une requête POST, mais cette fonction ne le fait pas.

Quelqu'un pourrait-il me montrer un exemple simple? Le résultat souhaité est d’obtenir la page de réponse http dans une chaîne var as.

Était-ce utile?

La solution

J'ai eu toute la partie url / nom de fichier en désordre avec le code précédent. J'utilise cette de Jeff DeVore et tout fonctionne correctement:

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 est une fonction qui divise une URL dans " hostname / filename " et TStringArray est un tableau de chaînes. Il me reste à relire le code demain, mais il a l'air d'aller et, dans mon renifleur, j'ai vu les données et les en-têtes de messages envoyés.

Autres conseils

Personnellement, je préfère utiliser la bibliothèque synapse pour l'ensemble de mes TCP / IP. travail. Par exemple, une publication HTTP simple peut être codée comme suit:

uses
  httpsend;

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

La bibliothèque est bien écrite et très facile à modifier pour répondre à vos besoins spécifiques. La dernière version de Subversion fonctionne sans aucun problème pour Delphi 2009 et Delphi 2010. Ce cadre n’est pas basé sur des composants, mais plutôt sur une série de classes et de procédures qui fonctionnent bien dans un environnement multithread.

Le troisième paramètre (lpszObjectName) à HttpOpenRequest doit être URL que vous souhaitez demander. C'est pourquoi la documentation décrit le cinquième paramètre (lpszReferer) en tant que "pointeur sur une chaîne terminée par un caractère nul" spécifiant l'URL du document à partir duquel l'URL de la requête (lpszObjectName) a été obtenue. "

Les données publiées sont envoyées avec HttpSendRequest . / a>; le paramètre lpOptional est décrit comme suit:

  

Pointeur sur une mémoire tampon contenant les données facultatives à envoyer immédiatement après les en-têtes de la demande. Ce paramètre est généralement utilisé pour les opérations POST et PUT. Les données facultatives peuvent être la ressource ou les informations publiées sur le serveur. Ce paramètre peut être NULL s'il n'y a pas de données facultatives à envoyer.

Le deuxième paramètre à InternetOpen devrait être juste le nom du serveur ; il ne devrait pas inclure le protocole. Le protocole que vous spécifiez avec le sixième paramètre.

Après avoir envoyé la demande, vous pouvez lire la réponse avec < code> InternetReadFile et InternetQueryDataAvailable .

Ne vous contentez pas de vérifier si les fonctions de l'API renvoient zéro puis passez à la ligne suivante. Si elles échouent, appelez GetLastError pour savoir pourquoi. Le code que vous avez posté ne soulèvera pas d'exceptions, il est donc inutile d'en prendre aucune. (Et il est insensé de les "manipuler" comme vous le faites quand même. Ne capturez pas une exception que vous ne savez pas déjà comment corriger. Laissez tout le reste aller jusqu'à l'appelant, ou l'appelant, etc.)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top