Commits

Remi Delon  committed 3ee7214

Re-organized server code to comply to CherryPyAPI in trunk

  • Participants
  • Parent commits 0f247f4
  • Branches cherrypy

Comments (0)

Files changed (3)

File _cphttpserver.py

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 """
 
-import cpg, sys, threading, SocketServer, _cphttptools, BaseHTTPServer, socket, Cookie, Queue, _cputil
+import cpg, sys, threading, SocketServer, _cphttptools, BaseHTTPServer, socket, Queue, _cputil
 
 def start():
     """ Prepare the HTTP server and then run it """
         if _reverseDNS: return BaseHTTPServer.BaseHTTPRequestHandler.address_string(self)
         else: return self.client_address[0]
 
-    def cook_headers(self):
-        """Process the headers in self.headers into the request.headerMap"""
-        cpg.request.headerMap = {}
-        cpg.request.simpleCookie = Cookie.SimpleCookie()
-        cpg.response.simpleCookie = Cookie.SimpleCookie()
-
-        # Build headerMap
-        for item in self.headers.items():
-            # Warning: if there is more than one header entry for cookies (AFAIK, only Konqueror does that)
-            # only the last one will remain in headerMap (but they will be correctly stored in request.simpleCookie)
-            _cphttptools.insertIntoHeaderMap(item[0],item[1])
-
-        # Handle cookies differently because on Konqueror, multiple cookies come on different lines with the same key
-        cookieList = self.headers.getallmatchingheaders('cookie')
-        for cookie in cookieList:
-            cpg.request.simpleCookie.load(cookie)
-
-        if not cpg.request.headerMap.has_key('Remote-Addr'):
-            try:
-                cpg.request.headerMap['Remote-Addr'] = self.client_address[0]
-                cpg.request.headerMap['Remote-Host'] = self.address_string()
-            except: pass
-
-        # Set peer_certificate (in SSL mode) so the web app can examinate the client certificate
-        try: cpg.request.peerCertificate = self.request.get_peer_certificate()
-        except: pass
-
-        _cputil.getSpecialFunction('_cpLogMessage')("%s - %s" % (cpg.request.headerMap.get('Remote-Addr', ''), self.raw_requestline[:-2]), "HTTP")
-
     def do_GET(self):
         """Serve a GET request."""
         cpg.request.method = 'GET'
-        _cphttptools.parseFirstLine(self.raw_requestline)
-        self.cook_headers()
-        # TODO _cphttptools.applyFilterList('afterRequestHeader')
-        # TODO _cphttptools.applyFilterList('afterRequestBody')
-        _cphttptools.doRequest(self.wfile)
+        _cphttptools.doRequest(self.raw_requestline, self.headers, self.rfile, self.wfile)
 
     def do_HEAD(self): # Head is not implemented
         """Serve a HEAD request."""
         cpg.request.method = 'HEAD'
-        _cphttptools.parseFirstLine(self.raw_requestline)
-        self.cook_headers()
-        _cphttptools.doRequest(self.wfile)
+        _cphttptools.doRequest(self.raw_requestline, self.headers, self.rfile, self.wfile)
 
     def do_POST(self):
         """Serve a POST request."""
         cpg.request.method = 'POST'
-        _cphttptools.parseFirstLine(self.raw_requestline)
-        self.cook_headers()
-        cpg.request.parsePostData = 1
-        cpg.request.rfile = self.rfile
-        # TODO _cphttptools.applyFilterList('afterRequestHeader')
-        if cpg.request.parsePostData:
-            _cphttptools.parsePostData(self.rfile)
-        # TODO _cphttptools.applyFilterList('afterRequestBody')
-        _cphttptools.doRequest(self.wfile)
+        _cphttptools.doRequest(self.raw_requestline, self.headers, self.rfile, self.wfile)
 
     def setup(self):
         """ We have to override this to handle SSL

File _cphttptools.py

 """
 
 import cpg, urllib, sys, time, traceback, types, StringIO, cgi, os
-import mimetypes, sha, random, string, _cputil, cperror
+import mimetypes, sha, random, string, _cputil, cperror, Cookie
 
 """
 Common Service Code for CherryPy
         cpg.request.queryString = cpg.request.path[i+1:]
         cpg.request.path = cpg.request.path[:i]
 
+def cookHeaders(headers, requestLine):
+    """Process the headers into the request.headerMap"""
+    cpg.request.headerMap = {}
+    cpg.request.simpleCookie = Cookie.SimpleCookie()
+
+    # Build headerMap
+    for item in headers.items():
+        # Warning: if there is more than one header entry for cookies (AFAIK, only Konqueror does that)
+        # only the last one will remain in headerMap (but they will be correctly stored in request.simpleCookie)
+        insertIntoHeaderMap(item[0],item[1])
+
+    # Handle cookies differently because on Konqueror, multiple cookies come on different lines with the same key
+    cookieList = headers.getallmatchingheaders('cookie')
+    for cookie in cookieList:
+        cpg.request.simpleCookie.load(cookie)
+
+    if not cpg.request.headerMap.has_key('Remote-Addr'):
+        try:
+            cpg.request.headerMap['Remote-Addr'] = self.client_address[0]
+            cpg.request.headerMap['Remote-Host'] = self.address_string()
+        except: pass
+
+    # Set peer_certificate (in SSL mode) so the web app can examinate the client certificate
+    try: cpg.request.peerCertificate = self.request.get_peer_certificate()
+    except: pass
+
+    _cputil.getSpecialFunction('_cpLogMessage')("%s - %s" % (cpg.request.headerMap.get('Remote-Addr', ''), requestLine[:-2]), "HTTP")
+
+
 def parsePostData(rfile):
     # Read request body and put it in data
     len = int(cpg.request.headerMap.get("Content-Length","0"))
     normalizedKey = '-'.join([s.capitalize() for s in key.split('-')])
     cpg.request.headerMap[normalizedKey] = value
 
-def doRequest(wfile):
+def initRequest(requestLine, headers, rfile, wfile):
+    parseFirstLine(requestLine)
+    cookHeaders(headers, requestLine)
+
+    cpg.request.base = "http://" + cpg.request.headerMap['Host']
+    cpg.request.browserUrl = cpg.request.base + cpg.request.browserUrl
+    cpg.request.isStatic = False
+    cpg.request.parsePostData = True
+    cpg.request.rfile = rfile
+
+    applyFilterList('afterRequestHeader')
+
+    if cpg.request.method == 'POST' and cpg.request.parsePostData:
+        parsePostData(rfile)
+
+    applyFilterList('afterRequestBody')
+
+def doRequest(requestLine, headers, rfile, wfile):
+    initRequest(requestLine, headers, rfile, wfile)
+
+    # Prepare response variables
+    now = time.time()
+    year, month, day, hh, mm, ss, wd, y, z = time.gmtime(now)
+    date = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (weekdayname[wd], day, monthname[month], year, hh, mm, ss)
+    cpg.response.headerMap = {
+        "protocolVersion": cpg.configOption.protocolVersion,
+        "Status": "200 OK",
+        "Content-Type": "text/html",
+        "Server": "CherryPy/" + cpg.__version__,
+        "Date": date,
+        "Set-Cookie": [],
+        "Content-Length": 0
+    }
+    cpg.response.simpleCookie = Cookie.SimpleCookie()
+    cpg.response.wfile = wfile
+    cpg.response.sendResponse = 1
+
     try:
         handleRequest(wfile)
     except:
     wfile.write(cpg.response.body)
 
 def handleRequest(wfile):
+    # Clean up expired sessions if needed:
     now = time.time()
-    year, month, day, hh, mm, ss, wd, y, z = time.gmtime(now)
-    date = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (weekdayname[wd], day, monthname[month], year, hh, mm, ss)
-    cpg.response.headerMap={"Status": "200 OK", "protocolVersion": cpg.configOption.protocolVersion, "Content-Type": "text/html", "Server": "CherryPy/" + cpg.__version__, "Date": date, "Set-Cookie": [], "Content-Length": 0}
-
-    # Two variables used for streaming
-    cpg.response.wfile = wfile
-    cpg.response.sendResponse = 1
-
-    if cpg.configOption.sslKeyFile:
-        cpg.request.base = "https://" + cpg.request.headerMap['Host']
-    else:
-        cpg.request.base = "http://" + cpg.request.headerMap['Host']
-    cpg.request.browserUrl = cpg.request.base + cpg.request.browserUrl
-    cpg.request.isStatic = 0
-
-    # TODO: Temp hack ... These filters shouldn't be here and remi
-    # needs to rewrite this code ...
-    applyFilterList('afterRequestHeader')
-    applyFilterList('afterRequestBody')
-
-    # Clean up expired sessions if needed:
     if cpg.configOption.sessionStorageType and cpg.configOption.sessionCleanUpDelay and cpg._lastSessionCleanUpTime + cpg.configOption.sessionCleanUpDelay * 60 <= now:
         cpg._lastSessionCleanUpTime = now
         _cputil.getSpecialFunction('_cpCleanUpOldSessions')()
         wfile.write('\r\n')
         return
          
-    cpg.request.objectPath = '/'.join(objectPathList)
+    cpg.request.objectPath = '/' + '/'.join(objectPathList)
     cpg.response.body = func(*(virtualPathList + cpg.request.paramList), **(cpg.request.paramMap))
 
     if cpg.response.sendResponse:

File test/testObjectMapping.py

     def index(self):
         return "index for dir1"
     index.exposed = True
+    def myMethod(self):
+        return "myMethod from dir1, object Path is:" + repr(cpg.request.objectPath)
+    myMethod.exposed = True
     def default(self, *params):
         return "default for dir1, param is:" + repr(params)
     default.exposed = True
 
 testList = [
     ("/", "cpg.response.body == 'world'"),
+    ("/dir1/myMethod", '''cpg.response.body == "myMethod from dir1, object Path is:'/root/dir1/myMethod'"'''),
     ("/this/method/does/not/exist", '''cpg.response.body == "default:('this', 'method', 'does', 'not', 'exist')"'''),
     ("/other", "cpg.response.body == 'other'"),
     ("/notExposed", '''cpg.response.body == "default:('notExposed',)"'''),