Home > Blockchain >  Why can I not send the contents of HTTP request as a response with express.js?
Why can I not send the contents of HTTP request as a response with express.js?

Time:06-19

I'm trying to set up a simple web server that returns the contents of the request as a response with node.js and express.js. My code is as below:

const express = require('express');
const app = express();
const port = 3000;

app.get("/", function(request,response){
  // console.log(request);
  response.send(request);
});

app.listen(port, function() {
  console.log("Server started on port #"   port);
});

And I get this error:

TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Socket'
    |     property 'parser' -> object with constructor 'HTTPParser'
    --- property 'socket' closes the circle
    at JSON.stringify (<anonymous>)

What exactly is happening and how can I modify my code to achieve my initial goal? I want to return a response that contains the contents of the request. I can console.log(request) without any issues so I'm even more confused here. I tried looking up this error but most don't seem to apply to this case.

CodePudding user response:

Please note that the Request type is not just the contents of the request, you can read about it on the official Node.js documentation. Most notably, the type represents an in-progress request whose header has already been queued. It is not the full request: the body may still being sent when you function is called! This is a common pattern in HTTP libraries, since you can process the HTTP headers before the body is even ready to be sent.

It's a complex object, which has circular references inside it. It means that some property of the object is pointing to another property of the same object, and can't represent that in JSON.Here's a good question about it. You can still do a console.log because the function handles circular references gracefully.

In order to echo the request back, you need to explicitly wait for the body to be sent completely (which may come in split in chunks). Again, the official docs cover this:

app.get("/", function(request,response){
  let body = [];
  request.on('data', (chunk) => {
    body.push(chunk);
  }).on('end', () => {
    body = Buffer.concat(body).toString();
    // at this point, `body` has the entire request body stored in it as a string
    response.send(body);
  });
});

If you want to extract other information from the request, you can look in the documentation on how to do it, but do not assume that the request or the response type are just their contents.

EDIT: I didn't realize you are using express.js, which has a different request type. The principals are the same, but the body is exposed in a different way, you can find how in the official documentation:

var express = require('express')

var app = express()

app.use(express.json()) // for parsing application/json
app.use(express.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded

get('/', function (req, res) {
  res.json(req.body)
})

CodePudding user response:

What do you need to know about the request? Method, url, headers, query, params...just extract what you need:

app.get("/", function(request,response){
  const { headers, method, url, search } = request;
  response.json({
    headers, method, url, search
  });
});

You should not send the whole request back, because it is a complex object that was never meant to be serialised.

  • Related