Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 339

Show
Ignore:
Timestamp:
06/17/05 14:48:32
Author:
fumanchu
Message:

Handle all HTTP methods.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/_cphttpserver.py

    r277 r339  
    7070        return list 
    7171     
    72     def doMethod(self): 
     72    def handle_one_request(self): 
     73        """Handle a single HTTP request.""" 
     74         
     75        self.raw_requestline = self.rfile.readline() 
     76        if not self.raw_requestline: 
     77            self.close_connection = 1 
     78            return 
     79        if not self.parse_request(): # An error code has been sent, just exit 
     80            return 
     81         
    7382        cpg.request.multithread = cpg.config.get("server.threadPool") > 1 
    7483        cpg.request.multiprocess = False 
     
    92101            for chunk in b: 
    93102                wfile.write(chunk) 
    94      
    95     do_GET = doMethod 
    96     do_HEAD = doMethod 
    97      
    98     def do_POST(self): 
    99         """Serve a POST request.""" 
    100         self.doMethod() 
    101         # What does this line do? 
    102         self.connection = self.request 
     103         
     104        if self.command == "POST": 
     105            self.connection = self.request 
    103106     
    104107    def log_message(self, format, *args): 
  • trunk/cherrypy/_cphttptools.py

    r338 r339  
    114114        self.requestLine = requestLine 
    115115        self.requestHeaders = headers 
    116         self.rfile = rfile 
    117116         
    118117        # Prepare cpg.request variables 
     
    123122        cpg.request.requestLine = requestLine 
    124123        cpg.request.simpleCookie = Cookie.SimpleCookie() 
    125         cpg.request.rfile = self.rfile 
     124        cpg.request.rfile = rfile 
    126125         
    127126        # Prepare cpg.response variables 
     
    144143         
    145144        self.run() 
     145         
     146        if cpg.request.method == "HEAD": 
     147            # HEAD requests MUST NOT return a message-body in the response. 
     148            cpg.response.body = [] 
    146149     
    147150    def run(self): 
     
    223226        for key, value in cpg.request.headerMap.items(): 
    224227            lowerHeaderMap[key.lower()] = value 
    225         forms = _cpcgifs.FieldStorage(fp = self.rfile, headers = lowerHeaderMap, 
     228        forms = _cpcgifs.FieldStorage(fp=cpg.request.rfile, headers=lowerHeaderMap, 
    226229                                      environ = {'REQUEST_METHOD': 'POST'}, 
    227230                                      keep_blank_values = 1) 
  • trunk/cherrypy/_cpwsgi.py

    r277 r339  
    100100            # not take any time at all if chunk is already of type "str". 
    101101            # If it's unicode, it could be a big performance hit (x ~500). 
    102             yield str(chunk) 
     102            chunk = str(chunk) 
     103            yield chunk 
    103104    except: 
    104105        tb = _cphttptools.formatExc() 
     
    116117# Server components 
    117118 
    118 class WSGIRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): 
    119      
    120     server_version = "CherryPyWSGI/2.1" 
    121     os_environ = dict(os.environ.items()) 
    122      
    123     def handle_one_request(self): 
    124         """Handle a single HTTP request. Overridden to handle all verbs.""" 
    125         response = None 
    126         self.headers_sent = False 
    127         self.responseHeaders = [] 
    128         try: 
    129             try: 
    130                 self.raw_requestline = self.rfile.readline() 
    131                 if not self.raw_requestline: 
    132                     self.close_connection = 1 
    133                     return 
    134                  
    135                 if not self.parse_request(): 
    136                     return 
    137                  
    138                 response = wsgiApp(self.environ(), self.start_response) 
    139                 for chunk in response: 
    140                     self.write(chunk) 
    141             except: 
    142                 self.handleError(sys.exc_info()) 
    143         finally: 
    144             if hasattr(response, 'close'): 
    145                 response.close() 
    146      
    147     def environ(self): 
    148         env = {'wsgi.version': (1, 0), 
    149                'wsgi.input': self.rfile, 
    150                'wsgi.errors': sys.stderr, 
    151                'wsgi.multithread': (cpg.config.get("server.threadPool") > 1), 
    152                'wsgi.multiprocess': False, 
    153                'wsgi.run_once': False, 
    154                'SERVER_PROTOCOL': self.request_version, 
    155                'GATEWAY_INTERFACE': 'CGI/1.1', 
    156                'CONTENT_TYPE': self.headers.get('Content-Type', ''), 
    157                'CONTENT_LENGTH': self.headers.get('Content-Length', ''), 
    158                # SCRIPT_NAME doesn't really apply to CherryPy 
    159                'SCRIPT_NAME': '', 
    160                } 
    161          
    162         env['SERVER_NAME'] = cpg.config.get('server.socketHost') 
    163         env['SERVER_PORT'] = cpg.config.get('server.socketPort') 
    164          
    165         if self.os_environ.get("HTTPS") in ('yes', 'on', '1'): 
    166             env['wsgi.url_scheme'] = 'https' 
    167         else: 
    168             env['wsgi.url_scheme'] = 'http' 
    169          
    170         host, port = self.client_address[:2] 
    171         env['REMOTE_ADDR'] = host 
    172          
    173         fullhost = socket.getfqdn(host) 
    174         if fullhost == host: 
    175             env['REMOTE_HOST'] = '' 
    176         else: 
    177             env['REMOTE_HOST'] = fullhost 
    178          
    179         # Update env with results of parse_request 
    180         env['REQUEST_METHOD'] = self.command 
    181         env['SERVER_PROTOCOL'] = self.request_version 
    182          
    183         if '?' in self.path: 
    184             path, query = self.path.split('?', 1) 
    185         else: 
    186             path, query = self.path, '' 
    187         env['PATH_INFO'] = urllib.unquote(path) 
    188         env['QUERY_STRING'] = query 
    189          
    190         # Update env with additional request headers 
    191         for name, value in self.headers.items(): 
    192             env['HTTP_%s' % name.replace ('-', '_').upper()] = value 
    193         return env 
    194      
    195     def start_response(self, status, headers, exc_info=None): 
    196         if exc_info: 
    197             try: 
    198                 if self.headers_sent: 
    199                     raise exc_info[0], exc_info[1], exc_info[2] 
    200             finally: 
    201                 # avoid dangling circular ref 
    202                 exc_info = None 
    203         elif self.responseHeaders: 
    204             raise AssertionError("Headers already set!") 
    205         self.status = status 
    206         self.responseHeaders = headers[:] 
    207         return self.write 
    208      
    209     def write(self, data): 
    210         if not self.headers_sent: 
    211             code, reason = self.status.split(" ", 1) 
    212             self.send_response(int(code), reason) 
    213             for name, value in self.responseHeaders: 
    214                 self.send_header(name, value) 
    215             self.end_headers() 
    216             self.headers_sent = True 
    217         self.wfile.write(data) 
    218      
    219     def send_response(self, code, message=None): 
    220         self.log_request(code) 
    221         if message is None: 
    222             if code in self.responses: 
    223                 message = self.responses[code][0] 
    224             else: 
    225                 message = '' 
    226         if self.request_version != 'HTTP/0.9': 
    227             self.wfile.write("%s %d %s\r\n" % 
    228                              (self.protocol_version, code, message)) 
    229      
    230     def handleError(self, exc): 
    231         self.close_connection = 1 
    232         msg = _cphttptools.formatExc(exc) 
    233         _cputil.getSpecialAttribute('_cpLogMessage')(msg, "HTTP") 
    234         self.status, self.headers, body = _cphttptools.bareError() 
    235         self.write(body) 
    236  
    237  
    238119class WSGIServer(_cpwsgiserver.CherryPyWSGIServer): 
    239120    def __init__(self): 
  • trunk/cherrypy/test/test_core.py

    r320 r339  
    139139         
    140140        return "double header test" 
     141 
     142 
     143defined_http_methods = ("OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", 
     144                        "TRACE", "CONNECT") 
     145class Method(Test): 
     146     
     147    def index(self): 
     148        m = cpg.request.method 
     149        if m in defined_http_methods: 
     150            return m 
     151         
     152        if m == "LINK": 
     153            cpg.response.status = 405 
     154        else: 
     155            cpg.response.status = 501 
    141156 
    142157 
     
    243258                                  'Location', 'Server']) 
    244259        self.assertEqual(cpg.response.body, "double header test") 
     260     
     261    def testMethods(self): 
     262        # Test that all defined HTTP methods work. 
     263        for m in defined_http_methods: 
     264            h = [] 
     265            if m == 'POST': 
     266                h = [("Content-type", "application/x-www-form-urlencoded"), 
     267                     ("Content-Length", "0")] 
     268            helper.request("/method/", h, method=m, body='') 
     269             
     270            # HEAD requests should not return any body. 
     271            if m == "HEAD": 
     272                m = "" 
     273             
     274            self.assertEqual(cpg.response.body, m) 
     275         
     276        # Request a disallowed method 
     277        helper.request("/method/", method="LINK") 
     278        self.assertEqual(cpg.response.status, "405 Method Not Allowed") 
     279         
     280        # Request an unknown method 
     281        helper.request("/method/", method="SEARCH") 
     282        self.assertEqual(cpg.response.status, "501 Not Implemented") 
    245283 
    246284 

Hosted by WebFaction

Log in as guest/cpguest to create tickets