We will inject the response object (from our server’s callback function onRequest()) through the router into the request handlers. The handlers will then be able to use this object’s functions to respond to requests themselves.
First we create an object. An an object in javascript is like a key/value dictionary, where we match keys and values up.
In our case, let’s create a handler object where we basically have the URL as the keys and the names of the functions that corresponds to those URLs as the value.
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
console.log('start of index.js'); //get the module server, which is the server.js we just wrote //put it into the variable server var server = require("./server"); //get the router module, which is router.js we just wrote //put it into the variable router var router = require("./router"); //then have server variable call its function start //using parameter router's router function var requestHandlers=require("./requestHandlers"); var handle = {} //create key "" and map it to a function in requestHandler.js handle["/"] = requestHandlers.start; handle["/start"] = requestHandlers.start; handle["/upload"] = requestHandlers.upload; console.log('index.js - server variable running function start with parameter router'); //server.start(router.route); server.start(router.route, handle); console.log('end of index.js'); |
The server’s start takes route function parameter and handle object parameter. The handle object was declared in index.js.
The route is a function variable that takes in the handle object, the response object, and pathname that’s in server.js.
It then processes the requests and outputs data using these objects.
Server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
console.log('start of server.js'); //requres the http module that ships with Node.js and return it to //global variable http var http = require("http"); var url = require("url"); //have start function...like bootstrap //start is called by global variable server in index.js function start(route, handle){ console.log('server.js - start function: '); //DEFINES a function called onRequest, to be used repeatedly //by global http's createServer function onRequest(request, response) { var pathname = url.parse(request.url).pathname; //let route give response to whoever wants to handle //the request route(handle, pathname, response); } http.createServer(onRequest).listen(8888); console.log("server.js - Server has started. end of start function"); } exports.start = start; console.log('end of server.js'); |
From index.js, we remember that handle[“/”] maps to a requestHandler.function1
handle[“/start”] maps to another requestHandler.function2…so on and so forth
Hence, in our case, the pathname represents the user’s path for their request…..and handle[pathname] is the name of the function we will call.
We first want to make a simple check to see if handle[pathname] is indeed in fact a function, if it is…then we call the function like so:
1 |
handle[pathname](response) |
where we throw in the response obj so that we can output to the browser whatever data we get.
router.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
console.log("start of router.js"); function route(handle, pathname, response) { console.log("router.js - about to route a request for " + pathname); if(typeof handle[pathname] === 'function') { console.log("router.js - we found a handle to process this pathname: " + pathname); //in index.js we had something like this: //handle["/upload"] = requestHandlers.upload; //we call that function and pass in the response obj handle[pathname](response); } else { console.log("router.js - no request handler found"); response.writeHead(404, { "Content-Type" : "text/plain"}); response.write("404 not found"); response.end(); } } exports.route = route; console.log("end of router.js"); |
requestHandler.js
Basically the function definitions that responds to the user’s request URLs.
We only provide 2: start and upload, which corresponds to
localhost:8888/start and localhost:8888/upload
1) We use dependency injection of the response object and have it output back to the browser the data we get.
2) We use child processes to make it non-blocking
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
console.log('requestHandlers.js start'); //so that we can use separate process var exec = require("child_process").exec; //response object passed through from onRequest in server.js function start(response){ console.log("requestHandlers.js - Request handler start was called"); //spawn a process and run unix cmd, once done //run finish block exec("find /", { timeout: 10000, maxBuffer: 20000 * 1024 }, function(error, stdout, stderr) { response.writeHead(200, {"Content-Type" : "text/plain"}); response.write(stdout); response.end(); }); } function upload(response) { console.log("requestHandlers.js - Request handler upload was called"); response.writeHead(200, {"Content-Type" : "text/plain"}); response.write("Hello upload"); response.end(); } exports.start = start; exports.upload = upload; console.log('requestHandlers.js end'); |