...veramente sono un Mohicano, non un Apache... |
Bene, senza stare a ripetere tutto il codice e la maniera di generarlo (c'è già tutto in "L'ultimo degli Apache II - La vendetta") riscriveremo solo la funzione myapmodHandler() e aggiungeremo una nuova funzione getPost(). Vai col codice!
// handler del modulo static int myapmodHandler( request_rec *reqrec) // request data { // test handler if (! reqrec->handler || strcmp(reqrec->handler, "myapmod")) return DECLINED; // set del appropriato content type ap_set_content_type(reqrec, "text/html"); // test metodo http if (reqrec->method_number == M_GET) { // petizione GET: scrive solo "Hello, World!" ap_rprintf(reqrec, "GET request: Hello, world!"); } else if (reqrec->method_number == M_POST) { // petizione POST: legge POST data char *data; if (readPost(reqrec, &data) != -1) { // scrive "Hello, World!" e mostra POST data ap_rprintf(reqrec, "POST request: Hello, world! postdata: %s", data); } else { // POST data non disponibile: scrive solo "Hello, World!" ap_rprintf(reqrec, "POST request: Hello, world!"); } } else return HTTP_METHOD_NOT_ALLOWED; // esce con OK return OK; } // funzione per leggere POST data static int readPost( request_rec *reqrec, // request data char **data) // buffer di destinazione per POST data { // setup del client per permettera che Apache legga il request body if (ap_setup_client_block(reqrec, REQUEST_CHUNKED_ERROR) == OK) { // determina se il client ha spedito dati if (ap_should_client_block(reqrec)) { // legge i dati di 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 di inserzione dati nel buffer di destinazione 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 blocco di dati memcpy((char *)*data + rpos, argsbuffer, rsize); rpos += rsize; } // POST data letto: return OK return 0; } } // esce con NOK return -1; }Ok, come vedete è ampiamente commentato e quindi è auto-esplicativo, per cui non mi dilungherò sulle singole istruzioni e/o gruppi di istruzioni (leggete i commenti! sono li per quello!), ma aggiungerò, solo, qualche dettaglio strutturale.
L'originale funzione myapmodHandler() è diventata una sorta di funzione helloworld (beh, in pratica lo era anche prima), che distingue i tipi di petizione e, nel caso POST, chiama la funzione readPost() e scrive come risposta "Hello, world!" più i dati. Nel caso di petizioni GET o di petizioni POST senza dati si limita a scrivere "Hello, world!", e per altri tipi di petizione esce con errore.
La funzione readPost() è semplice ma non immediata: a suo tempo la derivai dall'unico esempio interessante e ben fatto che trovai, e che stava nel (ottimo) libro "Writing Apache Modules with Perl and C", che vi raccomando. Direi che nell'ultima versione di Apache, la 2.4, sono stati introdotti (e descritti qui) altri metodi di estrazione dei dati POST (vi auguro una buona lettura!), comunque io me l'ero cavata così, e il modulo funzionava (e funziona tutt'ora) benissimo.
Ah, il test, dimenticavo! Testare con petizioni POST non è semplice come farlo con le GET, dove è sufficiente (come detto nel post precedente) scrivere la URI del modulo nella barra degli indirizzi di Firefox o Chrome e aspettare la risposta. Per testare il nostro nuovo modulo è meglio usare un bel plugin del browser (tipo Poster) per semplificare il lavoro.
Va bene, per il momento credo che possiamo fermare per un tempo l'argomento moduli Apache/lighttpd. Giuro che nel prossimo post parlerò d'altro, non vorrei che pensaste che il C si usa solo per i Web Servers...
Ciao e al prossimo post!
Nessun commento:
Posta un commento