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.
CodePudding user response:
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 !
CodePudding user response:
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();
}