Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hw10 #97

Open
wants to merge 66 commits into
base: master
Choose a base branch
from
Open

Hw10 #97

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
034ca40
modified server.py
Jan 15, 2014
6e16d25
updated server.py
Jan 15, 2014
408817b
test code for hw2
ctb Jan 17, 2014
b26ff8a
added comments.
ctb Jan 17, 2014
239ea08
added send-post-request
ctb Jan 17, 2014
e48fed6
Merge branch 'hw2' of https://github.com/ctb/cse491-serverz into hw2
Jan 22, 2014
9a45b50
passing the first test
Jan 22, 2014
b803c24
added additional page responses
Jan 22, 2014
2f723e3
fixed tests for additional page responses
Jan 23, 2014
affd9eb
Added POST response and testing
Jan 23, 2014
42a08f3
please fix
Jan 29, 2014
b64562e
splitting stuff into seperate functions
Jan 29, 2014
d612bcd
adding the form
Jan 29, 2014
f97ab58
finishing hw3
Jan 30, 2014
945317f
Updating ChangeLog
Jan 30, 2014
65452dd
Update ChangeLog
Jan 30, 2014
f3ce526
Merge pull request #2 from fenderic/hw3
Feb 6, 2014
c413434
task 1 and 2
Feb 6, 2014
db0aea4
cleaning up code
Feb 6, 2014
f50e055
adding template folder for jinja2
Feb 6, 2014
b936d1d
adding templates hopefully
Feb 6, 2014
1767c2d
got jinja stuff working properly
Feb 6, 2014
34c9930
Everything but tests are working
Feb 6, 2014
0a2b110
Update ChangeLog
Feb 6, 2014
e77f2fc
added demo of app.py, ref-server
ctb Feb 7, 2014
02de89a
Merge branch 'hw5-wsgi' of https://github.com/ctb/cse491-serverz into…
Feb 13, 2014
7b5e481
got everything except submits working
Feb 13, 2014
6bbe3c5
Update ChangeLog
Feb 13, 2014
56f047b
POST is dumb
Feb 13, 2014
538003e
Merge branch 'hw5' of http://github.com/fenderic/cse491-serverz into hw5
Feb 13, 2014
95c1d92
fixed nosetest errors from hw4
Feb 13, 2014
e274fbf
added run-qx
ctb Feb 18, 2014
44cb867
eunbong's server
ctb Feb 18, 2014
70bea8e
updated eunbong's server.py for running quixote demo app
ctb Feb 18, 2014
abda0ae
finished part 1
Feb 21, 2014
1754157
quixote stuff
Feb 21, 2014
9aebeea
finished hw6. something wrong with image, but i'll fix tomorrow
Feb 22, 2014
67bab3f
initial commit of Quixote structure
ctb Feb 22, 2014
8dfa7e2
added setup/teardown
ctb Feb 22, 2014
271c2d9
a nice, small image upload app
ctb Feb 22, 2014
d471eda
starting hw7
Feb 27, 2014
f0e37b4
cookies working
Feb 27, 2014
886ee0c
merging in imageapp stuff
Feb 27, 2014
40149b7
doing the imageapp stuff
Feb 27, 2014
b730c46
jq and js
ctb Feb 27, 2014
b9f9163
added 2nd upload example
ctb Feb 27, 2014
b40e4dd
Merge branch 'day16' of https://www.github.com/ctb/cse491-serverz int…
Feb 27, 2014
3d45917
adding in the stuff we did in class. did my javascript and jquery stuff
Feb 27, 2014
5b264b8
fixing stuff i accidentally removed and added in class that broke my
Mar 11, 2014
b7c7821
borrowing ben's code to fix my old hw
Mar 20, 2014
ad6c8e7
command line options work
Mar 20, 2014
16c71f5
twill tests'
Mar 20, 2014
565d2d5
added twill test for myapp
Mar 20, 2014
63db7ca
added thumbnail page to myapp
Mar 20, 2014
294478b
small fix
Mar 20, 2014
6817bbe
Update ChangeLog
Mar 20, 2014
8d8a60d
adding in files for quotes and chat apps from ctb's repo
Mar 24, 2014
e42e6fa
having some issues. will figure out later.
Mar 24, 2014
029bc10
project 2 for hw9. adding tiff and jpg support for imageapp
Mar 27, 2014
08c1be6
updating changelog
Mar 27, 2014
1424e4a
got chat working
Mar 27, 2014
43d54b5
fixed quotes app. no longer returns 404
Mar 27, 2014
2cc9189
added timestamp to chat messages
Mar 27, 2014
1c77915
ajaxUpload added to imageapp
Apr 1, 2014
4cec236
bleh
Apr 3, 2014
d8bd4be
i see you forking my repo westjour
Apr 3, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .coverage
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
�}q(U collectorqUcoverage v3.7.1qUlinesq}q(UK/user/austine5/cse491.env/lib/python2.7/site-packages/nose/plugins/cover.pyq]q(K�K�K�K�eU0/user/austine5/491files/cse491-serverz/server.pyq]q (KKKK K K K"K#K%K'K(K+K2K4K6K8K=K?KAKCKEKGKIKKKMKOKSKWKYKkKlKoKqKtKuKxKzK}K~K�K�K�K�K�K�K�K�K�K�K�K�eUB/user/austine5/cse491.env/lib/python2.7/site-packages/nose/case.pyq
]q (KK!K"K$K%K&K'K(K)K*K-K;K<K@KEKFKJK�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�MM
M MMMeUG/user/austine5/cse491.env/lib/python2.7/site-packages/nose/pyversion.pyq ]q(K8KwK�K�eUB/user/austine5/cse491.env/lib/python2.7/site-packages/nose/core.pyq]q(K"K$K%K)K*K+K,K2K3K7K8K;K<K=K>K?K�K�K�K�K�K�K�K�K�K�K�eUD/user/austine5/cse491.env/lib/python2.7/site-packages/nose/loader.pyq]q(KOKQKRKSKTKUKVKYKZK[K\K]K^K_KaKcK�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�M<M=M>M?MCMDMEMGMHMJMKMLMMMNMOMTMUMVMWM_MbMlMnMqMrMuMvM�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�MMMMMMM!M"M*M/M1M8MBMCMEMHeUC/user/austine5/cse491.env/lib/python2.7/site-packages/nose/proxy.pyq]q(KK+K-K.K/K9K:K;K<K>K@KNKPKQKRKSKfKgKhKnKoKpKtKuKvK�K�K�K�K�K�K�K�K�eUM/user/austine5/cse491.env/lib/python2.7/site-packages/nose/plugins/capture.pyq]q(K9K:KDKpKqKrKuKveUC/user/austine5/cse491.env/lib/python2.7/site-packages/nose/suite.pyq]q(K4KCKGKHKJKKKNKOKPK]K^K_K`KaKbKcKfKgKhKiKjKpKqK�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�M MMMMMMMMMMMM M"M#M$M(M)M,M-M.M/M3M4M7M8M:MBMCMDMEMFMGMHMIMJMPMQMRMSMTMUMXMYMZM[M\M]M^McMdMeMgMhMkMlMnMoMsMtMuMwMxMyM�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�MMMMM M!M"M)M2M3M6eU5/user/austine5/491files/cse491-serverz/test_server.pyq]q(KKKKK K
K KKKKKKKKKKKK3K4K:K<K?K@KTKUKXKZK]K^KbKcKeKgKjKkKoKpKrKtKwKxK|K}KK�K�K�K�K�K�K�K�K�K�K�K�K�eUM/user/austine5/cse491.env/lib/python2.7/site-packages/nose/plugins/manager.pyq]q(KXKYK]K^K_K`KcKiKjKkKoKrKvKxKyK{K|K�K�K�K�K�K�K�K�K�K�K�K�K�K�eUF/user/austine5/cse491.env/lib/python2.7/site-packages/nose/importer.pyq]q(KK K(K)K*K,K-K/K5K6K;K>K?KAKBKCKDKFKGKHKKKLKMKNKOKPKQK^K`KaKbKcKeKgKhK�K�K�K�K�K�K�K�K�K�K�K�K�K�K�eUP/user/austine5/cse491.env/lib/python2.7/site-packages/nose/plugins/logcapture.pyq]q(KVK�K�K�K�K�K�K�K�K�K�eUP/user/austine5/cse491.env/lib/python2.7/site-packages/nose/plugins/errorclass.pyq ]q!(K�K�K�K�K�K�eUD/user/austine5/cse491.env/lib/python2.7/site-packages/nose/result.pyq"]q#(K&K'K(K)K+K,KgKhKiKjKmKneUB/user/austine5/cse491.env/lib/python2.7/site-packages/nose/util.pyq$]q%(K�K�K�K�K�K�K�K�K�K�K�K�MMMM M
MMMMMMMMPMQMRMSMUMVM�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�M�MMM
M MMMeUF/user/austine5/cse491.env/lib/python2.7/site-packages/nose/selector.pyq&]q'(K#K%K(K)K*K+K,K-K5K6K9KDKEKHKIKJKLKMKPKQKtKuKvKwK{K|K}K~KK�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�K�euu.
Expand Down
39 changes: 37 additions & 2 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
2014-01-07 Titus Brown <[email protected]>
* Initialized repository

* Completed Homework 1

* Completed Homework 2

* Completed Homework 3

* Completed Homework 4

* Completed Homework 5

* Completed Homework 6

* Completed Homework 7

* Completed Homework 8
* * Project 1: Thumbnail Images
* * * Instructions:
* * * In command line type "python2.7 server.py -A myapp" and it will give you a link to an address.
* * * Visit that address and click on the "Thumbnail" link, that will take you to the page i added.

* Initialized repository, created server.py and README.
* Completed Homework 9
* * Project 2: JPEG and TIFF support
* * * Instructions:
* * * In command line type "python2.7 server.py -A image" and it will give you a link to an address.
* * * Visit that address and you can use either of the uploaders to upload PNG, JPEG, JPG, TIFF, TIF

* Completed Homework 10
* * Project 3: AJAX Image Upload
* * * Instructions:
* * * In command line type "python2.7 server.py -A image" and it will give you a link to an address.
* * * Visit that address and you can select AJAX Upload and then upload an
image and it will load the image without changing the page.
* * Project 4: Template
* * * Instructions:
* * * Just run the imageapp like above and you will see I have added the
ugliest template on oswd.org that i could find. It's called "grapes"
185 changes: 185 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# encoding: utf-8

import jinja2
from urlparse import parse_qs
import cgi
from os import listdir
from random import choice
from StringIO import StringIO

# Helper functions
def fileData(fname):
fp = open(fname, 'rb')
data = [fp.read()]
fp.close()
return data


def index(env, **kwargs):
response_headers = [('Content-type', 'text/html; charset="UTF-8"')]

template = env.get_template('index.html')
data = [template.render(kwargs).encode('utf-8')]

return (response_headers, data)

def content(env, **kwargs):
response_headers = [('Content-type', 'text/html; charset="UTF-8"')]

template = env.get_template('content.html')
data = [template.render(kwargs).encode('utf-8')]

return (response_headers, data)

def thumbnail(env, **kwargs):
response_headers = [('Content-type', 'text/html; charset="UTF-8"')]

template = env.get_template('thumbnail.html')
data = [template.render(kwargs).encode('utf-8')]

return (response_headers, data)

def serveImage(env, **kwargs):
# Set our response headers to indicate an image
#response_headers = [('Content-type', 'image/jpeg')]
response_headers - [('Content-type', 'image/jpg')]

# Load a random image from the images dir, and serve it
data = fileData(kwargs['path'][1:])

return (response_headers, data)

def serveFile(env, **kwargs):
# Set our response headers to indicate plaintext
response_headers = [('Content-type', 'text/plain; charset="UTF-8"')]

# Load a random image from the images dir, and serve it
data = fileData(kwargs['path'][1:])

return (response_headers, data)

def File(env, **kwargs):
# Load a random file from the files dir, and serve it
kwargs['path'] = '/files/'+choice(listdir('files'))
return serveFile(env, **kwargs)

def Image(env, **kwargs):
# Load a random image from the images dir, and serve it
kwargs['path'] = '/img/'+choice(listdir('img'))
return serveFile(env, **kwargs)

def form(env, **kwargs):
response_headers = [('Content-type', 'text/html; charset="UTF-8"')]

template = env.get_template('form.html')
data = [template.render(kwargs).encode('utf-8')]

return (response_headers, data)

def submit(env, **kwargs):
response_headers = [('Content-type', 'text/html; charset="UTF-8"')]

template = env.get_template('submit.html')
data = [template.render(kwargs).encode('utf-8')]

return (response_headers, data)

def fail(env, **kwargs):
response_headers = [('Content-type', 'text/html; charset="UTF-8"')]

# Select an amusing image to acompany
#kwargs['img'] = './404/'+choice(listdir('404'))

template = env.get_template('404.html')
data = [template.render(kwargs).encode('utf-8')]

return (response_headers, data)

def app(environ, start_response):
"""A simple WSGI application which serves several pages
and handles form data"""

# The dict of pages we know how to serve, and their corresponding templates
response = {
'/' : index, \
'/content' : content, \
'/file' : File, \
'/image' : Image, \
'/thumbnail' : thumbnail, \
'/form' : form, \
'/submit' : submit, \
'404' : fail, \
}

# Manually add all other available pages/images
#for page in listdir('404'):
# response['/404/' + page] = serveImage
#for page in listdir('images'):
# response['/img/' + page] = serveImage
#for page in listdir('files'):
# response['/files/' + page] = serveFile

# Basic connection information and set up templates
loader = jinja2.FileSystemLoader('./templates')
env = jinja2.Environment(loader=loader)

# Set up template arguments from GET requests
qs = parse_qs(environ['QUERY_STRING']).iteritems()
# Flatten the list we get from parse_qs; just assume we want the 0th for now
args = {key : val[0] for key, val in qs}
# Add the path to the args; we'll use this for page titles and 404s
args['path'] = environ['PATH_INFO']

# Grab POST args if there are any
if environ['REQUEST_METHOD'] == 'POST':
# Re-parse the headers into a format field storage can use
# Dashes instead of underscores, all lowercased
headers = {
key[5:].lower().replace('_','-') : val \
for key, val in environ.iteritems() \
if(key.startswith('HTTP'))
}
# Pull in the non-HTTP variables that field storage needs manually
headers['content-type'] = environ['CONTENT_TYPE']
headers['content-length'] = environ['CONTENT_LENGTH']
# Create a field storage to process POST args

## Bad hack to get around validator problem
if "multipart/form-data" in environ['CONTENT_TYPE']:
cLen = int(environ['CONTENT_LENGTH'])
data = environ['wsgi.input'].read(cLen)
environ['wsgi.input'] = StringIO(data)

fs = cgi.FieldStorage(fp=environ['wsgi.input'], \
headers=headers, environ=environ)
# Add these new args to the existing set
args.update({key : fs[key].value for key in fs.keys()})

# Get all the arguments in unicode form for Jinja
args = {
key.decode('utf-8') : val.decode('utf-8') \
for key, val in args.iteritems()
}

# Check if we got a path to an existing page
if environ['PATH_INFO'] in response:
# If we have that page, serve it with a 200 OK
status = '200 OK'
path = environ['PATH_INFO']

else:
# If we did not, redirect to the 404 page, with appropriate status
status = '404 Not Found'
path = '404'

args['path'] = path
response_headers, data = response[path](env, **args)

# Return the page and status code
# Page is first encoded to bytes from unicode for compatibility
start_response(status, response_headers)
return data

def make_app():
"""Wrapper function; returns the app function above to a WSGI server"""
return app
1 change: 1 addition & 0 deletions chat/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from apps import ChatApp
130 changes: 130 additions & 0 deletions chat/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import os
import os.path
import mimetypes
import traceback
import random
import time
import cgi

class Message(object):
def __init__(self, timestamp, user, message):
self.timestamp = timestamp
self.user = user
self.message = message

class ChatApp(object):
def __init__(self, files_path):
self.file_server = FileServer(files_path)
self.messages = []

def get_messages_since(self, timestamp):
"""Retrieve any messages received since the given timestamp."""
x = []
for m in self.messages:
if m.timestamp > timestamp:
x.append(m)

return x

def format_response(self, new_messages, timestamp):
x = []
for m in new_messages:
x.append("""\
<message>
<author>%s</author>
<text>%s</text>
</message>
""" % (m.user, m.message))

if x: # new messages received?
# yes
status = 1
else:
status = 2 # no new messages

xml = """
<?xml version="1.0"?>
<response>
<status>%d</status>
<time>%f</time>
%s
</response>
""" % (status, timestamp, "".join(x))

return xml

def __call__(self, environ, start_response):
url = environ['PATH_INFO']
if url == '/get_messages':
# last_time
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
last_time = float(form['last_time'].value)

new_messages = self.get_messages_since(last_time)
xml = self.format_response(new_messages, time.time())

# done; return whatever we've got.
start_response("200 OK", [('Content-type', 'text/html')])

print xml
return [xml]
elif url == '/post_message':
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)

# retrieve submitted data
last_time = float(form['last_time'].value)
author = form['user'].value
message = form['message'].value

# create and add new message:
timestamp = time.time()
m = Message(timestamp, author, message)
self.messages.append(m)

# return any new messages:
new_messages = self.get_messages_since(last_time)
xml = self.format_response(new_messages, timestamp)

# done; return whatever we've got.
start_response("200 OK", [('Content-type', 'text/html')])

print xml
return [xml]

# by default, just return a file
return self.file_server(environ, start_response)

class FileServer(object):
def __init__(self,path):
self.path = os.path.abspath(path)

def __call__(self, environ, start_response):
url = environ['PATH_INFO']

print 'url:' + url
if url.endswith('/'):
url += 'index.html'

fullpath = self.path + url
fullpath = os.path.abspath(fullpath)
assert fullpath.startswith(self.path)

extension=mimetypes.guess_type(fullpath)
extension=extension[0]

if extension is None:
extension = 'text/plain'

status = '200 OK'
headers = [('Content-type', extension )]

try:
fp = open(fullpath)
contents = fp.read()
start_response(status, headers)
return [contents]
except:
status = '404 Not Found'
headers = [('Content-type', 'text/html')]
start_response(status, headers)
return ['404 Not Found']
10 changes: 10 additions & 0 deletions chat/chat-server
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import sys
from webserve import Server

port = sys.argv[1]
port = int(port)

from apps import ChatApp
chat_app = ChatApp('./html')

Server(port, chat_app).serve_forever()
Loading