Upload
stephen-farmer
View
229
Download
5
Embed Size (px)
Citation preview
1
web.py
httpweb.py
2
Agenda
Introduction to http URL, URI Method: GET, POST Response Code: 200, 400, 401
Introduction to web.py
3
HTTP
HyperText Transport ProtocolLanguage of the Webprotocol used for communication between web browsers and web servers
TCP port 80 (443 secure)RFC 2616 (ver 1.1)
4
Frames
5
URI,URN,URL
Uniform Resource IdentifierInformation about a resource
Uniform Resource NameThe name of the resource with in a namespace
Uniform Resource LocatorHow to find the resource, a URI that says how to find the resource
6
HTTP - methods
Methods (cont.)PUT
• Used to transfer data from the client to the server
HEAD• requests URLs status header only• used for conditional URL handling for
performance enhancement schemes– retrieve URL only if not in local cache or date is more
recent than cached copy
7
HTTP - URLs
URLUniform Resource Locator
• protocol (http, ftp, news)• host name (name.domain name)• port (usually 80 but many on 8080)• directory path to the resource• resource name
http://xxx.myplace.com/www/index.htmlhttp://xxx.myplace.com:80/cgi-bin/t.exe
8
HTTP - methods
MethodsGET
• retrieve a URL from the server– simple page request
– run a program
– run a program with arguments attached to the URL
POST• preferred method for forms processing• run a program• parameterized data• more secure and private
9
HTTP Request Packets
Sent from client to serverConsists of HTTP headerheader is hidden in browser environmentcontains:
• content type / mime type• content length• user agent - browser issuing request• content types user agent can handle
and a URL
10
HTTP Request Headers
Precede HTTP Method requestsheaders are terminated by a blank lineHeader Fields:FromAcceptAccept-EncodingAccept Language
11
HTTP Request Headers (cont.)
RefererAuthorizationCharge-ToIf-Modified-SincePragma
12
Accept:
List of schemes which will be accepted by client<field> = Accept: <entry> * [,<entry>]<entry> = <content type> *[;<param>]<param> = <attr> = <float><attr> = q / mxs / mxb
<float> = <ANSI-C floating point > Accept: text/htmlAccept: audio/basic q-1if no Accept is found; plain/text is assumedmay contain wildcards (*)
13
Accept-Encoding
Like Accept but list is a list of acceptable encoding schemesExAccept-Encoding: x-compress;x-zip
14
User-Agent
Software product used by original client<field> = User-Agent: <product><product> = <word> [/<version>]<version> = <word>Ex.User-Agent: IBM WebExplorer DLL /v960311
15
Referer
For Server’s benefit, client lists URL od document (or document type) from which the URL in request was obtained.Allows server to generate back-links, logging, tracing of bad links…Ex.Referer: http:/www.w3.com/xxx.html
16
Authorization:
For Password and authentication schemesEx.Authorization: user fred:mypasswordAuthorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
17
ChargeTo:
Accounting informationAccounting system dependent
18
Pragma:
Same format as acceptfor serversshould be passed through proxies, but used by proxyonly pragma currently defined is no-cache; proxy should get document from owning server rather than cache
19
Modified-Since:
Used with GET to make a conditional GETif requested document has not been modified since specified date a Modified 304 header is sent back to client instead of documentclient can then display cached version
Response Packets
Sent by server to client browser in response to a Request Packet
Status Header
“HTTP/1.0 sp code”Codes:1xx - reserved for future use2xx - successful, understood and accepted3xx - further action needed to complete4xx - bad syntax in client request5xx - server can’t fulfill good request
HTTP Response Headers
Sent by server to client browserStatus HeaderEntities
• Content-Encoding:• Content-Length:• Content-Type:• Expires:• Last-Modified:• extension-header
Body – content (e.g., html)
Status Codes
200 OK201 created202 accepted204 no content301 moved perm.302 moved temp304 not modified400 bad request
401 unauthorized403 forbidden404 not found500 int. server error501 not impl.502 bad gateway503 svc not avail
Statelessness
Because of the Connect, Request, Response, Disconnect nature of HTTP it is said to be a stateless protocoli.e. from one web page to the next there is nothing in the protocol that allows a web program to maintain program “state” (like a desktop program).“state” can be maintained by “witchery” or “trickery” if it is needed
Maintaining program “state”
Hidden variables (<input type=hidden>Sessions Special header tags interpreted by the server
• Used by ASP, PHP, JSP– Implemented at the language api level
26
Agenda
Introduction to http Introduction to web.py
mvc model controller view
CRUD
27
web.py
MVC Controller:
URI handler accept http request process http request using model generate http response using view return http response
28
web.py
MVC Model
manage python and database objects
View http response
29
web.py
Todo Demo/schema.sql/templates: /templates/base.html /templates/index.html/model.py/todo.py
30
web.py
Todo Demo/schema.sql (Backend)/templates: (VIEW) /templates/base.html (static) /templates/index.html (dynamic)/model.py (MODEL)/todo.py (CONTROLLER)
31
database
schema.sqlCREATE TABLE todo ( id INT AUTO_INCREMENT, title TEXT, primary key (id));
32
database
model.pyimport web
db = web.database(dbn='mysql', db='test', user='')
33
Modelmodel.py
import web
db = web.database(dbn='mysql', db='test', user='')
def get_todos():
return db.select('todo', order='id')
def new_todo(text):
db.insert('todo', title=text)
def del_todo(id):
db.delete('todo', where="id=$id", vars=locals())
34
View
templates/base.html$def with (page)
<html>
<head>
<title>Todo list</title>
</head>
<body>
$:page
</body>
</html>
35
View
templates/index.html$def with (todos, form)
<table> $for todo in todos:
<tr>
<td>$todo.id</td>
<td>$todo.title</td>
<td>
<form action="/del/$todo.id" method="post">
<input type="submit" value="Delete"/>
</form>
</td>
</tr>
</table>
36
View
templates/index.html$def with (todos, form)
<table>
…
</table>
<form action="" method="post">
$:form.render()
</form>
37
Controller: url mapping
todo.pyimport web
import model
urls = (
'/', 'Index',
'/(\d+)', 'Index',
'/del/(\d+)', 'Delete'
)
38
Controller: handling GET /
todo.py### Templates
render = web.template.render('templates', base='base')
class Index:
form = web.form.Form(
web.form.Textbox('title', web.form.notnull,
description="I need to:"),
web.form.Button('Add todo'),
)
def GET(self):
""" Show page """
todos = model.get_todos()
form = self.form()
return render.index(todos, form)
39
Controller: handling POST /
todo.pyclass Index:
def POST(self):
""" Add new entry """
form = self.form()
if not form.validates():
todos = model.get_todos()
return render.index(todos, form)
model.new_todo(form.d.title)
raise web.seeother('/')
40
Controller: handling POST /del
todo.pyclass Delete:
def POST(self, id):
""" Delete based on ID """
id = int(id)
model.del_todo(id)
raise web.seeother('/')
41
MVC: GET / flow
ClientGET http://localhost:8080/
ServerIndex::GET (controller, todo.py)
• model.get_todos (model.py)• render http response (view)
– templates/base.html
– templates/index.html
• return http response
42
MVC: GET / flowcurl -v -X GET http://localhost:8080/
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
> Host: localhost:8080
> Accept: */*
>
43
MVC: GET / flowcurl -v -X GET http://localhost:8080/
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Date: Fri, 13 Feb 2015 05:30:34 GMT
< Server: localhost
<html>
<head>
<title>Todo list</title>
</head>
<body> ...
44
MVC: POST / flow
ClientPOST http://localhost:8080/
ServerIndex::POST (controller, todo.py)
• validate input• if input invalid, render http
response (view)– templates/base.html
– templates/index.html
• return http response
45
MVC: POST / flow
ClientPOST http://localhost:8080/
ServerIndex::POST (controller, todo.py)
• validate input• if input valid
– model.new_todo (model.py)
• seeother /
46
MVC: POST / flowcurl -v -d 'title=cleaningxx' -X POST localhost:8080
Connected to localhost (127.0.0.1) port 8080 (#0)
> POST / HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
> Host: localhost:8080
> Accept: */*
> Content-Length: 16
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 16 out of 16 bytes
47
MVC: POST / flowcurl -v -d 'title=cleaningxx' -X POST localhost:8080
< HTTP/1.1 303 See Other
< Content-Type: text/html
< Location: http://localhost:8080/
< Transfer-Encoding: chunked
< Date: Fri, 13 Feb 2015 01:41:35 GMT
< Server: localhost
<
* Connection #0 to host localhost left intact
* Closing connection #0
48
MVC: POST /del
ClientPOST http://localhost:8080/del/1
ServerDelete::POST (controller, todo.py)
• model.delete_todo (model.py)• seeother /
49
MVC: POST /del flow
$ curl -v -X POST localhost:8080/del/1
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /del/1 HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
> Host: localhost:8080
> Accept: */*
>
50
MVC: POST /del flow
$ curl -v -X POST localhost:8080/del/1
< HTTP/1.1 303 See Other
< Content-Type: text/html
< Location: http://localhost:8080/
< Transfer-Encoding: chunked
< Date: Fri, 13 Feb 2015 05:39:14 GMT
< Server: localhost
<
* Connection #0 to host localhost left intact
* Closing connection #0
51
MVC: DELETE /Browser form limitation: only GET and POST ### Url mappings
urls = (
'/', 'Index',
'/(\d+)', 'Index',
'/del/(\d+)', 'Delete'
)
class Index:
def DELETE(self, id):
""" Delete based on ID """
id = int(id)
model.del_todo(id)
raise web.seeother('/')
52
MVC: DELETE /
Browser form limitation: only GET and POST $ curl -v -X DELETE localhost:8080/3
* Connected to localhost (127.0.0.1) port 8080 (#0)
> DELETE /3 HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
> Host: localhost:8080
> Accept: */*
>
53
MVC: DELETE /
$ curl -v -X DELETE localhost:8080/3
< HTTP/1.1 303 See Other
< Content-Type: text/html
< Location: http://localhost:8080/
< Transfer-Encoding: chunked
< Date: Fri, 13 Feb 2015 07:15:52 GMT
< Server: localhost
<
54
User inputs
Form demo/schema.sql/templates: /templates/formtest.html /templates/index.html/form.py
55
User inputs
Form demoDatabase
create table form (id int auto_increment primary key, boe char(20), bax int, moe char(20), curly boolean, french char(20), joindate timestamp);
56
User inputs
Form demoimport web
from web import form
myform = form.Form(
form.Textbox("boe"),
form.Textbox("bax",
form.notnull,
form.regexp('\d+', 'Must be a digit'),
form.Validator('Must be more than 5', lambda x:int(x)>5)),
form.Textarea('moe'),
form.Checkbox('curly'),
form.Dropdown('french', ['mustard', 'fries', 'wine']))
57
User inputs
Form demo Extract inputs
def POST(self):
form = myform()
if not form.validates():
return render.formtest(form)
else:
db.insert('form', boe=form.d.boe,bax=form['bax'].value,moe=form.d.moe, curly=form.d.curly, french=form.d.french, joindate=web.SQLLiteral("NOW()"))
58
Database update
Blog demo model.py db = web.database(dbn='mysql', user='', pw='', db='test')
def update_post(id, title, text):
db.update('entries', where="id=$id", vars=locals(),
title=title, content=text)
59
Ordering
Blog demo model.py db = web.database(dbn='mysql', user='', pw='', db='test')
def get_posts():
return db.select('entries', order='id DESC')
60
Datetime
import datetime
from datetime import timedelta
db.insert('entries', title=title, content=text, posted_on=datetime.datetime.utcnow())
db.insert('items', category=category, title=title, price=price, open=True, end_date=datetime.datetime.utcnow()+timedelta(days=7))
61
Embed Python in HTML$def with (form, items, category, title, price, open, end_date)
<table>
$for item in items:
<tr>
<td>$item.id</td>
$if category: <td>$item.category</td>
$if title: <td>$item.title</td>
$if price: <td>$item.price</td>
$if open: <td>$item.open</td>
$if end_date: <td>$item.end_date</td>
<td><a href="/view/$item.id">View</a></td>
</tr>
</table>
62
Cookieurls = ('/bid', 'Bid',
'/bid/(\d+)', 'Bid'
)
class Bid:
def GET(self, id):
web.setcookie('id', item.id)
return render.bid(item, bid)
def POST(self):
id = web.cookies().get('id')
model.new_bid(id, bid.d.buyer, bid.d.price);
raise web.seeother('/view/' + id)