Server Programming II

Info 253: Web Architecture
Kay Ashaolu

What have we done

  • We have created a server that can accept HTTP requests, and send HTTP responses back
  • We have full control over what we send back as a response
  • We are using Python in order to fully control the back-end

More about routes

  • Routes connect URL paths to callback functions
  • You are essentially creating an "event listener"
    • On the event that a client goes to the "/" path
    • Execute the assigned callback function

Quick note

  • A server application is continuously running
  • It does this so that it always listens to requests
  • In order to exit a Python Flask web application you must kill the application
  • This is done in Unix by the keyboard combination
    Control + C

Route Example

webserver.py

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index_page():
  return "<html><head><title>Homepage</title></head>\
    <body><h1>This is the home page!</h1></body></html>"

@app.route('/about')
def about_page():
	return "<html><head><title>About</title></head>\
    <body><h1>This is the about us page!</h1></body></html>"

@app.route('/blog/post-1')
def blog_post():
	return "<html><head><title>Blog 1</title></head>\
    <body><h1>This is the first blog post</h1></body></html>"
					

What's happening

  • We have explicitly told our server to respond to three GET requests in a specific way
  • We return the raw text that we want our client (the browser) to receive
  • Note that we are sending pure html text to the client. The browser then creates a DOM from that text and displays the web page

What about our static files?

  • We need some mechanism for our static files to be sent to the client on request
  • Otherwise we would need to write our CSS in the app.js file itself

Flask and static files

  • Flask has a mechanism to set a directory to be treated as a static server
  • This is exactly how the server from last week operated, and how your local file system operates
  • When a user goes to a particular path, the file that is there is sent to the client as is
  • This is different with the routes that we have been using so far

Static example

webserver.py

from flask import Flask, render_template
app = Flask(__name__,static_url_path="/static")

@app.route('/')
def hello_world():

    return """
<html>
<head>
	<title>Homepage</title>
    <link rel='stylesheet' href='/static/style.css' />
</head>
<body>
	<h1>This is the home page!</h1>
    <script type='text/javascript' src='/static/script.js'></script>
</body>
</html>
"""
					

Static example

static/style.css

h1 {
	color: blue;
}
					

Static example

static/script.js

alert("script.js has been loaded!");
					

What's happening here?

  • We have set the path '/static' to run as a static server
  • Any path that starts with '/static' will serve files "as is" from the "static" folder
  • Check it out by going to http://localhost:5000/static/style.css

What's happening here?

  • Because of our static server, we can serve our own static files
  • Look at the HTML being sent from the '/' route
  • The HTML code includes a link to a style sheet and an include to a JavaScript file
  • This is why the heading was blue and the alert box appeared

This is great, but...

  • Writing out all of that text within a callback gets annoying quickly
  • What if you want to have HTML code common to several pages on your website?

Templates and template engines

  • There are a myriad of template engines out there
  • The idea is to write the HTML code that does not change in a "template"
  • And then designate placeholders for parts of the web page that does not stay the same
  • This is how dynamic pages are created (more on this next week)

Template Example

webserver.js

from flask import Flask, render_template
app = Flask(__name__,static_url_path="/static")

@app.route('/')
def hello_world():
  return render_template("index.html")
					

Template Example

templates/index.html

<html>
	<head>
		<title>Homepage</title>
    	<link rel='stylesheet' href='/static/style.css' />
    </head>
    <body>
    	<h1>This is the home page!</h1>
    	<p>With a template!</p>
    	<script type='text/javascript' src='/static/script.js'></script>
    </body>
</html>
					

What's happening?

  • This code does the same thing as the previous example
  • However, we loaded the html template "index.html" in the views folder
  • The templates folder is the default location of all templates
  • The render_template function takes the name of the template to load

But why use template engines at all?

  • We ran "index.html" through a template engine
  • But all we did is print the contents of "templates/index.html" to the screen
  • Couldn't we do this with static pages?
  • Why use a template rendering engine at all?

Dynamic Pages

  • We want to create pages that are different dependent on many different factors:
    • Authentication
    • Authorization
    • Data embedded in the URI
    • Data submitted in a form
    • Location
    • And so on
  • More on this next week, but here's a sneak peak

Grand Example

webserver.py (1/2)

from flask import Flask, request, render_template
app = Flask(__name__,static_url_path="/static")

quote_db = {
  'sunday': "Life is about making an impact, not making an income. \
  –Kevin Kruse",
  'monday': "Whatever the mind of man can conceive and believe, it can achieve. \
  –Napoleon Hill",
  'tuesday': "Strive not to be a success, but rather to be of value. \
  –Albert Einstein",
  'wednesday': "You miss 100% of the shots you don’t take. \
  –Wayne Gretzky",
  'thursday': "Every strike brings me closer to the next home run. \
  –Babe Ruth",
  'friday': "We become what we think about. \
  –Earl Nightingale",
  'saturday': "Life is what happens to you while you’re busy making other plans. \
  –John Lennon",
}
					

Grand Example

webserver.py (2/2)

@app.route('/')
def quote_of_the_day():
  day_of_week = request.args.get('day_of_week')
  return render_template(
    "index.html",
    day=day_of_week,
    quote=quote_db[day_of_week])
					

Grand Example

templates/index.html (1/2)

<html>
    <head>
        <title>Homepage</title>
        <link rel='stylesheet' href='/static/style.css' />
    </head>
    <body>
        <h1>This is the home page!</h1>

        <p>The quote for {{day}} is: {{quote}}</p>
        <br />

					

Grand Example

templates/index.html(2/2)

            <form action="/" method="GET">
            <label for="day_select">Select a day</label>
            <select name="day_of_week" id="day_select">
                <option value="sunday">Sunday</option>
                <option value="monday">Monday</option>
                <option value="tuesday">Tuesday</option>
                <option value="wednesday">Wednesday</option>
                <option value="thursday">Thursday</option>
                <option value="friday">Friday</option>
                <option value="saturday">Saturday</option>
            </select>
            <input type="submit" value="Give me a quote" />
        </form>
    </body>
</html>
					

What's happening

  • First we created a form that is going to send an GET request to the "/" route
  • It will pass a parameter called "day_of_week"
  • The server will gain access to that parameter using the requests.args.get function

What's happening

  • The server then accesses its "quote_db" to retrieve a quote for that particular day of the week
  • It then passes the day and the quote to the template engine
  • The template "index.html" replaces the tags {{day}} and {{quote}} with the values specified in the object passed by the function call render_template
  • And we see it on the screen

Questions?