Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Trucos (https://www.clubdelphi.com/foros/forumdisplay.php?f=52)
-   -   HTTP GET y HTTP POST utilizando WinInet (https://www.clubdelphi.com/foros/showthread.php?t=80771)

dec 01-11-2006 22:28:20

HTTP GET y HTTP POST utilizando WinInet
 
Bueno, como alternativa a Indy podemos usar Wininet. Podemos hacer Get, podemos hacer Post y maneja las cookies perfectamente incluso las de sesión. No tengo nada en contra de las Indy, es solo por dar alternativas, además no se pueden usar en el Turbo :( , aunque eso no es culpa suya.

Bueno, un poco de código para animar la cosa:
Código Delphi [-]
uses Windows, SysUtils, Classes,Wininet;

// URL Encode y Decode para codificar los strings segun la norma RFC 1738
function URLEncode(Str: string): string;
var
  i: integer;
begin
  Result:= '';
  for i:= 1 to Length(Str) do
    if Str[i] in ['A'..'Z','a'..'z','0'..'9','-','_','.'] then
      Result:= Result + Str[ i ]
    else
      Result:= Result + '%' + IntToHex(Ord(Str[ i ]),2);
end;

function URLDecode(Str: string): string;
var
  i: integer;
begin
  Result:= '';
  Str:= StringReplace(Str, '+', ' ', [rfReplaceAll]);
  while Length(Str) > 0 do
  begin
    if Copy(Str, 1, 1) = '%' then
    begin
      if not TryStrToInt('$' + Copy(Str, 2, 2),i) then
      begin
        Result:= '';
        Exit;
      end;
      Result:= Result + Char(i);
      Delete(Str, 1, 2);
    end else Result:= Result + Copy(Str, 1, 1);
    Delete(Str,1,1);
  end;
end;

// Con esta funcion hacemos Get y nos devuleve el resultado en un stream
function Get(Url: string; Stream: TStream): Boolean;
var
  hNet: HINTERNET;
  hUrl: HINTERNET;
  Buffer: array[0..10240] of Char;
  BytesRead: Cardinal;
begin
  Result:= FALSE;
  hNet:= InternetOpen('Agente', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if (hNet <> nil) then
  begin
    hUrl:= InternetOpenUrl(hNet, PChar(Url), nil, 0,
      INTERNET_FLAG_RELOAD, 0);
    if (hUrl <> nil) then
    begin
      while (InternetReadFile(hUrl, @Buffer, sizeof(Buffer), BytesRead)) do
      begin
        if (BytesRead = 0) then
        begin
          Result:= TRUE;
          break;
        end;
        Stream.Write(Buffer,BytesRead);
      end;
      InternetCloseHandle(hUrl);
    end;
    InternetCloseHandle(hNet);
  end;
end;

// Con esta funcion hacemos Post, los campos del formulario se pasan en PostString
// como pares nombre=valor
function Post(Servidor, Pagina: string; Puerto: Word;
  PostStrings: TStringList; Stream: TStream): Boolean;
var
  hNet: HINTERNET;
  hCon: HINTERNET;
  hReq: HINTERNET;
  Context: DWORD;
  Str: string;
  i: integer;
  Buffer: array[0..10240] of Char;
  BytesRead: DWORD;
begin
  Context:= 0;
  Result := FALSE;
  Str:= '';
  hNet := InternetOpen('Agente', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if (hNet <> nil) then
  begin
    hCon:= InternetConnect(hNet,PChar(Servidor),Puerto,nil,nil,
      INTERNET_SERVICE_HTTP,0,Context);
    if (hCon <> nil) then
    begin
      hReq:= HttpOpenRequest(hCon,'POST',PChar(Pagina),nil,nil,nil,
        INTERNET_FLAG_RELOAD,Context);
      if (hReq <> nil) then
      begin
        for i:= 0 to PostStrings.Count - 1 do
        begin
          Str:= Str + '&' + URLEncode(PostStrings.Names[i]) + '=' +
            URLEncode(PostStrings.ValueFromIndex[i]);
        end;
        Delete(Str,1,1);
        try
          if HttpSendRequest(hReq,nil,0,PChar(Str),Length(Str)) then
          begin
            while (InternetReadFile(hReq,@Buffer,sizeof(Buffer),BytesRead)) do
            begin
              if (BytesRead = 0) then
              begin
                Result := TRUE;
                break;
              end;
              Stream.Write(Buffer,BytesRead);
            end;
          end;
          except end;
        InternetCloseHandle(hReq);
      end;
      InternetCloseHandle(hCon);
    end;
    InternetCloseHandle(hNet);
  end;
end;

Un ejemplo de como usar lo anterior.
Código Delphi [-]
var
  Campos: TStringlist;
  Stream: TMemoryStream;
begin
  Campos:= TStringList.Create;
  Stream:= TMemoryStream.Create;
  try
    Campos.Values['Nombre']:= 'Valor';
    Post('www.clubdelphi.com','/',80,Campos,Stream);
    Stream.SaveToFile('d:\1.txt');
    Stream.Clear;
    Get('http://www.clubdelphi.com/',Stream);
    Stream.SaveToFile('d:\2.txt');
  finally
    Campos.Free;
    Stream.Free;
  end;
end;

vcarlosj 28-02-2007 18:14:50

Hola que tal..
He estado probando tu codigo y hay una parte en tu codigo que es:
hNet := InternetOpen('Agente', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);

por que: "Agente".

seoane 24-03-2007 18:38:36

Pues "Agente" es el nombre que identifica al navegador a la hora de hacer la petición, puedes usar el que tu quieras, o utilizar el mismo que el internet explorer o el firefox para suplantarlos. Aunque creo que a la hora de hacer este tipo de programas es interesante identificarse correctamente, así el servidor sabe que el que esta accediendo es un "robot", "spider" o como lo quieras llamar y no un usuario normal. Esta información le puede resultar útil al hacer estadísticas o al programar sus paginas.

davidvamo 07-05-2007 18:17:43

Buenas,
he probado tu ejemplo y todo correcto pero mi caso es que tengo que enviar por HTTPS hacia un WebService y por el puerto 4343 (para servidores de pruebas) o por el puerto 4433 (para servidores producción).

Tengo que enviar dos parámetros uno que es un código de referencia y el otro es código XML puro y duro.

¿Cómo hago que me use https y el puerto 4343 ó el 4433?.

Un ejemplo de la url que uso es la siguiente:

https://host:4343/WebServicesWeb/AqReceptorHTTP (srv pruebas)
ó
https://host:4433/WebServicesWeb/AqReceptorHTTP (srv. producción)

Muchas gracias y saludos.

davidvamo 07-05-2007 18:22:55

Buenas,
he probado tu ejemplo y todo correcto pero mi caso es que tengo que enviar por HTTPS hacia un WebService y por el puerto 4343 (para servidores de pruebas) o por el puerto 4433 (para servidores producción).

Tengo que enviar dos parámetros uno que es un código de referencia y el otro es código XML puro y duro.

¿Cómo hago que me use https y el puerto 4343 ó el 4433?.

Un ejemplo de la url que uso es la siguiente:

https://host:4343/WebServicesWeb/AqReceptorHTTP (srv pruebas)
ó
https://host:4433/WebServicesWeb/AqReceptorHTTP (srv. producción)

Muchas gracias y saludos.

Flecha 08-09-2008 11:35:56

Hola, ¿qué tal?
He probado el ejemplo y algo no funciona. Quizá sea por versión distinta de Delphi (yo tengo Delphi6), pero en la línea de código
Código:

URLEncode(PostStrings.ValueFromIndex[i]);
me dice que ValueFromIndex no está declarado. Así que lo he cambiado por
Código:

URLEncode(PostStrings.Strings[i]);
Por otro lado, yo intento acceder a una página realizada con ASP. En ella he puesto que me devuelva el típico "Hola mundo". Si accedo a ella con el explorador, veo el "Hola mundo" y me devuelve éste código fuente:
Código:

Hola mundo
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>WebForm1</title>
    <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
    <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
    <meta name=vs_defaultClientScript content="JavaScript">
    <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
  </head>
  <body MS_POSITIONING="GridLayout">

    <form name="Form1" method="post" action="webform1.aspx?parametro1=1&amp;parametro2=julian" id="Form1">
<input type="hidden" name="__VIEWSTATE" value="dDwtNjU0MzcyMTk1Ozs+tEUMoOMBCErd5wWPW47ZHfAC2AI=" />


    </form>

  </body>
</html>

Pero si accedo utilizando tus procedimientos es esto lo que me devuelve:
Código:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>WebForm1</title>
    <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
    <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
    <meta name=vs_defaultClientScript content="JavaScript">
    <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
  </head>
  <body MS_POSITIONING="GridLayout">

    <form name="Form1" method="post" action="webform1.aspx?parametro1=1&amp;parametro2=julian" id="Form1">
<input type="hidden" name="__VIEWSTATE" value="dDwtNjU0MzcyMTk1Ozs+tEUMoOMBCErd5wWPW47ZHfAC2AI=" />


    </form>

  </body>
</html>

Parece lo mismo, pero no lo es. Con tus procedimientos no me llega el "Hola mundo", así que no me vale.

¿Alguna idea para solucionarlo? Gracias.

Un saludo.

Flecha 08-09-2008 12:52:03

Ya sé lo que pasa.

Por alguna razón que desconozco el Post() falla porque la web no recibe los parámetros pasados.

Sin embargo el Get() sí que funciona pasándole todo el chorro de parámetros seguido a la junto al URL.

Un saludo.


La franja horaria es GMT +2. Ahora son las 14:46:01.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi