Upload
emil-lloyd
View
215
Download
0
Embed Size (px)
Citation preview
Web Basics
Willem VisserRW334
Overview
• Basic Browser and Server Interaction– Forms with actions, url encoding and handlers– Parameters– Having more than one handler– GET versus POST
• Templates– Jinja2
• Validation and Escaping
<thanks>Udacity CS253 is the inspiration for a lot of this content</thanks>
Forms with actions
<form action = "/foo"> <input name="q"> <input type="submit"></form>
<form> <input name="q"> <input type="submit"></form>
<form action = ”http://www.google.com/search"> <input name="q"> <input type="submit"></form>
Server side• How do we react to the “action”?
import webapp2
class MainPage(webapp2.RequestHandler): def get(self): self.response.headers['Content-Type'] = 'text/plain' self.response.out.write('Hello, RW334 World!')
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
…handlers:- url: /.* script: main.app…
Main.py
app.yam
l
Server Handler (1)• Lets first add the form to our web page
import webapp2
form = """ <form action = "/foo"> <input name="q"> <input type="submit"></form> """
class MainPage(webapp2.RequestHandler): def get(self): self.response.headers['Content-Type'] = 'text/plain' self.response.out.write(form)
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
Will this render the form?
Server Handler (2)• Default content type is HTML
import webapp2
form = """ <form action = "/foo"> <input name="q"> <input type="submit"></form> """
class MainPage(webapp2.RequestHandler): def get(self): #self.response.headers['Content-Type'] = 'text/plain' self.response.out.write(form)
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
Will this correctly submit?
Server Handler (3)• Add the FooPage handler whenever the “/foo”
url is accessed on our server• Can get the “q” parameter from the GET request
…class FooPage(webapp2.RequestHandler): def get(self): q = self.request.get("q") self.response.out.write("Thanks for %s" % q)
app = webapp2.WSGIApplication([('/', MainPage), ('/foo', FooPage)], debug=True)
Server Handler (4)
class FooPage(webapp2.RequestHandler): def get(self): self.response.headers['Content-Type'] = 'text/plain' self.response.out.write(self.request)
app = webapp2.WSGIApplication([('/', MainPage), ('/foo', FooPage)], debug=True)
GET /foo?q=blah HTTP/1.1Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.8,af;q=0.6Host: localhost:8080Referer: http://localhost:8080/User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36X-Appengine-Country: ZZ
GET versus POST…form = """ <form method = “post” action = "/foo"> <input name="q"> <input type="submit"></form> """
class MainPage(webapp2.RequestHandler): def get(self): self.response.out.write(form)
class FooPage(webapp2.RequestHandler): def get(self): q = self.request.get("q") self.response.out.write("Thanks for %s" % q)
app = webapp2.WSGIApplication([('/', MainPage), ('/foo', FooPage)], debug=True)
Will this correctly submit?
GET versus POST (2)…form = """ <form method = “post” action = "/foo"> <input name="q"> <input type="submit"></form> """
class MainPage(webapp2.RequestHandler): def get(self): self.response.out.write(form)
class FooPage(webapp2.RequestHandler): def post(self): q = self.request.get("q") self.response.out.write("Thanks for %s" % q)
app = webapp2.WSGIApplication([('/', MainPage), ('/foo', FooPage)], debug=True)
Where did the parameter go in url?
• Parameter now part of the body of request
GET versus POST (3)
POST /foo HTTP/1.1Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.8,af;q=0.6Content-Length: 6Content-Type: application/x-www-form-urlencodedContent_Length: 6Content_Type: application/x-www-form-urlencodedHost: localhost:8080Origin: http://localhost:8080Referer: http://localhost:8080/User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36X-Appengine-Country: ZZ
q=blah
GET versus POST (4)• GET
– Parameters in URL• Length restrictions
– Used for fetching documents– OK to cache
• Same request in succession should produce the same
– Should not change the server
• POST– Parameters in body– Used for updating (server)– No caching
Templates
• Greatly simplify developing dynamic websites• Pass data variables to the page• Embed programming constructs in the page• Lots of options, we will use jinja2
First create your Template<!DOCTYPE html><html> <head> <title>I'm using Templates!</title> </head> <body> I'm {{name}}, and I {{verb}} RW334! </body></html>
…libraries:- name: jinja2 version: latest…ap
p.yam
lbase.htm
l
Handlerimport osimport webapp2import jinja2
jinja_environment = jinja2.Environment(autoescape=True, loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
class MainPage(webapp2.RequestHandler): def get(self): template_values = { 'name': 'Willem', 'verb': 'love' }
template = jinja_environment.get_template('base.html') self.response.out.write(template.render(template_values))
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
Loops!<!DOCTYPE html><html> <head> <title>I'm using Templates!</title> </head> <body> I'm {{name}}, and I {{verb}} RW334! Here are a few of my favourite things about the course: <ul> {% for item in favourites %} <li>{{ item }}</li> {% endfor %} </ul> </body></html>
Handler…class MainPage(webapp2.RequestHandler): def get(self): template_values = { 'name': 'Willem', 'verb': 'love', 'favourites' : favourites }
template = jinja_environment.get_template('base.html') self.response.out.write(template.render(template_values))
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
Validation
• When you receive input it is important to validate it
• Can happen on the client and the server• We will look at it on the server side here
Birthday<!DOCTYPE html><html> <head> <title>Validation</title> </head> <body> <form method = "post"> What is your birthday? <br> <label> Month <input type = "text" name = "month" value="{{month}}”> </label> <label> Day <input type = "text" name = "day" value="{{day}}”> </label> <label> Year <input type = "text" name = "year" value = "{{year}}”> </label> <div style="color: red"> {{error}} </div> <br><br> <input type = "submit"> </form> </body></html>
Handler with Validationclass MainPage(webapp2.RequestHandler): def displayform(self, error = "", month = "", day = "", year = ""): values = dict([('error', error), ('month', month), ('day', day), ('year', year)]) template = jinja_environment.get_template('validation.html') self.response.out.write(template.render(values)) def get(self): self.displayform() def post(self): user_month = self.request.get("month") user_day = self.request.get("day") user_year = self.request.get("year") month = valid_month(user_month) day = valid_day(user_day) year = valid_year(user_year) if not(month and day and year): self.displayform("Not a valid date", user_month, user_day, user_year) else: self.response.out.write("Thanks for the valid birthday")
Escaping• What happens if we add this in a field
– yaya”>oops!
• We need to make sure HTML characters display as intended not mess with the “real” HTML
• This is done by Escaping the HTML– Convert it to something harmless
• Common cases– “ becomes " and & becomes &– > becomes > and < becomes <
Escaping Example
• If we want to display this line in the browser– How do we display <html> in HTML?
• By typing– How do we display <html> in HTML?
First Rule of Escaping
NEVER ROLL YOUR OWN!
Escape Libsimport cgidef escape_html(s): return cgi.escape(s,quote = True)
class MainPage(webapp2.RequestHandler): def displayform(self, error = "", month = "", day = "", year = ""): values = dict([('error', error),
('month', escape_html(month)), ('day', escape_html(day)), ('year', escape_html(year))])
template = jinja_environment.get_template('validation.html') self.response.out.write(template.render(values))
jinja_environment = jinja2.Environment(autoescape=True, loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
OR