~abyxcos/python_tutorial

8732dba07af4d2880f07d40fbf15dbc4fd054352 — abyxcos 4 years ago e3e1c4b
A simple GET request handler.
2 files changed, 49 insertions(+), 2 deletions(-)

M README.md
M journal.py
M README.md => README.md +39 -1
@@ 38,8 38,46 @@ git add journal.py
git commit -m "This is a basic web request handler, but nothing else yet."
```

If you have an account (or wish to create an account) on a code sharing site, such as [GitLab](https://gitlab.com/) or [GitHub](https://github.com/) you may want to choose now to also upload your project there to show off your progress or to be able to work continue work from multiple computers. Click the `New Project` button on the site and name your project something descriptive like `Web_Journal` or `Python_Journal`. I named my project `python_tutorial`, choosing underbars (`_`) instead of spaces as spaces usually cause problems with computers. The following two git commands link up your code sharing account with your project and then upload (push) your files to the website. 

```
git remote add origin git@gitlab.com:abyxcos/python_tutorial.git
git push -u origin master
```

If git has already been set up on your computer, this should just work. If you have not set up git yet, then git will likely print out some instructions on how to finish the setup. This usually includes steps like setting your email and often uploading a secret passkey to the website (more secure than a standard password). 

## Talking to the browser

Now that we have our program talking to the internet, let's take the next step and set up the full pipeline so that rather than stopping when your computer makes an internet connection, the program will proceed to continue the conversation and send a message to the browser. 
Now that we have our program talking to the internet, let's take the next step and set up the full pipeline so that rather than stopping when your computer makes an internet connection, the program will proceed to continue the conversation and send a message to the browser. This is accomplished simply by popping out that placeholder `BaseHttpRequestHandler` and crafting our own class to handle requests how we want them. If you haven't bumped into classes yet, classes are just a way of grouping a bunch of generic functions into a package that anyone can easily extend. Classes differ from libraries in that while both group up a set of functions, libraries give you code in a take it or leave it method. Classes however give you a template of functions that you can pick, replace, or extend  as you need. In Python a lot of core libraries (including `http.server`) actually provide classes rather than raw functions allowing us this freedom. `BaseHTTPRequestHandler` actually provides a lot of code we want to take advantage of already, but it's missing one particular function that were are very interested in; the `do_GET` function that gets called any time a browser opens a connection to our server and wants to get a page. Right now the browser is just stopping at opening the connection because we don't have that function to give it a page created yet. So let's make a `JournalRequstHandler` class to handle people requesting pages off our journal, link it up to the `BaseHttpRequestHandler`, and then make a simple `do_GET` function to do something useful when someone tries to get our page. 

```
import http.server

class JournalRequestHandler(http.server.BaseHTTPRequestHandler):
   def do_GET(self):
      # Standard template nonsense
      self.send_response(200) # All ok
      self.end_headers()

      # Our message starts here
      self.wfile.write('Welcome to my web journal!'.encode())

httpd = http.server.HTTPServer(
   ('127.0.0.1', 8000),
   JournalRequestHandler
)
httpd.serve_forever()
```

As you can see, our core program is still the same, we've just added our new request handler class and the single function to chat with the browser, of which two lines are comments (lines starting with a `#` are just notes and not code), two lines are standard code that every function talking to a browser needs (the header on any message we send), and one weird looking line to actually send our message. To break down that line, `self` is the state/context of the request the browser sent that gets passed in to our function for free. We could use this data to do some fancier checking like seeing what files or folders the user is trying to get at, but for now we'll stay simple and reply with the same message to everyone. The `wfile` is not a misspelling, it's a file writer method that lets us pack all our data in to the request as though we were just writing data to a file. This might look a little funny right here, but Python has a lot of tools for working with files so by pretending our message is a file, we get access to all of those tools for free. The last part is much simpler. Just a normal `write` that writes any message (or data) we pass it in to the file we name (`self.wfile`, our request message). If you have looked at any other programming guides or tutorials before, they almost always start out by showing you how to print a simple "Hello World!" message to the screen. This is our version of the "Hello World!" message. Almost all computer chatter on the internet is actually no fancier than printing messages back and forth. And what we are doing here is no more complicated than printing a message out to the internet with the `write` function. That `encode` we sneak in at the end of the `write` is just our way of telling Python to take our message full of characters (a string) and convert (encode) it into a bunch of bytes so we can save it to a file (in this case our pretend file, `wfile`). 

As we now have another working feature, I make it a habit to always create a checkpoint in git, no matter how simple the feature. Using `git commit` with the `-a` flag tells git to automatically add any changed files it already knows about (is tracking) to the commit group for the checkpoint. If you want to manually check on what changed, the status command is great to see what git thinks is going on so you can correct it.

```
git status
git commit -a -m "A simple GET request handler."
git push
git status
```


M journal.py => journal.py +10 -1
@@ 1,7 1,16 @@
import http.server

class JournalRequestHandler(http.server.BaseHTTPRequestHandler):
	def do_GET(self):
		# Standard template nonsense
		self.send_response(200)	# All ok
		self.end_headers()

		# Our message starts here
		self.wfile.write('Welcome to my web journal!'.encode())

httpd = http.server.HTTPServer(
	('127.0.0.1', 8000),
	http.server.BaseHTTPRequestHandler
	JournalRequestHandler
)
httpd.serve_forever()