Buenas a todos!
version: REVISION 6 (21/febrero/14)!!!!El martes me surgio la idea de enviar un HTTP POST de forma asincronica, y no encontre nada piola.
Hablando con Cobein se me ocurrio el de utilizar un codigo que use el HttpCreateRequest y HttpSendRequest, pero que la llamada bloqueante (HttpSendRequest) se haga en un thread aparte.
Ahora, la magia reside en que la parte "heavy" se hace en VB, mientras que en el thread solo se hace la llamada a HttpSendRequest y a SendMessageTimeout (para avisarle al thread 'main' que ya termino la ejecucion).
El codigo del thread esta hecho 100% en assembly (ver asm.asm). En dicho archivo, se ven unos pushs y unos llamados a cualquier lugar (fuera de joda, lo hice aproposito). La gracia de eso, es que el codigo en VB va a parchear eso, con llamadas a direcciones validas (la del HttpSendRequest y SendMessageTimeout), como asi tambien, reemplazar las "constantes" del hWnd de la ventana, y el uMsg custom. (la clase crea una ventana oculta para recibir los mensajes del thread, y el mensaje es uno custom, creado con RegisterWindowMessage).
La logica es sencilla. Se llama a la funcion SendRequest o SendRequest_OptionalAsByte con todos los parametros, inclusive el "private key", que seria un string para identificar los eventos (la diferencia radica en que la primera, el parametro opcional lpOptional es interpretado en base a un string, y en la segunda, es un array de bytes y precisa que se le pase el tamaño del mismo).
Tambien hay un parametro de Timeout.
Los demas parametros conforman a los que uno usaria al llamar a InternetConnect y HttpCreateRequest.
Hay varias enums de flags y demas, para usar en esas llamadas, o en QueryInfoAsXXXXX (puede ser AsLong, AsDate, AsString).
QueryInfoAsXXXX consulta algun parametro dentro del header y lo devuelve, segun el formato elegido (leer el msdn para saber si usar Long, Date o String). La funcion acomoda el tamaño del string automaticamente.
Luego quedan las funciones DumpRequestToBuffer, DumpRequestToString y DumpRequestToFile (todas estas leen el resultado del Request, y lo devuelven de maneras distintas).
Tambien hay una funcion mas, CancelRequest, la cual se podria llamar para cancelar un Request que se esta ejecutando.
Eventos: RequestDone (cuando HttpSendRequest termina), RequestCancelled (cuando es cancelado por el usuario), RequestTimeout (cuando hay timeout)
En el ejemplo hay 3 botones.
1º Descarga el google a googlex.html
2º Descarga 10 veces el google a google_xx.html
3º Envia un POST a un php en un host mio, que solamente devuelve el parametro "q"
- rev1: Ahora la cantidad maxima de request esta limitada (para prevenir arrays locks); Se volo a la mierda el PostMessage y se reemplazo por el
SendMessageTimeout (espera hasta que el thread main le responda); Se corrigieron unos leaks de handles (faltaba cerrar el hRequest) - rev2: Se corrigio el leak de handles (no se cerraba el objeto thread)
- rev3: Se agrego la opcion de "Esperar a que terminen todos los threads". Esto es importante, porque antes se deallocaba la memoria de los threads, y si estos aun estaban activos, iba a surgir un error de "Memory access violation". Ademas le agregue el evento del WM_TIMER, que me lo habia olvidado y no estaba funcionando la parte del timeout.
- rev4: Se agrego el soporte para SSL y Proxy. Se removieron muchos parametros y ahora solo se pasa una URL. Ahora en los eventos aparece el LastError del thread, el cual indica porque fallo el API. El "esperar a que los threads terminen" es una propiedad que puede ser cambiada en runtime (en IDE es 100% necesario!!!).
- rev5: Se arreglo DumpRequestToString y DumpRequestToBufer, el cual escribia en un pedazo de memoria que no correspondia.
- rev6: Se modificaron algunos eventos y propiedades para que el control se parezca mas al WinHTTP. Se agregó toda la logica de InternetReadFile en el thread, de forma que el thread de VB no se bloquea mas (ya que InternetReadFile bloquea).
(el link siempre es el mismo para LA ULTIMA VERSION)
DESCARGAR rev6Cualquier cosa los escucho...
Saludos!!!