Attachment 'testACHTTPServer.py'

Download

   1 #!/usr/bin/env python
   2 #
   3 # Beat the hell out of AsyncoreHTTPServer.py.
   4 #
   5 # SVN Info
   6 #----------------------------------
   7 # $Author: cnobile $
   8 # $Date: 2010-03-04 20:50:34 $
   9 # $Revision: 1.6 $
  10 #----------------------------------
  11 ##########################################################################
  12 # Copyright (c) 2010 Carl J. Nobile.
  13 # All rights reserved. This program and the accompanying materials
  14 # are made available under the terms of the Eclipse Public License v1.0
  15 # which accompanies this distribution, and is available at
  16 # http://www.eclipse.org/legal/epl-v10.html
  17 #
  18 # Contributors:
  19 #    Carl J. Nobile - initial API and implementation
  20 ##########################################################################
  21 
  22 import socket, sys, time, getopt
  23 from asyncore import dispatcher, loop
  24 from email.Parser import Parser
  25 from email.Message import Message
  26 from threading import Thread
  27 
  28 
  29 class HeaderProducer:
  30     def __init__(self, headers):
  31         """
  32         HeaderProducer constructor.
  33 
  34         @param headers: C{email.Message.Message} object.
  35         """
  36         if not isinstance(headers, Message):
  37             raise TypeError("Must use an email.Message.Message object.")
  38 
  39         self.__headers = headers.items()
  40         self.__done = False
  41 
  42     def more(self):
  43         result = ''
  44 
  45         if self.__headers:
  46             result = "%s: %s\r\n" % (self.__headers.pop(0))
  47         elif not self.__done:
  48             self.__done = True
  49             result = "\r\n"
  50 
  51         return result
  52 
  53 
  54 class ListProducer:
  55     def __init__(self, list):
  56         """
  57         ListProducer constructor.
  58 
  59         @param list: A Python list object.
  60         """
  61         self.__list = list
  62 
  63     def more(self):
  64         result = ''
  65         if self.__list: result = self.__list.pop(0)
  66         return result
  67 
  68 
  69 class WebServerTestClient(dispatcher):
  70     def __init__(self, host, port, method, path, count, keepalive=True):
  71         dispatcher.__init__(self)
  72         self.__host = host
  73         self.__port = port
  74         self.__method = method
  75         self.__path = path
  76         self.__count = count
  77         self.__keepalive = (count != 1) and keepalive
  78         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  79         self.connect((host, port))
  80         self.buffer = ''
  81         self.getHeaders()
  82         #print "In Constructor: %s, %s, %s" % (host, port, path)
  83 
  84     def handle_connect(self):
  85         print "Connected to: http://%s:%s%s" % \
  86               (self.__host, self.__port, self.__path)
  87 
  88     def getHeaders(self):
  89         headers = Parser().parsestr('', headersonly=True)
  90         headers.add_header('Host', '%s:%s' % (self.__host, self.__port))
  91         headers.add_header('Content-Type', 'text/plain')
  92         if not self.__keepalive: headers.add_header('Connection', 'close')
  93         self.send('%s %s HTTP/1.1\r\n' % (self.__method, self.__path))
  94         hp = HeaderProducer(headers)
  95         data = hp.more()
  96 
  97         while data:
  98             self.buffer += data
  99             data = hp.more()
 100 
 101     def handle_read(self):
 102         data = self.recv(8192)
 103         print data
 104 
 105     def writable(self):
 106         return (len(self.buffer) > 0)
 107 
 108     def handle_write(self):
 109         for i in range(self.__count):
 110             if i >= (self.__count - 1): self.__keepalive = False
 111             if i != 0: self.getHeaders()
 112             self.sendRequest()
 113 
 114     def sendRequest(self):
 115         sent = self.send(self.buffer)
 116         self.buffer = self.buffer[sent:]
 117 
 118     def handle_close(self):
 119         self.close()
 120 
 121 
 122 class Channel(Thread):
 123     def __init__(self, host, port, method, path, count, keepalive, **kwargs):
 124         super(Channel, self).__init__(**kwargs)
 125         self.__host = host
 126         self.__port = port
 127         self.__method = method
 128         self.__path = path
 129         self.__count = count
 130         self.__keepalive = keepalive
 131 
 132     def run(self):
 133         print "%s, URI: http://%s:%s%s" % (self.getName(), self.__host,
 134                                            self.__port, self.__path)
 135         WebServerTestClient(self.__host, self.__port, self.__method,
 136                             self.__path, self.__count, self.__keepalive)
 137 
 138 
 139 class GetOptions(object):
 140     """
 141     This class parses the command line options and returns a dictionary
 142     of {option:value, ...} pairs.
 143     """
 144     __slots__ = ('__args', '__options', '__longOptions', '__optmap')
 145 
 146     def __init__(self, args=None, options=None, long_options=[]):
 147         """
 148         Parse the option list.
 149 
 150         @param args: The arguments from the command line minus the program
 151         name.
 152         @param options: The single character arguments.
 153         @param long_options: A Tuple of the long arguments.
 154         """
 155         self.__args = args
 156         self.__options = options
 157         self.__longOptions = long_options
 158         self.__optmap = {}
 159 
 160     def parse(self):
 161         """
 162         Parse the options into a dictionary.
 163 
 164         @return: A key/value map of the arguments and their values.
 165         """
 166         optlist, extraopts = getopt.gnu_getopt(self.__args, self.__options,
 167                                                self.__longOptions)
 168         return self._createDict(optlist)
 169 
 170     def _createDict(self, opts):
 171         """
 172         Create a dictionary of command line flags. If an arg is present more
 173         than once put all args in a list.
 174 
 175         @param opts: List of (option, value) pairs.
 176         """
 177         for arg, value in opts:
 178             if value:
 179                 if self.__optmap.has_key(arg):
 180                     tmp = self.__optmap.get(arg)
 181 
 182                     if not isinstance(tmp, list):
 183                         self.__optmap[arg] = [tmp]
 184 
 185                     valueList = self.__optmap[arg]
 186                     valueList.append(value)
 187                 else:
 188                     self.__optmap[arg] = value
 189             else:
 190                 self.__optmap[arg] = True
 191 
 192         return self.__optmap
 193 
 194     def getOptionMap(self):
 195         """
 196         Gets the option dictionary map.
 197 
 198         @return: The raw option map.
 199         """
 200         return self.__optmap
 201 
 202 
 203 def usage():
 204     """
 205     Prints the scripts usage to stdout.
 206     """
 207     print "Usage: %s " % (sys.argv[0]) + "-[d] " + \
 208           "-[h host:port, m method, p URI, c count, t timeout," + \
 209           " k keepalive(True|Flase)]"
 210 
 211 
 212 if __name__ == '__main__':
 213     import traceback
 214 
 215     options = 'dh:m:p:c:t:k:'
 216     longOptions = []
 217     opts = None
 218 
 219     try:
 220         opt = GetOptions(sys.argv[1:], options, longOptions)
 221         opts = opt.parse()
 222     except Exception, e:
 223         print "Error: Invalid argument list, " + str(e)
 224         usage()
 225         sys.exit(1)
 226 
 227     host, port = opts.get('-h', 'localhost:8081').split(':')
 228     port = int(port)
 229     method = opts.get('-m', 'HEAD').strip()
 230     path = opts.get('-p', '/')
 231     count = int(opts.get('-c', '1'))
 232     timeout = float(opts.get('-t', '30.0'))
 233     keepalive = eval(opts.get('-k', 'True').strip().capitalize())
 234     threadMap = {}
 235 
 236     if keepalive:
 237         # range should be different paths (Not implimented yet).
 238         for i in range(1):
 239             c = Channel(host, port, method, path, count, keepalive)
 240             c.setName('Channel%02i' % (i+1))
 241             threadMap[c.getName()] = c
 242             c.run()
 243     else:
 244         for i in range(count):
 245             print "Instance%02i, URI: http://%s:%s%s" % (i, host, port, path)
 246             WebServerTestClient(host, port, method, path, 1, keepalive)
 247 
 248     loop(timeout=timeout)
 249     sys.exit(0)

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.