Curl es una librería escrita en
C para utilizar diversos protocolos de red y
LibCurlNet es un wrapper de la librería para usarla en
.Net Framework es una buena alternativa para las clases que derivan de
WebRequest sobre todo si quieres usar un protocolo no so soportado por
WebRequest, los protocolos que soporta esta
API son
HTTP, HTTPS, FTP, FTPS, SCP, SFTP, TFTP, TELNET, LDAP, DICT y FILE.
Además
WebRequest a veces falla sin ninguna razón aparente y también en estos casos podrías usar
Curl como una alternativa.
Se puede descargar
desde el sitio de LibCurlNet.
LibCurlNet nos presenta dos formas de uso principalmente la llamada
easy y la llamada
multi, En esta entrada hablare de la interfaz
easy con
HTTP que como su nombre nos indica es muy sencilla de usar, un poco más complicado que
WebRequest pero no demasiado.
El
API se accede en el espacio de nombres
SeasideResearch.LibCurlNet y lo primero que hay que hacer es inicializar el
API con la llamada al método
Curl.GlobalInit y al terminar de usar el
API se usa necesariamente el método
Curl.GlobalCleanup, es muy importante hacer estas llamadas solo una vez en toda la vida del programa de lo contrario obtendremos errores.
Ahora pasamos a usar la clase
Easy para bajar un archivo
html con la operación
GET (también se soporta
POST y
PUT).
El wrapper usa casi directamente el
API en
C y no esta muy orientada a objetos pero aún así resulta muy sencilla de utilizar en general usamos la funcíon
SetOpt del objeto
Easy para establecer las opciones de transferencia incluyendo la URL, proxy, headers, seguimiento de redirecciones, etc y utilizamos la llamada a Perform para obtener el resultado, aquí es donde esta la mayor diferencia entre
WebRequest y
CURL, la llamada a
Perform por si misma lleva a cabo toda la transferencia, pero lo único que nos da como resultado es código que nos indica si se realizo la transferencia o no y la causa del fallo, para obtener los datos tenemos que escribir una función que usara el objeto
Easy (como un delegado) para transmitirnos los datos en forma de un arreglo de bytes y es nuestra responsabilidad decidir que hacemos con esos bytes.
También podemos obtener el código
http de la respuesta con la función
GetInfo.
Si queremos remplazar o eliminar los headers que manda
Curl automáticamente podemos agregar estos headers con o sin valor y se eliminaran o remplazaran en la transferencia.
El mismo objeto
Easy se puede usar cuantas veces queramos para diferentes URLs y el mismo tratara de reutilizar la misma conexión a menos que se indique lo contrario, cuando se termine de usar debemos llamar a
easy.Cleanup antes de la llamada a
Curl.GlobalCleanup de lo contrario se provocara un error.
A continuación les dejo el ejemplo en
C# que explica el proceso por si mismo.
static void Main(string[] args) {
Curl.GlobalInit((int)CURLinitFlag.CURL_GLOBAL_ALL);
Easy easy = new Easy();
easy.SetOpt(CURLoption.CURLOPT_URL, "http://localhost/");
easy.SetOpt(CURLoption.CURLOPT_FOLLOWLOCATION, true);
easy.SetOpt(CURLoption.CURLOPT_CONNECTTIMEOUT, 10);
easy.SetOpt(CURLoption.CURLOPT_TIMEOUT, 90);
easy.SetOpt(CURLoption.CURLOPT_PROXY, "http://localhost:8080");
easy.SetOpt(CURLoption.CURLOPT_USERAGENT, "My Download");
easy.SetOpt(CURLoption.CURLOPT_ENCODING, "gzip,deflate");
easy.SetOpt(CURLoption.CURLOPT_FAILONERROR, true);
Slist headers = new Slist();
headers.Append("Pragma:");
headers.Append("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7");
easy.SetOpt(CURLoption.CURLOPT_HTTPHEADER, headers);
List<byte> buffer = new List<byte>();
Easy.WriteFunction writer = new Easy.WriteFunction(OnWriteData);
easy.SetOpt(CURLoption.CURLOPT_WRITEFUNCTION, writer);
easy.SetOpt(CURLoption.CURLOPT_WRITEDATA, buffer);
easy.Perform();
int code = 0;
easy.GetInfo(CURLINFO.CURLINFO_RESPONSE_CODE, ref code);
easy.Cleanup();
Curl.GlobalCleanup();
string content = "";
using(MemoryStream mStream = new MemoryStream(buffer.ToArray())) {
using(StreamReader reader
= new StreamReader(mStream, Encoding.UTF8)) {
content = reader.ReadToEnd();
}
}
Console.WriteLine("Status: " + code.ToString());
Console.WriteLine(content);
Console.WriteLine("leido");
Console.ReadLine();
}
private static Int32 OnWriteData(Byte[] buf, Int32 size, Int32 nmemb
, Object extractData) {
List<byte> buffer = (List<byte>)extractData;
buffer.AddRange(buf);
return size * nmemb;
}