0

I'm writing a simple REST server as part of a javascript tutorial, but I don't know how to read POST data, and I don't even know how to get the length of the POST data. (I have no trouble processing a GET command.) Here's what I'm doing:

const http = require('http');
const URL = require('url').URL;

const book = {title:"Dune", author:"Frank Herbert"}

const app = http.createServer((req, res) => {
    console.log("Headers:", req.headers);
    accept = req.headers.accept;
    console.log("Accept:", accept);
    // contentLength = req.headers.contentLength;
    // console.log("content length:", contentLength);
    data = req.read(61);
    console.log("req.read(61):", data);

    let path=req.url;
    if (req.method === 'GET') {
        doGet(req, res, path);
    } else if (req.method === 'POST') {
        doPost(req, res, path);
    }
})

function doGet(req, res, path) {
    if (path === "/basic") {
        console.log("Basic path")
        res.writeHead(200, {"Content-Type": "text/json","Access-Control-Allow-Origin":"*"});
        res.write(JSON.stringify(book));
        res.end();
    } else {
        console.log("error path");
        res.writeHead(404, {"Content-Type": "text/json","Access-Control-Allow-Origin":"*"});
        // res.write(asHtml("Not Found"));
        res.write(JSON.stringify("{Not Found: " + path + "}"));
        res.end();
    }
}

// to test this method, I use this curl call:
// curl --data "{title:'Stranger In a Strange Land',author:'Robert Heinlein'}" localhost:4000/add
function doPost(req, res, path) {
    if (path === "/add") {
        res.writeHead(200);
        var data = '';
        req.on("data", function(chunk) {
            data += chunk;
        })
        console.log("req.on():", data);

        var postData = req.body;
        console.log("req.body:", postData);

        var readData = req.read();
        console.log("POST data by read:", readData);

        res.end();
    } else {
        res.writeHead(400);
        res.write('');
        res.end();
    }
}

app.listen(4000);

So I can get the value of the accept header with this expression: req.headers.accept But if I say req.headers.content-length it will throw an error, and if I say req.headers.'content-length', it won't even compile.

How can I read the value of the content-length, and how can I read the POST data?

Addendum: I should have been more clear about my results. The value of req.body is undefined.

Here is the output of the code above: (I modified it a bit for clarity.)

Headers: {
  host: 'localhost:4000',
  'user-agent': 'curl/7.79.1',
  accept: '*/*',
  'content-length': '61',
  'content-type': 'application/x-www-form-urlencoded'
}
Accept: */*
req.read(61): null     
req.on(): 
req.body: undefined    
POST data by read: null

As you can see, the content-length, at 61, is correct. But req.body, which is where I expected to find the data, is undefined.

2
  • 1
    It's in req.body. Commented Apr 23, 2022 at 23:20
  • I should have clarified. req.body returns undefined. I have modified the question to show my results. Commented Apr 24, 2022 at 1:13

2 Answers 2

1

The post data should be in req.body but try parsing the body first. Try using body-parser middleware on your app, and checking req.body again

Here's the documentation for this middleware and how to have your app automatically decode your request bodies for you, especially if you're using express, which is how you should be implementing a node server. The second link also walks through how to set up a simple JavaScript server, without needing body parser or express if you don't want to use it, and it comes directly from node.js documentation. It does require more setup, which is why express is recommended, but its up to you. Let me know if this helps !

Sign up to request clarification or add additional context in comments.

3 Comments

Unfortunately, the value of req.body is undefined. If it had held anything useful, I would have been happy with it.
I think you may have forgotten the req.on("end") portion. You have req.on("data") but not "end". Since receiving a request is asynchronous and occurs in a stream, you may have to add that portion, and on the req.on("end") you can parse your json data.
Actually, your 'node server' link explained it. I had never used javascript streams before so I didn't use the code correctly. I fixed it by changing the code that called res.on(). I posted the new code in a separate answer.
0

Here's the solution, which comes from the node server link provided in Arky Asmal's answer. First, when I process the valid POST request, I removed the call to res.end(). This looks all wrong, because without this call, the server never returns a result. But I fixed the code to read the stream using res.on(). Here's what it my doPost() method looks like now.

function doPost(req, res, path) {
    if (path === "/add") {
        res.writeHead(200);
        var postValue = '';
        // Read the stream.
        req.on("data", function(chunk) {
            postValue += chunk; // chunk is a buffer, but this still works.
        })
        req.on("end", () => {
            console.log('PostData:', postValue);
            console.log('req.body:', req.body); // still empty
            res.end(); // Don't send the reply till we're done reading the stream.
        })
    } else {
        res.writeHead(400);
        res.write('');
        res.end();
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.