mercoledì, dicembre 10, 2014

Esercitazioni su node.js: esercizio 10

Testo dell'esercizio
Ancora un esercizio sull'uso degli stream associati a richieste e risposte http.
Creare un server http che riceva, in streaming sulla richiesta, un file da salvare nella directory corrente di lavoro, rappresentata dalla variabile globale __dirname.
Creare un client http che effettui una richiesta POST al server, mandando in streaming sulla richiesta il contenuto di un file di testo.

Suggerimenti
Trovate una bozza di soluzione a questo indirizzo: si tratta di implementare due programmi, un client http ed un server http. 
Il client crea un oggetto richiesta, passando opportuni opzioni di configurazione (indirizzo server, porta) e manderà in streaming sulla richiesta un file di testo tramite una pipe, chiudendo la richiesta quando la pipe ha finito di travasare i dati dal file alla richiesta stessa.
Il server, dualmente, legge in streaming la richiesta e scriverà i dati ricevuti su uno stream di scrittura associato ad un file, sempre tramite una pipe: appena finito chiuderà la risposta.

Buon Lavoro!

Una possibile soluzione
Vediamo prima il codice del programma client
 var http = require('http'),   
     fs = require('fs');  
   
 var options = {  
    host: 'localhost',   
    port: 8000, path: '/',   
    method: 'POST'  
 };  
   
 var req = http.request(options, function(res) {  
    console.log(res.statusCode);  
 });  
   
 var readStream = fs.ReadStream(__dirname + '/in.txt');  
        
      readStream.pipe(req);  
   
      readStream.on('close', function () {  
            req.end();  
            console.log('Io ho terminato di mandare il file al server...');  
      });
      console.log('Resto in attesa di chiusura connessione da parte del server ...');
Il codice è molto pulito e intuitivo, a patto di ricordarsi dell'asincronicità di alcune funzioni.
Per fare una richiesta http ad un server, viene creato un oggetto options con i dettagli di conettività: serve a configurare una richiest http di tipo post al server in esecuzione su localhost e porta 8000.

Viene utilizzato il modulo http per fare la richiesta. Il metodo request ritona subito uno stream di scrittura: tutto cio' che mandiamo su questo stream arriverà al server: la funzione di callback passata al metodo request viene eseguita solo quando il server finisce di rispondere.

Vine creato uno stream di lettura per il file in.txt presente nella cartella di lavoro, rappresentata dalla variabile globale __dirname: tramite una pipe viene scritto il suo contenuto sullo stream di scrittura req.

Quando finisce il flusso di lettura, viene invocato il metodo end() dello stream per permettere al server di elaborare la richiesta.

Vediamo ora la parte server
 var http = require('http'),   
     fs = require('fs'),  
     writeStream;  
   
 var server = http.createServer(function (req, res) {  
    writeStream = fs.createWriteStream(__dirname +   
                         'out_' +   
                         new Date().getTime() +  
                         '.txt');  
    req.pipe(writeStream);  
    req.on('end', function() {  
       writeStream.end();  
       res.statusCode = 200;  
       res.end('OK');  
    });  
 });  
   
 server.listen(8000, function() {  
      console.log('server http in ascolto sulla porta 8000');  
 });  
In maniera duale, per ogni richiesta che arriva al server, viene creato uno stream di scrittura associato ad un file presente in __dirname e con nome out_msda1/1/1970.txt su cui viene mandata in pipe il flusso di lettura rappresentato dalla richiesta.

Quando il flusso della richiesta è terminato, viene chiuso il flusso di scrittura del file e terminata la richiesta, con un codice standard di 200 (così come definito dal protocollo http) che causerà la chiusura della connessione.

Per testare il programma, mandate prima in esecuzione il server e poi il client da due shell diverse, magari provate a mandare in esecuzione, sempre su shell diverse, più programmi client,

Notate come, nonostante la funzione di callback sul client venga eseguita abbastanza in fretta, il server ci mette un po' a chiudere la connessione e quindi a far terminare il client: credo che sia una anomalia che dovrebbe essere messa a posto al più presto.

Ho aggiornato su github il progetto, effettuate un git pull per aggiornare i sorgenti che avete in locale, come mostrato in questo post

Come al solito, per dubbi e/o domande: commentate!

Alla prox.
Ivan

Nessun commento:

Posta un commento