COMP249 Week 6

Steve Cassidy and Yan Wang

HTTP is Stateless

HTTP wasn't designed as a protocol for long-lived transactions -- if we were starting again we might build in some idea of state or at least have the option of a stateful protocol. We didn't so we need some other mechanisms; luckily these are easily managed within the HTTP protocol.

Faking State in HTTP

What info do we want to exchange? In general we need to get some info back from the client to enable us to identify them on each transaction. This could be as simple as a username but more generally will be a unique session key. The exchanged value allows the server to look up the user or session state in a local data store.

Form Variables for State

Hidden form variable carries session info:

<form action='go.cgi'>
  ...
  <input type='hidden' name='userid' value='steve' />
  ...
</form>

When you generate a form via a CGI script the value can be inserted based on the logged in user.

Example

Form Variables in URLs

NOTE: for this to work, page generation must be via a program (CGI, JSP, etc), but then, you can't keep track of users without code.

A Better Way: Cookies

Set-Cookie

HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: session=31926xxks6; Path=/; 

<html>
...
      

Set-Cookie header instructs client to remember this cookie. Client sends it back on next request:

GET /acme/shopping HTTP/1.1
Cookie: session=31926xxks6

      

Cookie Ingredients

A cookie has more than just name=value:

Note that Expires was the old way to specify the lifetime of a cookie, Max-Age is the new way.

Cookie Ingredients

Complex Cookie

POST /acme/login HTTP/1.1
[form data]

HTTP/1.1 200 OK
Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"

POST /acme/pickitem HTTP/1.1
Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme" 
[form data]

HTTP/1.1 200 OK
Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"

POST /acme/shipping HTTP/1.1
Cookie: $Version="1";
Customer="WILE_E_COYOTE"; $Path="/acme";
Part_Number="Rocket_Launcher_0001"; $Path="/acme" 
[form data]

This example is taken from the HTTP state Management Mechanism standard (RFC2109).

Cookie Flavours

Cookie Restrictions

Cookies have been seen as a serious privacy threat since they allow sites to track users browsing patterns and potentially identify them via personal info entered into forms etc.

Cookies in Python

>>> import Cookie
>>> C = Cookie.SimpleCookie()
>>> C['name'] = 'steve'
>>> print C
Set-Cookie: name=steve;
>>> C['item'] = 'water pistol'
>>> print C
Set-Cookie: item="water pistol";
Set-Cookie: name=steve;
>>> C['item']['path'] = '/products'
>>> print C
Set-Cookie: item="water pistol"; Path=/products;
Set-Cookie: name=steve;
 

A Cookie CGI Script

from Cookie import SimpleCookie
import os

C = SimpleCookie()
C['item'] = "Water Pistol"
C['item']['path'] = '/~cassidy/'

# now output the HTTP header and content
print C
print "Content-Type: text/html\n"
print "<html><head><title>Cookie</title></head><body>"
print "<p>", C ,"</p>"
print "</body></html>"

Example

Eating Cookies

The cookie header is passed to the CGI script in the HTTP_COOKIE environment variable.

from Cookie import SimpleCookie
import os

user = ''
item = ''
if os.environ.has_key('HTTP_COOKIE'):
    C = SimpleCookie(os.environ['HTTP_COOKIE'])
    if C.has_key('user'):
        user = C['user']
    if C.has_key('item'):
        item = C['item']
else:
    C = SimpleCookie()

Example

Eating Cookies

print C
print "Content-Type: text/html\n"
print "<html><head><title>Cookie</title></head><body>"
if not user == '':
    print "<p>User is ", user ,"</p>"
    print "<p>Item is ", item ,"</p>"
else:
    print "<p>Our cookie not found.</p>"
print "</body></html>"

Example

Cookies with max-age: Example 1     Example 2

Cookies and Javascript

Web Applications

The URL Revisited

Web Applications

Web Applications

Web 2.0

And many more are tagged Web 2.0 applications.

Web Application Requirements

Web Application Reliability

Web Applications and Databases

Database Interfaces

Relational Databases

Relational Databases

An Example Database Schema

SQL

SQL

INSERT INTO orders 
            (username,item,amount)
VALUES
            ('steve','widget','1000');
	  
DELETE FROM orders 
WHERE       username = 'steve';
	  

Web Application Processes

Apache and mod_python

Zope

The ArsDigita Community System

Python and Databases

Solid Example

From The Python DB-API in Linux Journal

>>> import soliddb
>>> conn = soliddb.soliddb("Upipe SOLID', 'myusername', 'mypassword')
>>> cursor = conn.cursor()
>>> cursor.execute("select * from Seminars")
>>> cursor.fetchall()
[(4, 'Web Commerce', 300.0, 26),
 (1, 'Python Programming', 200.0, 15),
 (3, 'Socket Programming', 475.0, 7),
 (2, 'Intro to Linux', 100.0, 32),
 ]

For SQLite (pysqlite2)

>>> from pysqlite2 import dbapi2 as sqlite
>>> conn = sqlite.connect(dbname)
...

Cursor Object

A cursor object allows you to send a query and get the results.

...
cursor = conn.cursor()
cursor.execute('select * from Attendees where seminar = 1')
while 1:
   attendee = cursor.fetchone()
   if attendee == None: break
   print attendee

cursor.execute("update Attendees set paid='yes' where name='steve'")
#...more updates...
conn.commit()    # commit changes to database
#...more updates...
# discover a problem
conn.rollback()   # undo changes since last commit

RDBMS for Development

PySQLite Example

from pysqlite2 import dbapi2 as sqlite

# Create a connection to the database file "mydb":
con = sqlite.connect("mydb")

# Get a Cursor object that operates in the context of Connection con:
cur = con.cursor()

# Execute the SELECT statement:
cur.execute("select * from people order by age")

# Retrieve all rows as a sequence and print that sequence:
for row in cur.fetchall():
   print row

Some examples can be found here.