...en realidad soy un Mohicano, no un Apache... |
Pues bien, sin molestarse en repetir todo el código y la forma de generarlo (hay de todo en "El último Apache II - El regreso"), sólo reescribiremos la función myapmodHandler() y añadiremos una nueva función getPost(). ¡Vamos con el código!
// handler del modulo static int myapmodHandler( request_rec *reqrec) // request data { // test handler if (! reqrec->handler || strcmp(reqrec->handler, "myapmod")) return DECLINED; // set del apropiado content type ap_set_content_type(reqrec, "text/html"); // test método http if (reqrec->method_number == M_GET) { // petición GET: escribe solo "Hello, World!" ap_rprintf(reqrec, "GET request: Hello, world!"); } else if (reqrec->method_number == M_POST) { // petición POST: lee POST data char *data; if (readPost(reqrec, &data) != -1) { // escribe "Hello, World!" y enseña POST data ap_rprintf(reqrec, "POST request: Hello, world! postdata: %s", data); } else { // POST data no disponible: escribe solo "Hello, World!" ap_rprintf(reqrec, "POST request: Hello, world!"); } } else return HTTP_METHOD_NOT_ALLOWED; // sale con OK return OK; } // función para leer POST data static int readPost( request_rec *reqrec, // request data char **data) // buffer de destinazion paraer POST data { // setup del client para permitir que Apache lea el request body if (ap_setup_client_block(reqrec, REQUEST_CHUNKED_ERROR) == OK) { // determina si el client ha enviado datos if (ap_should_client_block(reqrec)) { // lee los datos de POST char argsbuffer[HUGE_STRING_LEN]; int rsize, len_read, rpos=0; long length = reqrec->remaining; *data = (char*)apr_pcalloc(reqrec->pool, length +1); // loop de inserción datos en el buffer de destinación while ((len_read = ap_get_client_block(reqrec, argsbuffer, sizeof(argsbuffer))) > 0) { if ((rpos + len_read) > length) rsize = length - rpos; else rsize = len_read; // copia un bloque de datos memcpy((char *)*data + rpos, argsbuffer, rsize); rpos += rsize; } // POST data leido: return OK return 0; } } // sale con NOK return -1; }Ok, como se nota es ampliamente comentado y así se auto-explica, por lo cual no voy a detenerme sobre las instrucciónes y/o grupos de instrucciones (¡leer los comentarios! ¡Están ahí para eso!), pero voy a añadir, solamente, algunos detalles estructurales.
la función original myapmodHandler() se ha convertido en una especie de función helloworld (bueno, en práctica lo era incluso antes), que distingue los tipos de petición y, en el caso POST, llama a la función readPost() y escribe como respuesta "Hello, world!" mas los datos. En el caso de peticiones GET o POST sin datos se limita a escribir "Hola, mundo!", y para otros tipos de peticiones sale con error.
La función readPost() es simple, pero no es inmediata: en su tiempo la derivé de el único ejemplo interesante y bien hecho que encontré, y que estaba en el (óptimo) libro "Writing Apache Modules with Perl and C", que os recomiendo. Yo diría que en la última versión de Apache, la 2.4, se han introducido (y descritos aquí) otros métodos de extracción de datos de POST (¡os deseo buena lectura!), de todas maneras yo me la arreglé así, y el módulo funcionaba (y funciona todavía) muy bien.
¡Ah, el test, se me olvidaba! Testear con peticiones POST no es simple cómo hacerlo con las GET, adonde es suficiente (como dicho en el post anterior) escribir la URI del modulo en la barra de direcciones de Firefox o Chrome y esperar la respuesta. Para probar el nuestro nuevo módulo es mejor usar un buen plugin (como Poster, por ejemplo) que nos facilitará mucho la tarea.
Vale, de momento, creo que podemos parar por un tiempo el tema módulos de Apache/lighttpd. Juro que en el próximo post voy a hablar de otra cosa, no me gustaría que pensaran que el C se utiliza sólo para Web Servers...
¡Hasta el próximo post!
No hay comentarios:
Publicar un comentario