Nodejs Book: Chapter 8

In the previous chapter we uploaded an image by sending the binary directly.
But the issue was we able to send the information, but at the cost of losing
information on the filename. So if we want to have our cake and eat it too, we
need a method of separating and parsing the information we send to and from
our server.

Fortunately there is already a standard in place for doing this. When form data
is sent from a browser client to a server, the browser arranges the information
in being sent to the server in a method the server can parse and respond to. In
this chapter, we’re just going to confirm the format in which information is sent
from the client to server. We will worry about parsing this information in the
next chapter.

The file layout of this chapter’s code is listed below.

- callback.js
+ public/
| - form.html
| - + js/
| --- form.js

We have a pretty simple form.html, consisting of a form with a table and a few
example fields, such as a username, email, password and phone number.

File: form.html

<!DOCTYPE HTML>
<html>

    <head>

        <meta charset="utf-8"/>
        <title>Ajax Request</title>

    </head>

    <body>

        <form id="exampleForm">
            <table>
                <tr>
                    <td>Username:</td>
                    <td><input type="text" name="username"/></td>
                </tr>
                <tr>
                    <td>Email:</td>
                    <td><input type="text" name="email"/><br></td>
                </tr>
                <tr>
                    <td>Password:</td>
                    <td><input type="password" name="password"/></td>
                </tr>
                <tr>
                    <td>Phone Number:</td>
                    <td><input type="text" name="phone_number"/></td>
                </tr>
                <tr>
                    <td>Submit:</td>
                    <td><input type="submit" value="Submit"/></td>
                </tr>
            </table>
        </form>

        <br>

        <pre id="responseText"></pre>

        <script type="text/javascript" src="js/form.js"></script>

    </body>

</html>

Our Javascript also hasn’t changed much, but we use yet another method of
sending information. In this case we use the internal FormData Javascript object
to handle creating the form send request for us.

File: js/form.js

"use strict";

var exampleForm = document.getElementById("exampleForm");
var responseText = document.getElementById("responseText");

exampleForm.addEventListener("submit", function (event) {

    event.preventDefault();

    var formData = new FormData(exampleForm);

    var xml = new XMLHttpRequest();
    xml.open("POST", "/api/form", true);
    xml.send(formData);

    xml.onload = function() {

        responseText.textContent = xml.responseText;

    }


});

The reason event.preventDefault() is included because the default response
to a form submit, is for the browser to create, send a response to the server,
and then load a new page. In this case we handle everything with Javascript via
ajax, so we don’t want the browser to handle the event.

File: callback.js

"use strict";

const fs = require("fs");
const http = require("http");
const uniqid= require("uniqid");
const handleFile = require("handle-file");

const server = http.createServer();
server.on("request", handleRequest);
server.listen(8080, handleListen);

function handleRequest(req, res) {

    console.log(req.method);

    if(req.method === "GET") {

        handleFile(req, res);

    } else if(req.method === "POST") {

        switch(req.url) {
            case "/api/hello":

                api_say_hello(req, res);

            break;
            case "/api/upload":

                api_upload_file( req, res );

            break;
            case "/api/form":

                api_form( req, res );

            break;
            default:

                res.writeHead( 204, { "Content-Type" : "text/plain" });
                res.end( "Empty Response" );

            break;
        }

    } else {

        res.writeHead( 204, { "Content-Type" : "text/plain" });
        res.end( "Empty Response" );

    }

}

function handleListen( ) {

    console.log("Server is listening on port 8080");

}

function api_form( req, res ) {

    var str = "";

    req.on("data", function(data) {

        str += data;

    });

    req.on("end", function() {

        res.writeHead(200, { "Content-Type" : "text/plain" });
        res.end( str );

    });

}

Since we’re just debugging we have a very simple function for handling our form.
We create a string and continue to add into it as we get content from the client.
And then we just return the string received from the client back to the client so
we can display it in the browser.

The content is as follows:

-----------------------------2285823208496
Content-Disposition: form-data; name="username"

my_username
-----------------------------2285823208496
Content-Disposition: form-data; name="email"

my_email@example.com
-----------------------------2285823208496
Content-Disposition: form-data; name="password"

12345678
-----------------------------2285823208496
Content-Disposition: form-data; name="phone_number"

080-2222-3333
-----------------------------2285823208496--

In the next chapter we will derive a function to parse this information.