From 2446cfd2df5e0e47df584d87816dfc9fcfe410b5 Mon Sep 17 00:00:00 2001 From: Zack Newman Date: Sun, 13 Nov 2011 23:05:06 -0500 Subject: [PATCH] Added lots of content --- http-client.py | 25 ++++++++ http-client.sh | 18 ++++++ http-echo.py | 56 +++++++++++++++++ http-server.py | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ rest.odp | Bin 0 -> 35765 bytes 5 files changed, 259 insertions(+) create mode 100755 http-client.py create mode 100755 http-client.sh create mode 100755 http-echo.py create mode 100755 http-server.py create mode 100644 rest.odp diff --git a/http-client.py b/http-client.py new file mode 100755 index 0000000..64a75a5 --- /dev/null +++ b/http-client.py @@ -0,0 +1,25 @@ +#!/usr/bin/python + +# This is the hands-on part of the talk + +# You need to get this library first: +# pip install requests +# That easy! As long as you have pip +# virtualenv recommended +import requests + +# Just see basic requests +echo = "http://djce.org.uk/utils/echo.cgi" +r = requests.get(echo) +print r.content + +# See a POST request +payload = {'username': 'zack', 'password': 'squeamishossifrage'} +r = requests.post(echo, data=payload) +print r.content + +# Twitter! See what Fiddy is up to +twitter = "http://api.twitter.com/1/statuses/user_timeline.xml" +twitter_params = "?count=1&screen_name=50cent" +r = requests.get(twitter + twitter_params) +print r.content diff --git a/http-client.sh b/http-client.sh new file mode 100755 index 0000000..3bbe5b9 --- /dev/null +++ b/http-client.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# This is the hands-on part of the talk + +####### +# cURL +####### + +# Basics: Let's see what our HTTP requests look like +curl "http://djce.org.uk/utils/echo.cgi" +# POST with data +curl -d "name=zack&password=12345" "http://djce.org.uk/utils/echo.cgi" +# POST with URL-encoded data +curl --data-urlencode "name=zack&password=12345 ?" "http://djce.org.uk/utils/echo.cgi" + +# Twitter! +curl "http://api.twitter.com/1/statuses/user_timeline.xml?count=1&screen_name=50cent" + diff --git a/http-echo.py b/http-echo.py new file mode 100755 index 0000000..c4e1ad9 --- /dev/null +++ b/http-echo.py @@ -0,0 +1,56 @@ +#!/usr/bin/python + +# Much of this code thanks to docs.python.org/howto/sockets.html + +# We need to make a sockets to make a basic HTTP server +import socket +# Used to get the IP address +import fcntl +import struct + +def get_ip_address(ifname): + """ + Given an interface name (i.e. 'lo' or 'eth0') gives that interface's IP + address. Credit to http://code.activestate.com/recipes/439094/ + + Probably very specific to Linux, not portable code + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + return socket.inet_ntoa(fcntl.ioctl( + s.fileno(), + 0x8915, # SIOCGIFADDR + struct.pack('256s', ifname[:15]) + )[20:24]) + +################ +# Set up server +################ + +# INET, STREAMing socket +serversocket = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) + +# Bind to the local hostname on a port that probably isn't being used +#serversocket.bind((socket.gethostname(), 3000)) +serversocket.bind((get_ip_address('eth1'), 3000)) + +# Start listening +serversocket.listen(5) + +################### +# Main server loop +################### + +response = """HTTP/1.1 200 OK +Date: Sun, 13 Nov 2011 22:08:44 GMT +Content-Type: text/html; charset=UTF-8 + +some content +""" + +while 1: + (clientsocket, address) = serversocket.accept() + msg = clientsocket.recv(4096) + clientsocket.send(response) + clientsocket.close() + print msg diff --git a/http-server.py b/http-server.py new file mode 100755 index 0000000..c0424b7 --- /dev/null +++ b/http-server.py @@ -0,0 +1,160 @@ +#!/usr/bin/python + +# RESTful API server example + +# Much of this code thanks to docs.python.org/howto/sockets.html + +# We need to make a sockets to make a basic HTTP server +import socket +# Used to get the IP address +import fcntl +import struct +# Used for processing HTTP requests. Needs to be installed (i.e. through pip). +# try to import C parser then fallback in pure python parser. +try: + from http_parser.parser import HttpParser +except ImportError: + from http_parser.pyparser import HttpParser + +def get_ip_address(ifname): + ''' + Given an interface name (i.e. 'lo' or 'eth0') gives that interface's IP + address. Credit to http://code.activestate.com/recipes/439094/ + + Probably very specific to Linux, not portable code + ''' + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + return socket.inet_ntoa(fcntl.ioctl( + s.fileno(), + 0x8915, # SIOCGIFADDR + struct.pack('256s', ifname[:15]) + )[20:24]) + +################ +# Set up server +################ + +# INET, STREAMing socket +serversocket = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) + +# Bind to the local hostname on a port that probably isn't being used +#serversocket.bind((socket.gethostname(), 3000)) +serversocket.bind((get_ip_address('eth1'), 3000)) + +# Start listening +serversocket.listen(5) + +################################ +# Process received HTTP requests +################################ + +# User database, stored as [name, password, number logins] lists +users = [] + +def process_request(method, path, body): + if method == 'GET': + if path == '/users': + return str(users) + elif path.startswith('/users'): + return str([x for x in users if x[0] == path[len('/users/'):]]) + else: + return 'Bad URL' + elif method == 'POST': + if path == '/users/new': + name = body['name'] + password = body['password'] + if len([x for x in users if x[0] == name]) > 0: + return "ERROR: User already exists" + users.append([name, password, 0]) + return "User {0} successfully created.".format(name) + elif path == '/users/changepassword': + name = body['name'] + password = body['password'] + passwordnew = body['passwordnew'] + match_users = [x for x in users if x[0] == name] + print match_users + if len(match_users == 0): + return "ERROR: No such user" + user = match_users[0] + if password != user[1]: + return "ERROR: Bad password" + user[1] = passwordnew + return "User {0}'s password successfully changed.".format(name) + elif path == '/users/login': + name = body['name'] + password = body['password'] + match_users = [x for x in users if x[0] == name] + if len(match_users == 0): + return "ERROR: No such user" + user = match_users[0] + if password != user[1]: + return "ERROR: Bad password" + user[2] += 1 + return "User {0} successfully logged in. " + \ + "Login count: {1}".format(name, user[2]) + else: + return 'Bad URL' + elif method == 'DELETE': + if path.startswith('/users'): + name = body['name'] + password = body['password'] + match_users = [x for x in users if x[0] == name] + if len(match_users == 0): + return "ERROR: No such user" + user = match_users[0] + if password != user[1]: + return "ERROR: Bad password" + users.remove(user) + return "User {0}'s successfully deleted.".format(name) + else: + return 'Bad URL' + else: + return 'Bad Method' + +################### +# Main server loop +################### + +response = '''HTTP/1.1 200 OK +Date: Sun, 13 Nov 2011 22:08:44 GMT +Content-Type: text/html; charset=UTF-8 + +''' + +while True: + (clientsocket, address) = serversocket.accept() + parser = HttpParser() + body = [] + while True: + data = clientsocket.recv(1024) + if not data: + break + + recved = len(data) + nparsed = parser.execute(data, recved) + assert nparsed == recved + + if parser.is_headers_complete(): + print parser.get_method() + print parser.get_path() + print parser.get_headers() + + if parser.is_partial_body(): + body.append(parser.recv_body()) + + if parser.is_message_complete(): + break + + print ''.join(body) + print [x.split('=') for x in ''.join(body).split('&')] + print dict([x.split('=') for x in ''.join(body).split('&') if len(x) == 2]) + + result = process_request(parser.get_method(), + parser.get_path(), + dict([x.split('=') for x in ''.join(body).split('&') if len(x.split('=')) == 2])) + result += '\n' + clientsocket.send(response + str(result)) + print result + + clientsocket.close() diff --git a/rest.odp b/rest.odp new file mode 100644 index 0000000000000000000000000000000000000000..4d58d0faa96e2a08a52c28625041361cc19857a5 GIT binary patch literal 35765 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