Consumir un Http Form con mono/.net
En esta entrada muestro algo muy similar a lo que hago en esta (), en la cual consumo un método de un form http. A diferencia del artículo anterior, en esta oportunidad lo voy a hacer con mono (.net también).
En primer lugar presento una clase que generé, la cual es una abstracción de un http form:
Sus métodos son:
el constructor, el primer parametro es la url de la accion, y el segundo es la forma en que se envian los parámetros, si vemos en la declaracion del formulario, nos daremos cuenta cual es el valor indicado aquí:
agrega un campo al formulario, es decir un parámetro con su correspondiente valor.
elimina un parámetro agregado con RemoveField ().
simplemente invoca el método y retorna la respuesta de este, por ejemplo código html.
Bueno, ahora un ejemplo de su uso. En el siguiente, lo uso para buscar con google, y simplemente imprimo el codigo html resultante:
Por lo que se ve es facil de utilizar. Ahora vamos a mostrar un ejemplo un poquitito mas complicado, el cual utiliza herencia, y expresiones regulares para analizar la respuesta del método. Además el método es invocado utilizando POST:
Este ejemplo utiliza la herencia para definir una nueva clase, la cual utiliza el servicio de traducción de texto de google.
Entonces solo nos resta utilizarlo:
Bueno, ahora pongo todo este codigo completo para hacer copy/paste/test:
para compilar, simplemente:
$ mcs archivo.cs -r:System.Web
un ejemplo de su uso:
jaa@dino-thunder:~$ mono archivo.exe
El perro es blanco: The dog is white
Este es otro ejemplo: This is another example
jaa@dino-thunder:~$
Y esto es todo por ahora.
En primer lugar presento una clase que generé, la cual es una abstracción de un http form:
class HttpForm
{
public enum HttpFormMethod : uint
{
POST,
GET
}
HttpFormMethod method;
HttpWebRequest req;
HttpWebResponse resp;
Hashtable fields;
string url=null;
static string EncodeData (string paramName, string value)
{
return "&"+paramName+"="+HttpUtility.UrlEncode (value);
}
public HttpForm (string url, HttpFormMethod method)
{
fields = new Hashtable ();
this.method = method;
this.url = url;
}
public HttpForm AddField (string name, string val)
{
this.fields[name]=val;
return this;
}
public HttpForm RemoveField (string name)
{
try
{
this.fields.Remove(name);
}
catch (Exception ex)
{ }
return this;
}
private object getFieldsData ()
{
StringBuilder encodedData = new StringBuilder ();
foreach (DictionaryEntry de in this.fields)
encodedData.Append (EncodeData (de.Key.ToString(), de.Value.ToString()));
if (this.method == HttpFormMethod.POST)
{
return System.Text.Encoding.Default.GetBytes (encodedData.ToString());
}
return encodedData.ToString();
}
public virtual string Invoke ()
{
Stream postDataWriter= null;
StreamReader reader = null;
string response = null;
try
{
if (this.method == HttpFormMethod.POST)
{
byte [] buffer = (byte[])this.getFieldsData ();
this.req = (HttpWebRequest)WebRequest.Create (url);
this.req.Method = method.ToString ();
this.req.ContentLength = buffer.Length;
postDataWriter = this.req.GetRequestStream ();
postDataWriter.Write (buffer, 0, buffer.Length);
postDataWriter.Close ();
}
else
{
this.req = (HttpWebRequest)WebRequest.Create (url+"?"+this.getFieldsData ().ToString());
System.Console.WriteLine (url+"?"+this.getFieldsData ());
}
// obtiene la respuesta
resp = (HttpWebResponse) this.req.GetResponse ();
reader = new StreamReader (resp.GetResponseStream ());
response = reader.ReadToEnd ();
reader.Close ();
resp.Close ();
}
catch (Exception ex)
{
if (reader != null) reader.Close ();
if (resp != null) resp.Close ();
throw ex;
}
return response;
}
}
Sus métodos son:
-public HttpForm (string url, HttpFormMethod method)
el constructor, el primer parametro es la url de la accion, y el segundo es la forma en que se envian los parámetros, si vemos en la declaracion del formulario, nos daremos cuenta cual es el valor indicado aquí:
<form name="Consultar" action="../cgi-bin/ConsultaDisponibilidad.py" method="POST">
-public HttpForm AddField (string name, string val)
agrega un campo al formulario, es decir un parámetro con su correspondiente valor.
<input type="hidden" name="lang" value="es"/>
-public HttpForm RemoveField (string name)
elimina un parámetro agregado con RemoveField ().
-public virtual string Invoke ()
simplemente invoca el método y retorna la respuesta de este, por ejemplo código html.
Bueno, ahora un ejemplo de su uso. En el siguiente, lo uso para buscar con google, y simplemente imprimo el codigo html resultante:
HttpForm form = new HttpForm ("http://www.google.com.ar/search", HttpForm.HttpFormMethod.GET);
form.AddField ("hl","es");
form.AddField ("q","river+plate");
string ret = form.Invoke ();
System.Console.WriteLine (ret);
Por lo que se ve es facil de utilizar. Ahora vamos a mostrar un ejemplo un poquitito mas complicado, el cual utiliza herencia, y expresiones regulares para analizar la respuesta del método. Además el método es invocado utilizando POST:
class GoogleTranslator
: HttpForm
{
public enum Lang: uint
{
es,en
}
static string url="http://translate.google.com/translate_t?langpair=";
static string ComposeLangPair (Lang fromLang, Lang toLang)
{
return fromLang.ToString()+"|"+toLang.ToString();
}
public GoogleTranslator (Lang fromLang, Lang toLang)
: base (url+ComposeLangPair (fromLang, toLang), HttpFormMethod.POST)
{
this.AddField ("hl","es");
this.AddField ("ie","UTF-8");
this.AddField ("langpair",ComposeLangPair(fromLang, toLang));
}
static string ExtractTranslation (string htmlCode)
{
Regex TradRegex;
Regex TradSubRegex;
Match m;
Group trad;
string str_regex = @".*<div id=result_box dir=""ltr"">(([^<]+(<br>)*)*)</div>.*";
string str_subregex = "[ ]?<br>";
StringBuilder sb = null;
string ret_val = null;
TradRegex = new Regex (str_regex);
TradSubRegex = new Regex (str_subregex);
m = TradRegex.Match (htmlCode);
if (m.Value != string.Empty)
sb = new StringBuilder (m.Groups[1].Value);
if (sb != null)
{
sb.Replace ("<","<");
sb.Replace (">",">");
ret_val = sb.ToString ();
sb = null;
System.GC.Collect ();
ret_val = TradSubRegex.Replace (ret_val,"\n");
}
return ret_val;
}
public string Translate (string text)
{
string result=null;
this.RemoveField ("text");
this.AddField ("text",text);
result = this.Invoke ();
return ExtractTranslation (result);
}
}
Este ejemplo utiliza la herencia para definir una nueva clase, la cual utiliza el servicio de traducción de texto de google.
Entonces solo nos resta utilizarlo:
public static void Main(string[] args)
{
string result1 = null;
string result2 = "";
string text1="El perro es blanco";
string text2="Este es otro ejemplo";
GoogleTranslator gt = new GoogleTranslator (GoogleTranslator.Lang.es, GoogleTranslator.Lang.en);
result1 = gt.Translate (text1);
result2 = gt.Translate (text2);
System.Console.WriteLine ("{0}: {1}",text1,result1);
System.Console.WriteLine ("{0}: {1}",text2,result2);
}
Bueno, ahora pongo todo este codigo completo para hacer copy/paste/test:
// project created on 01/04/2008 at 13:39
using System;
using System.Web;
using System.Net;
using System.IO;
using System.Text; // StringBuilder
using System.Text.RegularExpressions;
using System.Collections;
namespace TestHttpRequest
{
class MainClass
{
public static void Main(string[] args)
{
string result1 = null;
string result2 = "";
string text1="El perro es blanco";
string text2="Este es otro ejemplo";
GoogleTranslator gt = new GoogleTranslator (GoogleTranslator.Lang.es, GoogleTranslator.Lang.en);
result1 = gt.Translate (text1);
result2 = gt.Translate (text2);
System.Console.WriteLine ("{0}: {1}",text1,result1);
System.Console.WriteLine ("{0}: {1}",text2,result2);
}
}
public enum Lang : short
{
es=0,
en=1
}
class HttpForm
{
public enum HttpFormMethod : uint
{
POST,
GET
}
HttpFormMethod method;
HttpWebRequest req;
HttpWebResponse resp;
Hashtable fields;
string url=null;
static string EncodeData (string paramName, string value)
{
return "&"+paramName+"="+HttpUtility.UrlEncode (value);
}
public HttpForm (string url, HttpFormMethod method)
{
fields = new Hashtable ();
this.method = method;
this.url = url;
}
public HttpForm AddField (string name, string val)
{
this.fields[name]=val;
return this;
}
public HttpForm RemoveField (string name)
{
try
{
this.fields.Remove(name);
}
catch (Exception ex)
{ }
return this;
}
private object getFieldsData ()
{
StringBuilder encodedData = new StringBuilder ();
foreach (DictionaryEntry de in this.fields)
encodedData.Append (EncodeData (de.Key.ToString(), de.Value.ToString()));
if (this.method == HttpFormMethod.POST)
{
return System.Text.Encoding.Default.GetBytes (encodedData.ToString());
}
return encodedData.ToString();
}
public virtual string Invoke ()
{
Stream postDataWriter= null;
StreamReader reader = null;
string response = null;
try
{
if (this.method == HttpFormMethod.POST)
{
byte [] buffer = (byte[])this.getFieldsData ();
this.req = (HttpWebRequest)WebRequest.Create (url);
this.req.Method = method.ToString ();
this.req.ContentLength = buffer.Length;
postDataWriter = this.req.GetRequestStream ();
postDataWriter.Write (buffer, 0, buffer.Length);
postDataWriter.Close ();
}
else
{
this.req = (HttpWebRequest)WebRequest.Create (url+"?"+this.getFieldsData ().ToString());
System.Console.WriteLine (url+"?"+this.getFieldsData ());
}
// obtiene la respuesta
resp = (HttpWebResponse) this.req.GetResponse ();
reader = new StreamReader (resp.GetResponseStream ());
response = reader.ReadToEnd ();
reader.Close ();
resp.Close ();
}
catch (Exception ex)
{
if (reader != null) reader.Close ();
if (resp != null) resp.Close ();
throw ex;
}
return response;
}
}
class GoogleTranslator
: HttpForm
{
public enum Lang: uint
{
es,en
}
static string url="http://translate.google.com/translate_t?langpair=";
static string ComposeLangPair (Lang fromLang, Lang toLang)
{
return fromLang.ToString()+"|"+toLang.ToString();
}
public GoogleTranslator (Lang fromLang, Lang toLang)
: base (url+ComposeLangPair (fromLang, toLang), HttpFormMethod.POST)
{
this.AddField ("hl","es");
this.AddField ("ie","UTF-8");
this.AddField ("langpair",ComposeLangPair(fromLang, toLang));
}
static string ExtractTranslation (string htmlCode)
{
Regex TradRegex;
Regex TradSubRegex;
Match m;
Group trad;
string str_regex = @".*<div id=result_box dir=""ltr"">(([^<]+(<br>)*)*)</div>.*";
string str_subregex = "[ ]?<br>";
StringBuilder sb = null;
string ret_val = null;
TradRegex = new Regex (str_regex);
TradSubRegex = new Regex (str_subregex);
m = TradRegex.Match (htmlCode);
if (m.Value != string.Empty)
sb = new StringBuilder (m.Groups[1].Value);
if (sb != null)
{
sb.Replace ("<","<");
sb.Replace (">",">");
ret_val = sb.ToString ();
sb = null;
System.GC.Collect ();
ret_val = TradSubRegex.Replace (ret_val,"\n");
}
return ret_val;
}
public string Translate (string text)
{
string result=null;
this.RemoveField ("text");
this.AddField ("text",text);
result = this.Invoke ();
return ExtractTranslation (result);
}
}
}
para compilar, simplemente:
$ mcs archivo.cs -r:System.Web
un ejemplo de su uso:
jaa@dino-thunder:~$ mono archivo.exe
El perro es blanco: The dog is white
Este es otro ejemplo: This is another example
jaa@dino-thunder:~$
Y esto es todo por ahora.

0 comentarios:
Publicar un comentario en la entrada
Suscribirse a Enviar comentarios [Atom]
<< Página principal