So we built a browser in Python. It's time to build a web server in Python. So remember that what we've got here is we've got the browser is an application, and we've made this a Python application now, that sends this GET request. So we have effectively, like I said, built the world's simplest browser and that sends a GET request. The server does something and then it sends the response back. And now, we're going to kind of change this, right? We're going to assume the browser exists and it's like okay, because we're going to be the server folks, right? So now we're going to look in greater detail at what goes on in the server. And so here is a very, very simple web server. It's a few more lines than the simplest web browser because we have to put a little bit of error checking in with some tries and excepts, okay? So let's walk through what this code does, okay? Let me change the color again to black. If you're from Microsoft and you can tell them to make a key to change the color on the scribbler, I'd greatly appreciate it. Oh, and then I went down a page too. Okay, so we're going to pull in some more stuff from the socket. We're going to pull in some stuff from the socket right here. So we're going to make a function called createServer that we're going to call right down here, and it's going to print out how you're suppose to access it and then start the server. Now the whole idea of the server is that the server is woke up to wait for incoming connections. So the server already exists. So when you start talking to a web server, that server is in that computer already. The server software is already running, registering its interest in incoming requests. So that's what we do. So when this Python program starts, it's going to sit there and wait in an infinite loop for incoming requests. So the first thing we do is we're going to make a socket. This looks very much like the time we made. It's an endpoint. It's not actually making the phone call. Remember, I said this socket call is making the phone. So we're saying, we're going to make a phone and it's up to us later to decide if we're going to make a phone call or receive phone calls. And then this next thing is like the connect, except this is, "I am willing on port 90 to receive the phone calls." Now it turns out there's only one program on port 90 that can receive phone calls. So this might blow up. You might try to do this, I mean port 9000, and if you run this twice, and you can do it in two windows on your computer, the second one will blow up and say, you can't have port 9000 because another piece of software has it. But as long as there's only one running, away you go. And that's part of this whole try/except thing, because if you run this twice, it's going to blow up the second time because you cannot receive phone calls on this server on port 9000 with two applications. One application gets the phone calls. That's what socket listen says. The 5 on there says, "Dear operating system, if I'm busy handling one phone call, you can hold on to four more and queue them and then I'll come back and get them for you." That you're asking the operating system to queue incoming calls. Don't just say you're busy, shut down. If you didn't say this listen(5), if you're busy writing the data for phone call 1 and phone call 2 came in and you weren't ready for it right that instant, it would just deny the phone call. So that's what listen says is, "Dear operating system hold those temporarily. I'll get back to you." Which is how it works. And then what happens is we go into this accept. Now this accept is, "I'm at the phone, I've registered what my number is and what my extension is, and I'm ready to pick the phone up. Let me know." So this accept is blocking. It stops and it just sits there. And it can sit there forever, just literally forever. And if nobody calls it, nothing happens. The next line never runs until you blow it up or the server goes down. So that accept is a blocking. And the reason we do this accept, well, we have to establish the phone call first, right? So then this next line runs only when a phone call is received. So that means that we on the browser side, we already connected. We made the phone call. Now we haven't sent any data yet, right? Now at this point, somewhere out there there's a piece of client software that has done a socket.connect, and we have done accept and our accept has succeeded in the server, the connect has succeeded, and we are ready to talk. So the phone call has been made. Now the question is, who is going to say hello? And this is where the HTTP protocol solves our problem. The server knows that the client must speak first, so it just does a receive. Now you'll notice the receive and the send are the same function calls because it's a two-way thing. Whatever the browser is sending, the server is receiving, and whatever the server sends, the browser receives, and they can do it simultaneously if they can figure it out. But usually you kind of like say, it's your turn to listen and my turn to send and then I'll listen, and usually they kind of go back and forth. In this, there is only one step. The server listens, gets the GET request, sends the data back. So then we're going to read some data and we're going to get 5,000 characters. We going to get the whole thing. Remember it's one line, it has a GET request in it, and it has the optional parameters in it. And so we're going to split it. Now again, we've received it as UTF-8. We've got to decode it for Unicode inside of Python, and then we split it based on newlines because the GET request is on one line, then header, header, header, header, header, and then the blank line to tell us that we're ended the headers. In this, we're just going to look at that first line. We're not going to do anything with it. Most servers actually like look at the line to figure out what document to send. This a very simple server, it sends the same document no matter what the URL is. All we do with the URL is we print it out to prove that we got it, and then we construct a response. And in this response, again, go back to RFC 2616, and it will tell you what this response is supposed to look like. It sends back a 200 OK. Remember, this is all the stuff we saw. Probably I cut and pasted it from a working thing. We tell it that we're sending it back in content type text/html, the character set UTF-8, remember I was telling you that, a blank line, and then some HTML. HTML body, Hello World body. And I'm throwing in these \r\n's, which is the network's version of newlines. And then you will notice that I encode it before I send it, because it's Unicode inside of Python, and it needs to be sent as UTF-8. Because when you're in a socket, that thing that's going across the socket almost always is supposed to be UTF-8. So we encode it. And then, because the protocol says so, as soon as we send the data, we close the connection. And remember that the client had to close the connection too. So we close it, it's half closed, and then the client gets all of its data, gets the indication that it closed, knows it's finished all the data, and then the client shuts its side down. And so there are two hang-ups. It's kind of like a phone call. The person hangs up, and then click, you hang up. Now you can't really keep talking, but you do want to have both sides hang up and that shutdown is what's going on. And then the rest of this is all try/except for various things so we clean up our socket, so we don't have to restart our server when our software blows up, and so the rest of it is pretty simple. So this while(1), the first browser will talk and then it'll send some data and it'll go back and wait for the next phone call, and that's what's going on. The next phone call comes in, it receives a GET request. It sends the data back, then waits for another phone call. So this is an infinite loop that sits and waits for incoming phone calls and it answers the same thing. So it's like you call this phone number and it goes and you go, "I would like a pizza," and it says, "Hello World," and then click. And then you call it up and say, "I would like a car." And it says "Hello World." Click. And then you say, "I would like to register for this class." And it says, "Hello World." Click. So this is not a very flexible server, you will build far more flexible servers, but it's the one that I could build and fit on a single page in a slide deck. So to run this, if you download this code, and it's a tiny bit of code, and you run it, so you go somewhere, maybe your laptop, maybe PythonAnywhere, I don't know if it works on Python, it probably doesn't work on PythonAnywhere because you can't actually talk to ports. But let's just run this on your laptop and you start the server up, somewhere get ahold of my sample code or download from here, server.py, and it's telling you this is just output from the server. And this is the moment at which it's waiting, right? It's waiting. The server could wait for hours at this point. But I just give you this in a print statement so you can copy that and put it into your browser, so you paste localhost:9000 into your browser, and then the server is printing that it got a GET request for the slash document from this browser. That's what the browser sent. I mean, we're talking from Firefox browser to the little web server that we just built. Now there's another a second GET request that you don't even know because you didn't ask for it, and that's because the browser is built in to ask for a URL called favicon.ico so that it can make an icon, and that icon ends up in the tab or wherever in your browser and so that's like an icon for the website. So you didn't ask the browser to do this, but it's a thing browsers do. And you'll see when you're looking at your debug logs when you're building stuff that it's a favicon. And so this happens like blink blink and now it's waiting again, right? And you can hit refresh or you can go start a different browser, and you would see the GET requests. Every GET request you're going to see in your browser and your server. So it's working, and it works really well and you're welcome to go ahead and play with it and try it all out. So now what we're going to do is build a simple web client and it'll talk to our server. So the other web client we made talked to data.pr4e.org. This one is going to talk to yourself. So it's this. It almost looks identical, right? We're making a phone. We're going to connect to localhost. 127.0.0.1 is the IPv4 connection, what's called loopback, right to the same host. We're talking to port 9000 because that's where we've got our web server running, that little web server we just wrote. And then we're going to send a GET request, a valid GET request, to this thing HTTP/1.0, and then two newlines and we're going to encode it into UTF-8 before we send it. Then we send it, and then we just have a loop that prints it all out, and then when the socket gets closed, we hit a break and then we close our end of the socket. So the server clicks the phone and then we know we're done with our data but we've already printed it out, and then we hang up the phone on our end to kind of clean everything up all the way in between everything else. So this is a very simple web client. And so now you can run the web server, right, just like we did before, and instead of talking in a browser, we run this client. And this client gets a header of HTTP 1 OK, its content type HTML, it gets a newline, and then the body, and we're done. Now, I mean, it's not a browser, but it is client that's talking HTTP, and so now you'll notice that this server sort of sits and waits for incoming calls. You could run this over and over on the client, run the client over and over again, right? And then you would see more requests, but in general the server is destined to just sit and wait for hours potentially until a client connects to it. Then at some point you'll just abort this server, and then if you Control C or blow this up somehow, this will fail. The client will fail, and it will fail in this connect code. So if you want to play with it, try to run this client without running the server, and you'll see that the connect, which is the part of actually making the phone call. This will continue to work, which is make me a phone on my current computer. And then connect is make a call to the remote computer, that will blow up. And then if you wanted to play with this you could put some try and excepts around it, say remote computer is not responding on port 9000, that's if you blew up you could put a try and except around that. But I'm not doing it because it don't fit on my slides. So here is an even simpler web client that we can use, and again you can get this code from my sample code. We don't talk this week there's a higher-level thing. So the previous client talked to sockets, so I could show you the low level. But because we spend so much time talking to URLs, we then have a urllib. So I'm just going to use urllib, and this could be a localhost or it could be whatever. I'm just going to make a four-line urllib call. And so I just do a urlopen of that same URL. Now we're operating at the HTTP level because the concept of URL is not a socket concept, the concept of URL is a HTTP concept. Then we just get in effect what looks like a file handle to us and we loop through it and print it all out. So we run our server, and the server sort of says this and waits. And then we run our client. It basically hits our server and we can see in the server window, you've got to do these two things in two windows, right? You've got to do these things in two separate windows. So in the server window it'll sit and wait, and then in the client window, when it runs you'll see the client will make the request to the server or blow up if the server's not running. And the server will see the GET request and then the data will come back to the client. So you sort of do this in two things and you can run the client over and over and over again, and you'll see every time you run the client, the server sees it, responds, and away you go. And again, our server always says, "Hello World" no matter what, which is delightful and classic. It's a classic. So you actually can watch when you're running Django, there will be a way for you to see when you're running Django locally and you start the server up. We'll do this later, manage .py runserver and then you talk to it, and you will see all the GET requests. And so Django when you run it locally you can debug a lot of what's going on. You can see like the favicon that it's asking for, and that is five or six HTTP requests to produce that little Django web page. And so that will be something that you will learn how to do. And so that sums up what we're doing in this. At the beginning you look at it very simply. Pretty soon you'll just be looking at the developer console and it will all make sense to you. I want you to be able to know that you can dig as deep as you want to and understand all of these protocols that are going back and forth, okay? Cheers. [MUSIC]