Easily create nodejs server (10) : process POST requests

  • 2020-05-07 19:15:52
  • OfStack

So far, the server we've been working on isn't really useful, so let's start implementing some useful functionality.

Here's what we do: the user selects a file, uploads it, and then sees the uploaded file in the browser.

First we need a text area (textarea) for user input and then submit it to the server via the POST request.

We add the code in start event handler, requestHandlers.js is modified as follows:


function start(response) {
 console.log("Request handler 'start' was called.");
 var body = '<html>'+ '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" method="post">'+
    '<textarea name="text" rows="20" cols="60"></textarea>'+
    '<input type="submit" value="Submit text" />'+
    '</form>'+
    '</body>'+
    '</html>';
 response.writeHead(200, {"Content-Type": "text/html"});
 response.write(body);
 response.end();
}
function upload(response) {
 console.log("Request handler 'upload' was called.");
 response.writeHead(200, {"Content-Type": "text/plain"});
 response.write("Hello Upload");
 response.end();
}
exports.start = start;
exports.upload = upload;

Through in the browser to access http: / / localhost: 8888 / start can see the effect.

Next we will implement the trigger /upload request handler to handle the POST request when the user submits the form.

To make the whole process non-blocking, Node.js breaks up POST data into small chunks, which are then passed to the callback function by triggering specific events. The specific events here are the data event (to indicate that a new small block of data has arrived) and the end event (to indicate that all data has been received).

We do this by registering a listener (listener) on the request object. The request object here is passed to the onRequest callback function every time an HTTP request is received.

We put the code in the server, server.js is modified as follows:


var http = require("http");
var url = require("url");
function start(route, handle) {
 function onRequest(request, response) {
  var postData = "";
  var pathname = url.parse(request.url).pathname;
  console.log("Request for " + pathname + " received.");
  request.setEncoding("utf8");
  request.addListener("data", function(postDataChunk) {
   postData += postDataChunk;
   console.log("Received POST data chunk '"+ postDataChunk + "'.");
  });
  request.addListener("end", function() {
   route(handle, pathname, response, postData);
  });
 }
 http.createServer(onRequest).listen(8888);
 console.log("Server has started.");
}
exports.start = start;

The above code to do three things: first, we set the receiving data encoding format for UTF - 8, then register the "data" event listeners, used to collect each receives a new block of data, and its assignment to postData variables, in the end, we will request routing calls to end event handler, to ensure that it only be triggered only after the all data reception, and triggers only once. We also pass the POST data to the request route, because this data will be used by the request handler.

Next on the /upload page, show the inside of the user's input

Let's change router by 1.js:


function route(handle, pathname, response, postData) {
 console.log("About to route a request for " + pathname);
 if (typeof handle[pathname] === 'function') {
  handle[pathname](response, postData);
 } else {
  console.log("No request handler found for " + pathname);
  response.writeHead(404, {"Content-Type": "text/plain"});
  response.write("404 Not found");
  response.end();
 }
}
exports.route = route;

Then, in requestHandlers.js, we include the data in the response to the upload request:


function start(response, postData) {
 console.log("Request handler 'start' was called.");
 var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" method="post">'+
    '<textarea name="text" rows="20" cols="60"></textarea>'+
    '<input type="submit" value="Submit text" />'+
    '</form>'+
    '</body>'+
    '</html>';
 response.writeHead(200, {"Content-Type": "text/html"});
 response.write(body);
 response.end();
}
function upload(response, postData) {
 console.log("Request handler 'upload' was called.");
 response.writeHead(200, {"Content-Type": "text/plain"});
 response.write("You've sent: " + postData);
 response.end();
}
exports.start = start;
exports.upload = upload;

The last thing we want to do is we are currently passing the entire body of the request to the request routing and request handler. We should only pass the parts of the POST data that we are interested in to the request routing and request handler. In our example, we are really only interested in the text field.

We can use the querystring module described earlier to implement:


var querystring = require("querystring");
function start(response, postData) {
 console.log("Request handler 'start' was called.");
 var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" method="post">'+
    '<textarea name="text" rows="20" cols="60"></textarea>'+
    '<input type="submit" value="Submit text" />'+
    '</form>'+
    '</body>'+
    '</html>';
 response.writeHead(200, {"Content-Type": "text/html"});
 response.write(body);
 response.end();
}
function upload(response, postData) {
 console.log("Request handler 'upload' was called.");
 response.writeHead(200, {"Content-Type": "text/plain"});
 response.write("You've sent the text: "+ querystring.parse(postData).text);
 response.end();
}
exports.start = start;
exports.upload = upload;

Okay, that's all about working with POST data.

In the next section, we will realize the function of image upload.


Related articles: