moy2010
moy2010

Reputation: 902

Send new request response with Node HTTP server

Stack Overflow community, greetings. I'm trying to pass the response of a new request on the request object using the Node HTTP Module for a basic autocomplete search app for my website (i.e using Node as a proxy that will transform and redirect the requests within the server).

The flow basically is:

Client Browser - Node - ElasticSearch - Node - Client Browser

I've started with:

The problem is that the content of newReqResponse is always outdated (trails behind the last typed character). i.e.:

And so on.

I've tried to solve it using Node.js streams and using the file system module to write and read files sync and async, but the result is the same. Here's a sample of the whole -code- picture:

var http = require('http');
var fs = require('fs');

http.createServer(function (req, res) {
    var reqBody = '';
    var newReqResponseBody = "";
    req.on('data', function (chunk) {
        reqBody += chunk;
        fs.writeFile('reqbody.json', reqBody, function(err) {
        if (err) {
          throw err;
        }
      });
      var options = {
      hostname: '127.0.0.1',
      port: 9500,
      method: 'GET',
      path: '/_search',
      headers: { host: 'es',
        'content-length': Buffer.byteLength(reqBody),
        'content-type': 'application/json',
        accept: 'application/json' },
    };
    
      var newReq = http.request(options, function (newReqResponse) {


    newReqResponse.setEncoding("UTF-8");

    newReqResponse.on('data', function (ch) {
      newReqResponseBody += ch;
    });
    
    newReqResponse.on("end", function() {
      fs.writeFile("newReqResponseBody.json", newReqResponseBody, function(err) {
        if (err) {
          throw err;
        }
      });
    });
    });

  
newReq.on("error", function(err) {
      console.log(`problem with request: ${err.message}`);
      });
newReq.write(reqBody);
newReq.end();


    });
     
    req.on('end', function() {
    var responseBody = fs.readFileSync('newReqResponseBody.json', 'utf8');
console.log(responseBody);
res.end(responseBody);   
    });
      
}).listen(3000, '127.0.0.1');

Is there a workaround to work with requests and responses within the http server? If there isn't, I'll be very grateful if you give me any directions on how to solve this.

Since the planned use for Node is rather basic, I prefer to stick with core modules rather than having to get new ones from npm, unless that it's necessary.

Thanks in advance.

EDIT:

All I had to do was to call res.end(responseBody) within the newReqResponse.on("end") callback, which is totally counterintuitive for me, but... it works.

Upvotes: 2

Views: 3300

Answers (1)

Luis Estevez
Luis Estevez

Reputation: 1407

Glad you solved your own problem. However, I see room for improvement (not sure if you're new), especially if you're transferring data. Which you can do with streams.

You can see that I didn't calculate the content length, you're asked not to and should get ignore (for this specific case) according to HTTP specification as streams pass data in chunks with 'Transfer-Encoding': 'chunked' header.

const fs = require('fs');
const http = require('http');

const options = {
    hostname: '127.0.0.1',
    port: 9500,
    method: 'GET',
    path: '/_search',
    headers: {
        'Content-Type': 'application/json'
    }
};

http.createServer((req, res) => {
    req.pipe(fs.createWriteStream('reqBody.json'));

    let request = http.request(options, (newRes) => {
        newRes.pipe(res);
    });
    fs.createReadStream('reqBody.json').pipe(request);

    res.setHeader('Content-Type', 'application/json');

}).listen(3000, '127.0.0.1');

You can shorten this snippet more if you don't want your data saved in the future and only want to pipe the req stream to request.

Upvotes: 1

Related Questions