2008-11-19 29 views
36

Hay un servicio web al que quiero llamar en mi aplicación, puedo usarlo para importar el WSDL o simplemente usar "HTTP GET" con la URL y los parámetros, por lo que prefiero el último porque es algo simple.¿Cuál es la forma más sencilla de llamar a Http GET url usando Delphi?

Sé que puedo usar indy idhttp.get, para hacer el trabajo, pero esto es algo muy simple y no quiero agregar código complejo indy a mi aplicación.

ACTUALIZACIÓN: lo siento si no estaba claro, que quiere decir "no agregar código de Indy complejo", que no quiero añadir componentes Indy por sólo esta tarea simple, y prefiero mucho más ligero para eso.

+0

¿Crees que solo usar HTTP GET es suficiente para invocar una función webservice? – Serguzest

+0

Es si se trata de un servicio web RESTful. –

+0

no sabía que REST puede tener wsdl también – Serguzest

Respuesta

24

podría utilizar el WinINet API así:

uses WinInet; 

function GetUrlContent(const Url: string): string; 
var 
    NetHandle: HINTERNET; 
    UrlHandle: HINTERNET; 
    Buffer: array[0..1024] of Char; 
    BytesRead: dWord; 
begin 
    Result := ''; 
    NetHandle := InternetOpen('Delphi 5.x', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); 

    if Assigned(NetHandle) then 
    begin 
    UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0); 

    if Assigned(UrlHandle) then 
     { UrlHandle valid? Proceed with download } 
    begin 
     FillChar(Buffer, SizeOf(Buffer), 0); 
     repeat 
     Result := Result + Buffer; 
     FillChar(Buffer, SizeOf(Buffer), 0); 
     InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead); 
     until BytesRead = 0; 
     InternetCloseHandle(UrlHandle); 
    end 
    else 
     { UrlHandle is not valid. Raise an exception. } 
     raise Exception.CreateFmt('Cannot open URL %s', [Url]); 

    InternetCloseHandle(NetHandle); 
    end 
    else 
    { NetHandle is not valid. Raise an exception } 
    raise Exception.Create('Unable to initialize Wininet'); 
end; 

fuente: http://www.scalabium.com/faq/dct0080.htm

La API de WinINet utiliza el mismo InternetExplorer cosas está utilizando por lo que también recibe cualquier configuración de conexión y proxy establecida por InternetExplorer gratis.

+1

Obtener la configuración de IE "gratis" es solo una característica si utiliza IE. :) –

+0

Gracias Lars, esa es la manera iluminada :) –

+1

Como dice bruce, si tuvieras un IE configurado incorrectamente para usar una configuración de proxy que está abajo, por ejemplo, también serás atacado. Oscuro y frustrante, si sucedió. –

29

Llamar a un servicio web RESTful utilizando Indy es bastante directo.

Agregue IdHTTP a su cláusula de usos. Recuerde que IdHTTP necesita el prefijo "HTTP: //" en sus URL.

function GetURLAsString(const aURL: string): string; 
var 
    lHTTP: TIdHTTP; 
begin 
    lHTTP := TIdHTTP.Create; 
    try 
    Result := lHTTP.Get(aURL); 
    finally 
    lHTTP.Free; 
    end; 
end; 
+3

La pregunta era si podría hacerse sin Indy –

+4

La cuestión era no agregar código complejo de Indy. El código no es complejo. –

+0

Bruce, Lars tiene razón, dije en mis preguntas que no quiero usar indyt "idhttp.get", es la manera más simple pero quería la forma iluminada :) –

2

Utilice la función Synapse TCP/IP en la unidad HTTPSEND (HTTPGetText, HTTPGetBinary). Hará la extracción de HTTP para usted y no requiere ninguna DLL externa que no sea Winsock. La última versión de SVN funciona perfectamente en Delphi 2009. Esto utiliza llamadas de función de bloqueo, por lo que no hay eventos para programar.

Actualización: Las unidades son muy livianas y no están basadas en componentes. La última versión de SVN funciona perfectamente también en Delphi XE4.

+1

Las llamadas HTTP en Indy también son bloqueantes. –

7

Si está bien descargar a un archivo, puede usar TDownloadURL desde la unidad ExtActns. Mucho más simple que usar WinInet directamente.

procedure TMainForm.DownloadFile(URL: string; Dest: string); 
var 
    dl: TDownloadURL; 
begin 
    dl := TDownloadURL.Create(self); 
    try 
    dl.URL := URL; 
    dl.FileName := Dest; 
    dl.ExecuteTarget(nil); //this downloads the file 
    finally 
    dl.Free; 
    end; 
end; 

También es posible obtener notificaciones de progreso al usar esto. Simplemente asigne un controlador de eventos al evento OnDownloadProgress de TDownloadURL.

11

En realidad el código en la respuesta aceptada no funcionó para mí. Así que lo modifiqué un poco para que realmente devuelva String y cierre todo con gracia después de la ejecución. El ejemplo devuelve datos recuperados como UTF8String, por lo que funcionará bien para ASCII y para las páginas UTF8.

uses WinInet; 

function GetUrlContent(const Url: string): UTF8String; 
var 
    NetHandle: HINTERNET; 
    UrlHandle: HINTERNET; 
    Buffer: array[0..1023] of byte; 
    BytesRead: dWord; 
    StrBuffer: UTF8String; 
begin 
    Result := ''; 
    NetHandle := InternetOpen('Delphi 2009', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); 
    if Assigned(NetHandle) then 
    try 
     UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0); 
     if Assigned(UrlHandle) then 
     try 
      repeat 
      InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead); 
      SetString(StrBuffer, PAnsiChar(@Buffer[0]), BytesRead); 
      Result := Result + StrBuffer; 
      until BytesRead = 0; 
     finally 
      InternetCloseHandle(UrlHandle); 
     end 
     else 
     raise Exception.CreateFmt('Cannot open URL %s', [Url]); 
    finally 
     InternetCloseHandle(NetHandle); 
    end 
    else 
    raise Exception.Create('Unable to initialize Wininet'); 
end; 

creo que sirve para alguien como yo que estaba buscando código fácil cómo recuperar contenido de la página en Delphi. Cheers, Aldis :)

+0

Y funciona con URLs HTTPS;) – Beny

1

Si su aplicación es solo para Windows, sugeriría que use WinSock. Es lo suficientemente simple, permite ejecutar cualquier solicitud HTTP, puede trabajar de forma síncrona y asíncrona (utilizando WSASend/WSARecv sin bloqueo con devoluciones de llamada o un buen envío/recv antiguo en un hilo dedicado).

4

El uso de la API HTTP de Windows podría ser fácil también.

procedure TForm1.Button1Click(Sender: TObject); 
var http: variant; 
begin 
http:=createoleobject('WinHttp.WinHttpRequest.5.1'); 
http.open('GET', 'http://lazarus.freepascal.org', false); 
http.send; 
showmessage(http.responsetext); 
end; 

En el código anterior, supongo que COM ya se ha inicializado para el hilo principal de VCL. Según se informa, puede no ser siempre el caso para aplicaciones simplistas o para aplicaciones LCL. También definitivamente no sería el caso para el trabajo asíncrono (multiproceso).

A continuación se muestra el código real cortado. Nota: la funcionalidad es extra. No es obligatorio trabajar. Entonces, mientras hago solicitudes de emisión, no me preocupan sus resultados, ese resultado se ignora y se descarta.

procedure TfmHaspList.YieldBlinkHTTP(const LED: boolean; const Key_Hardware_ID: cardinal); 
var URL: WideString; 
begin 
    URL := 'http://127.0.0.1:1947/action.html?blink' + 
    IfThen(LED, 'on', 'off') + '=' + IntToStr(Key_Hardware_ID); 

    TThread.CreateAnonymousThread(
    procedure 
    var Request: OleVariant; 
    begin 
     // COM library initialization for the current thread 
     CoInitialize(nil); 
     try 
     // create the WinHttpRequest object instance 
     Request := CreateOleObject('WinHttp.WinHttpRequest.5.1'); 
     // open HTTP connection with GET method in synchronous mode 
     Request.Open('GET', URL, False); 
     // set the User-Agent header value 
//  Request.SetRequestHeader('User-Agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0'); 
     // sends the HTTP request to the server, the Send method does not return 
     // until WinHTTP completely receives the response (synchronous mode) 
     Request.Send; 
//  // store the response into the field for synchronization 
//  FResponseText := Request.ResponseText; 
//  // execute the SynchronizeResult method within the main thread context 
//  Synchronize(SynchronizeResult); 
     finally 
     // release the WinHttpRequest object instance 
     Request := Unassigned; 
     // uninitialize COM library with all resources 
     CoUninitialize; 
     end; 
    end 
).Start; 
end; 
+1

Sí, esta es una solución excelente y simple, pero no olvide llamar 'CoInitialize (nil);' y 'CoUninitialize' al inicio y al final, respectivamente. – supersan

+2

Eso se menciona en los enlaces para el caso de subprocesos asíncronos. Sin embargo, en este ejemplo específico, el objeto opera dentro del hilo VCL principal, donde COM ya se inicializó. Supongo que (aunque no se comprobó) lo mismo vale para LCL en Windows –

+0

Quizás alguien debería mencionar también el objeto TJvURLGrabber de JediVCL ... –

3

En las nuevas versiones de Delphi es mejor utilizar THTTPClient de System.Net.HttpClient unidad, ya que es estándar y multiplataforma. El ejemplo simple es

function GetURL(const AURL: string): string; 
var 
    HttpClient: THttpClient; 
    HttpResponse: IHttpResponse; 
begin 
    HttpClient := THTTPClient.Create; 
    try 
    HttpResponse := HttpClient.Get(AURL); 
    Result := HttpResponse.ContentAsString(); 
    finally 
    HttpClient.Free; 
    end; 
end; 
Cuestiones relacionadas