Check out a free preview of the full Digging Into Node.js course:
The "Creating a Web Server" Lesson is part of the full, Digging Into Node.js course featured in this preview video. Here's what you'd learn in this lesson:

Kyle demonstrates how to create a web server, writes a function to handle requests to the server, and then writes code that handles whether to display a message on the page or return a default 404 page. - http://static.frontendmasters.com/resources/2019-05-09-digging-into-node/digging-into-node.zip

Get Unlimited Access Now

Transcript from the "Creating a Web Server" Lesson

[00:00:00]
>> Kyle Simpson: All right, let's go ahead and turn our attention now to exercise five. Again there's a new file provided for you, ex5.js, so go ahead and open that one up. And you'll see that we've got a few different things going on, we are still gonna work with sqlite.

[00:00:15] But now we're gonna working with http, so we're gonna be building our first web server. And our web server is going to have an API endpoint that serves up the records from our database to a web page. That's what we're gonna to be building here in exercise five.

[00:00:36] First things first, we need to pull in the http Module that handles all of the gory details of doing http response and request and response handling in our web server. And then we're also going to use this package that I've downloaded for you called node static alias. That's a wrapper around a more commonly known package called nodes static, which is one of the more common of the static file servers.

[00:01:05] Specifically, that one handles all of the mime type handling and content link calculation, all that other junk that we don't wanna do, whenever we serve up JavaScript and CSS and images and all those other kind of files. Static file servers are what do that for us, and node static is probably one of the most well known of those, node-static-alias has a wrapper around it that gives us a little bit more declarative alias URL routing.

[00:01:33] So we're gonna use "node-static-alias" for them, but we'll come back to the node-static-alias in a moment. Let's instantiate our server, so line 45 is how we make a new server, we use the http module and we say create server, and then handle request. And we haven't defined the handle request function yet, but we're going to in just a moment.

[00:02:02] Before we do that I've just wanna point out that I have set up a variable called HTTP Port with port 8039. That's the one we are gonna use for the purposes of this discussion. If you wanna change that port to different port cuz you don't like the number 8039 that's fine.

[00:02:16] Just make sure in all the rest of our exercises you keep updating that, cuz we'll be assuming 8039. Okay, so we need to actually listen on that port, and the way we do that is to call httpserv, that's the server instance that we just created, call httpserv.listen and we're gonna use (HTTP_PORT).

[00:02:45] And for good measure we'll just go ahead and uncomment that console.log statement.
>> Kyle Simpson: Now we need to define that handle request function that we've referenced above. So function handleRequest takes a req and a res, that is the request stream and the response stream. Remember, we talked about streams earlier in the course.

[00:03:14] These are streams, they're specifically HTTP streams, but they are streams. They have all the same read and write semantics that we've talked about, so you theoretical could be piping a request stream into a response stream or things like that, okay? I'm gonna go ahead and make this an async function, because we eventually are gonna be doing some asynchronous operations as we, handle our incoming request.

[00:03:40] But for now, we wanna just kinda do the hello world of HTTP server, which is that on each incoming request, we just wanna respond on the response stream with some text, okay? So basic way for us to do that is we're gonna call res, which is our response string.

[00:04:00] It has a method on it since it's an HTTP string that has a special method called writeHead which is gonna write out all the headers for our HTTP response. We're gonna give it 200 because this is gonna be a success. And for now let's just send a Content-Type of text/plain.

[00:04:26]
>> Kyle Simpson: And then we need to write some content to this stream, so I'm just gonna say Hello world. And then we have to make sure to end this stream so that everything is flushed so we call res.end. But for our purposes, since we're only sending one string, you can actually pass that string to res.end.

[00:04:49] So we really just need these two lines, res.end, okay, so I'm gonna switch back over to our command line. I'm gonna run node ex5.js and you'll notice that instead of running and finishing, now it's just sitting there waiting. It's because it's going to run essentially forever until we stop it, the way you stop it is with the Ctrl+C, so if I say Ctrl+C it stops it.

[00:05:16] We're going to run our server, and then I'm going to switch over to a browser. Let's come here, and let's say http local host for at 8039 and there you see our Hello world.
>> Kyle Simpson: And if we look at the local host, specifically in our Network tab over here, you'll notice that the headers, when we look at the headers they came back, the Response Headers included are text plain content type

[00:06:02]
>> Kyle Simpson: In fact we could send any custom headers that we wanted to if we really felt like
>> Kyle Simpson: Okay, writing out text like that is not particularly interesting. We're probably immediately gonna think, well how do I send out like whole websites. If I can serve up some text, I'm gonna probably wanna start searching serving up a website.

[00:06:29] So before we, actually before we get there, I just want to point out one little thing. All of the big, major frameworks that are out there, like Express.js, and Sales, and all those others that are node frameworks, and node router frameworks, there are dozens and dozens of them out there.

[00:06:48] Really they boil down to a series of if statements, they have very fancy APIs, lots of complexity, lots of sophistication. But what they really boil down to in all their routing goodness and magic, they really boil down to a set of if statements. So if we wanted to do our own custom routing, and I literally do this in my production sites, because why put extra abstraction when it's unnecessary?

[00:07:12] We can literally just do an if statement like if req.url equals hello, then we're gonna respond with hello world, and otherwise, we're gonna say res.writehead(404), and res.end. So we're gonna send a 404 and if you don't go to /hello. So I'm gonna save my server, I'm gonna start stop and restart it, I'm gonna refresh the browser, and now we got a 404.

[00:07:53] Couldn't be found but if we then add /hello, now suddenly we have our page back.
>> Kyle Simpson: So it really doesn't get any more complicated than a series of matching decisions that you could model with a series of if statements. You might match on whether or not the request method was a get or a post or whether there's a certain header.

[00:08:20] Or whether there's certain cookies involved or the URL matches some particular regular expression. All of the fanciness of those frameworks boils down to, can I do some matching and decide where to dispatch this stuff? And I've written whole production websites on node, using nothing other than just a series of if statements or switch statements exactly like that.

[00:08:43]
>> Student: Is the browser just throwing that hello world into the body tag?
>> Kyle Simpson: Yes, it is, because we sent, actually not even a body tag, since we sent that text plain, it's not interpreting it as HTML at all. If we sent that text HTML, then it would be assuming that we have a body to put that stuff in.

[00:09:01] But this is literally just plain text response.