{"id":278,"date":"2020-06-06T09:15:22","date_gmt":"2020-06-06T00:15:22","guid":{"rendered":"https:\/\/blog.wsd.sh\/?p=278"},"modified":"2020-06-06T09:21:44","modified_gmt":"2020-06-06T00:21:44","slug":"nodejs-book-chapter-6","status":"publish","type":"post","link":"https:\/\/blog.wsd.sh\/?p=278","title":{"rendered":"Nodejs Book: Chapter 6"},"content":{"rendered":"<p>In the previous chapter, we created a very simple proof of concept ajax request<br \/>\nfrom within a client Javascript. In this chapter we&#8217;re going to expand on this<br \/>\nexample so that instead of just the static text, &#8220;Hello, World!&#8221; change the<br \/>\nrequest so we return &#8220;Hello <name>!&#8221;. The output from this chapter will look<br \/>\nlike the following.<\/name><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_08-300x233.jpg\" alt=\"\" class=\"alignnone size-medium wp-image-279\" width=\"300\" height=\"233\" srcset=\"https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_08-300x233.jpg 300w, https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_08-1024x794.jpg 1024w, https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_08-768x595.jpg 768w, https:\/\/blog.wsd.sh\/wp-content\/uploads\/2020\/06\/fig_08.jpg 1135w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>The client side code is the most similar so we&#8217;ll take a look at that first.<\/p>\n<p>File: post.html<\/p>\n<pre>&lt;!DOCTYPE HTML&gt;\n&lt;html&gt;\n\n    &lt;head&gt;\n\n        &lt;meta charset=\"utf-8\"\/&gt;\n        &lt;title&gt;Ajax Request&lt;\/title&gt;\n\n    &lt;\/head&gt;\n\n    &lt;body&gt;\n\n        &lt;input type=\"text\" id=\"inputName\"\/&gt;\n        &lt;button id=\"clickBtn\"&gt;Click Me!&lt;\/button&gt;\n        &lt;p id=\"responseText\"&gt;&lt;\/p&gt;\n\n        &lt;script type=\"text\/javascript\" src=\"js\/post.js\"&gt;&lt;\/script&gt;\n\n    &lt;\/body&gt;\n\n&lt;\/html&gt;\n<\/pre>\n<p>Above is the code for the hmtl, it&#8217;s almost entirely identical, with the only<br \/>\ndifference being that we add a new input element, for the user to enter<br \/>\ntheir name. The code for the client side Javascript is largely unchanged as<br \/>\nwell. The source code is as listed below.<\/p>\n<p>File: js\/post.js<\/p>\n<pre>\"use strict\";\n\nvar inputName = document.getElementById(\"inputName\");\nvar clickBtn = document.getElementById(\"clickBtn\");\nvar responseText = document.getElementById(\"responseText\");\n\nclickBtn.addEventListener(\"click\", function (event) {\n\n    var args = {\n        \"name\" : inputName.value\n    }\n\n    var xml = new XMLHttpRequest();\n    xml.open(\"POST\", \"\/api\/hello\", true);\n    xml.send(JSON.stringify(args));\n\n    xml.onload = function() {\n\n        responseText.textContent = xml.responseText;\n\n    }\n\n\n});\n<\/pre>\n<p>The main difference is that we now create a JSON object to be sent to the server,<br \/>\nwhich we refer to as args. We also set the request type as &#8220;POST&#8221; for the xml.open<br \/>\nfunction and input the string representation of the arguments we want sent to the<br \/>\nserver.<\/p>\n<p>If your wondering where the &#8220;GET&#8221; and &#8220;POST&#8221; types come from, they are two specific<br \/>\ntypes of http request. GET is likely the most common, as it only sends a URL<br \/>\nwith a set of headers to the server to ask for a given resource. POST is different<br \/>\nin that in addition to a URL and headers, a body is also sent with the request. In<br \/>\nthis case our JSON string is attached to the body of the request to the server.<\/p>\n<p>There are also other standard http requests. HEAD, which just requests HTTP header<br \/>\nresponses with no body. PUT to send information, DELETE to request the deletion<br \/>\nof a resource, OPTIONS which returns the HTTP methods the server supports, and CONNECT<br \/>\nwhich converts the connection to a TCP tunnel.<\/p>\n<p>Which brings us to the source for the actual server:<\/p>\n<p>File: callback.js<\/p>\n<pre>\"use strict\";\n\nconst http = require(\"http\");\nconst handleFile = require(\"handle-file\");\n\nconst server = http.createServer();\nserver.on(\"request\", handleRequest);\nserver.listen(8080, handleListen);\n\nfunction handleRequest(req, res) {\n\n    if(req.method === \"GET\") {\n\n        handleFile(req, res);\n\n    } else if(req.method === \"POST\") {\n\n        switch(req.url) {\n            case \"\/api\/hello\":\n\n                api_say_hello(req, res);\n\n            break;\n            default:\n\n                res.writeHead( 204, { \"Content-Type\" : \"text\/plain\" });\n                res.end( \"Empty Response\" );\n\n            break;\n        }\n\n    } else {\n\n        res.writeHead( 204, { \"Content-Type\" : \"text\/plain\" });\n        res.end( \"Empty Response\" );\n\n    }\n\n}\n\nfunction handleListen( ) {\n\n    console.log(\"Server is listening on port 8080\");\n\n}\n\nfunction api_say_hello( req, res ) {\n\n    var json_str, json;\n\n    var json_str = \"\";\n\n    req.on(\"data\", function(data) {\n\n        json_str += data;\n\n    });\n\n    req.on(\"end\", function() {\n\n        try {\n            json = JSON.parse(json_str);\n        } catch(err) {\n            res.writeHead( 400, { \"Content-Type\" : \"text\/plain\" });\n            return res.end( \"Invalid JSON parameter\" );\n        }\n\n        res.writeHead(200, { \"Content-Type\" : \"text\/plain\" });\n        res.end(\"Hello \" + json.name);\n\n    });\n\n}\n<\/pre>\n<p>The first thing that sticks out is the handle function request.<\/p>\n<pre>function handleRequest(req, res) {\n\n    if(req.method === \"GET\") {\n\n        handleFile(req, res);\n\n    } else if(req.method === \"POST\") {\n\n        switch(req.url) {\n            case \"\/api\/hello\":\n\n                api_say_hello(req, res);\n\n            break;\n            default:\n\n                res.writeHead( 204, { \"Content-Type\" : \"text\/plain\" });\n                res.end( \"Empty Response\" );\n\n            break;\n        }\n\n    } else {\n\n        res.writeHead( 204, { \"Content-Type\" : \"text\/plain\" });\n        res.end( \"Empty Response\" );\n\n    }\n\n}\n<\/pre>\n<p>We can use the request method to quickly filter what the intent of the request is.<br \/>\nFor GET requests, we can assume a file is being requested and serve a file. In the<br \/>\ncase of POST, we can consider it a call to the server from an ajax client, and filter<br \/>\nout which function should be called to handle the request. And lastly to make sure<br \/>\nthat in the case of any other method type are handled and simply returned an empty<br \/>\nresponse.<\/p>\n<pre>function api_say_hello( req, res ) {\n\n    var json_str, json;\n\n    var json_str = \"\";\n\n    req.on(\"data\", function(data) {\n\n        json_str += data;\n\n    });\n\n    req.on(\"end\", function() {\n\n        try {\n            json = JSON.parse(json_str);\n        } catch(err) {\n            res.writeHead( 400, { \"Content-Type\" : \"text\/plain\" });\n            return res.end( \"Invalid JSON parameter\" );\n        }\n\n        res.writeHead(200, { \"Content-Type\" : \"text\/plain\" });\n        res.end(\"Hello \" + json.name);\n\n    });\n\n}\n<\/pre>\n<p>The actual code for handling our &#8220;\/api\/hello&#8221; reply is written above. When a client<br \/>\nsends a POST request to a server, it sends the information in packets. And if<br \/>\nthe information being sent to the server is large, the client server may have<br \/>\nto send the information in stages. So we listen for data to be sent and add it<br \/>\nto our JSON string, and then once the information has finished, we parse the JSON<br \/>\nstring. Once that&#8217;s finished we are able to send our response.<\/p>\n<p>So in this chapter we managed to send a simple JSON string to the server and got<br \/>\na response. So what about uploading files? We&#8217;ll work on that in the next chapter.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous chapter we wrote a simple Ajax call where we returned the simple expression &#8220;Hello World&#8221;. In this chapter we add on to the previous example by writing a simple echo function where we provide a Name as a parameter to the server, and have the server reply with &#8220;Hello Name&#8221;.<\/p>\n","protected":false},"author":1,"featured_media":249,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false},"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts\/278"}],"collection":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=278"}],"version-history":[{"count":4,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts\/278\/revisions"}],"predecessor-version":[{"id":283,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts\/278\/revisions\/283"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/media\/249"}],"wp:attachment":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=278"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=278"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=278"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}