def cookHeaders(clientAddress, remoteHost, headers, requestLine): """Process the headers into the request.headerMap""" cpg.request.headerMap = {} cpg.request.requestLine = requestLine 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) cpg.request.remoteAddr = clientAddress cpg.request.remoteHost = remoteHost # 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.remoteAddr, requestLine[:-2]), "HTTP")
def handle_error(self, request, client_address): """ Handle an error gracefully. May be overridden. The default is to print a traceback and continue. """ import traceback, StringIO bodyFile = StringIO.StringIO() traceback.print_exc(file=bodyFile) errorBody = bodyFile.getvalue() bodyFile.close() _cputil.getSpecialFunction("_cpLogMessage")(errorBody)
def outputConfigOptions(): _cpLogMessage = _cputil.getSpecialFunction("_cpLogMessage") _cpLogMessage("Server parameters:", "CONFIG") _cpLogMessage(" logToScreen: %s" % cpg.configOption.logToScreen, "CONFIG") _cpLogMessage(" logFile: %s" % cpg.configOption.logFile, "CONFIG") _cpLogMessage(" protocolVersion: %s" % cpg.configOption.protocolVersion, "CONFIG") _cpLogMessage(" socketHost: %s" % cpg.configOption.socketHost, "CONFIG") _cpLogMessage(" socketPort: %s" % cpg.configOption.socketPort, "CONFIG") _cpLogMessage(" socketFile: %s" % cpg.configOption.socketFile, "CONFIG") _cpLogMessage(" reverseDNS: %s" % cpg.configOption.reverseDNS, "CONFIG") _cpLogMessage(" socketQueueSize: %s" % cpg.configOption.socketQueueSize, "CONFIG") _cpLogMessage(" processPool: %s" % cpg.configOption.processPool, "CONFIG") _cpLogMessage(" threadPool: %s" % cpg.configOption.threadPool, "CONFIG") _cpLogMessage(" threading: %s" % cpg.configOption.threading, "CONFIG") _cpLogMessage(" forking: %s" % cpg.configOption.forking, "CONFIG") _cpLogMessage(" sslKeyFile: %s" % cpg.configOption.sslKeyFile, "CONFIG") if cpg.configOption.sslKeyFile: _cpLogMessage(" sslCertificateFile: %s" % cpg.configOption.sslCertificateFile, "CONFIG") _cpLogMessage( " sslClientCertificateVerification: %s" % cpg.configOption.sslClientCertificateVerification, "CONFIG" ) _cpLogMessage(" sslCACertificateFile: %s" % cpg.configOption.sslCACertificateFile, "CONFIG") _cpLogMessage(" sslVerifyDepth: %s" % cpg.configOption.sslVerifyDepth, "CONFIG") _cpLogMessage(" flushCacheDelay: %s min" % cpg.configOption.flushCacheDelay, "CONFIG") _cpLogMessage(" sessionStorageType: %s" % cpg.configOption.sessionStorageType, "CONFIG") if cpg.configOption.sessionStorageType: _cpLogMessage(" sessionTimeout: %s min" % cpg.configOption.sessionTimeout, "CONFIG") _cpLogMessage(" cleanUpDelay: %s min" % cpg.configOption.sessionCleanUpDelay, "CONFIG") _cpLogMessage(" sessionCookieName: %s" % cpg.configOption.sessionCookieName, "CONFIG") _cpLogMessage(" sessionStorageFileDir: %s" % cpg.configOption.sessionStorageFileDir, "CONFIG") _cpLogMessage(" staticContent: %s" % cpg.configOption.staticContentList, "CONFIG")
def parseConfigFile(configFile=None, parsedConfigFile=None): """ Parse the config file and set values in cpg.configOption """ _cpLogMessage = _cputil.getSpecialFunction("_cpLogMessage") if configFile: cpg.parsedConfigFile = ConfigParser.ConfigParser() if hasattr(configFile, "read"): _cpLogMessage("Reading infos from configFile stream", "CONFIG") cpg.parsedConfigFile.readfp(configFile) else: _cpLogMessage("Reading infos from configFile: %s" % configFile, "CONFIG") cpg.parsedConfigFile.read(configFile) else: cpg.parsedConfigFile = parsedConfigFile # Read parameters from configFile for sectionName, optionName, valueType in [ ("server", "logToScreen", "int"), ("server", "logFile", "str"), ("server", "socketHost", "str"), ("server", "protocolVersion", "str"), ("server", "socketPort", "int"), ("server", "socketFile", "str"), ("server", "reverseDNS", "int"), ("server", "processPool", "int"), ("server", "threadPool", "int"), ("server", "threading", "int"), ("server", "forking", "int"), ("server", "sslKeyFile", "str"), ("server", "sslCertificateFile", "str"), ("server", "sslClientCertificateVerification", "int"), ("server", "sslCACertificateFile", "str"), ("server", "sslVerifyDepth", "int"), ("session", "storageType", "str"), ("session", "timeout", "float"), ("session", "cleanUpDelay", "float"), ("session", "cookieName", "str"), ("session", "storageFileDir", "str"), ]: try: value = cpg.parsedConfigFile.get(sectionName, optionName) if valueType == "int": value = int(value) elif valueType == "float": value = float(value) if sectionName == "session": optionName = "session" + optionName[0].upper() + optionName[1:] setattr(cpg.configOption, optionName, value) except: pass try: staticDirList = cpg.parsedConfigFile.options("staticContent") for staticDir in staticDirList: staticDirTarget = cpg.parsedConfigFile.get("staticContent", staticDir) cpg.configOption.staticContentList.append((staticDir, staticDirTarget)) except: pass
def sendResponse(wfile): applyFilterList('beforeResponse') # Save session data if cpg.configOption.sessionStorageType and not cpg.request.isStatic: sessionId = cpg.response.simpleCookie[cpg.configOption.sessionCookieName].value expirationTime = time.time() + cpg.configOption.sessionTimeout * 60 _cputil.getSpecialFunction('_cpSaveSessionData')(sessionId, cpg.request.sessionMap, expirationTime) # Set the content-length if (cpg.response.headerMap.has_key('Content-Length') and cpg.response.headerMap['Content-Length']==0): buf = StringIO.StringIO() [buf.write(x) for x in cpg.response.body] buf.seek(0) cpg.response.body = [buf.read()] cpg.response.headerMap['Content-Length'] = len(cpg.response.body[0]) wfile.write('%s %s\r\n' % (cpg.response.headerMap['protocolVersion'], cpg.response.headerMap['Status'])) for key, valueList in cpg.response.headerMap.items(): if key not in ('Status', 'protocolVersion'): if type(valueList) != type([]): valueList = [valueList] for value in valueList: wfile.write('%s: %s\r\n'%(key, value)) # Send response cookies cookie = cpg.response.simpleCookie.output() if cookie: wfile.write(cookie+'\r\n') wfile.write('\r\n') for line in cpg.response.body: wfile.write(line) # finalization hook for filter cleanup & logging purposes applyFilterList('afterResponse')
def applyFilterList(methodName): try: filterList = _cputil.getSpecialFunction('_cpFilterList') for filter in filterList: method = getattr(filter, methodName, None) if method: method() except basefilter.InternalRedirect: # If we get an InternalRedirect, we start the filter list # from scratch. Is cpg.request.path or cpg.request.objectPath # has been modified by the hook, then a new filter list # will be applied. # We use recursion so if there is an infinite loop, we'll # get the regular python "recursion limit exceeded" exception. applyFilterList(methodName)
def run_server(HandlerClass, ServerClass, server_address, socketFile): """Run the HTTP request handler class.""" if cpg.configOption.socketFile: try: os.unlink(cpg.configOption.socketFile) # So we can reuse the socket except: pass server_address = cpg.configOption.socketFile if cpg.configOption.threadPool > 1: myCherryHTTPServer = ServerClass(server_address, cpg.configOption.threadPool, HandlerClass) else: myCherryHTTPServer = ServerClass(server_address, HandlerClass) cpg._server = myCherryHTTPServer if cpg.configOption.socketFile: try: os.chmod(socketFile, 0777) # So everyone can access the socket except: pass global _cpLogMessage _cpLogMessage = _cputil.getSpecialFunction("_cpLogMessage") servingWhat = "HTTP" if cpg.configOption.socketPort: onWhat = "socket: ('%s', %s)" % (cpg.configOption.socketHost, cpg.configOption.socketPort) else: onWhat = "socket file: %s" % cpg.configOption.socketFile _cpLogMessage("Serving %s on %s" % (servingWhat, onWhat), "HTTP") try: # Call the functions from cpg.server.onStartServerList for func in cpg.server.onStartServerList: func() myCherryHTTPServer.serve_forever() except KeyboardInterrupt: _cpLogMessage("<Ctrl-C> hit: shutting down", "HTTP") myCherryHTTPServer.server_close() # Call the functions from cpg.server.onStartServerList for func in cpg.server.onStopServerList: func()
def handleRequest(wfile): # Clean up expired sessions if needed: now = time.time() if cpg.configOption.sessionStorageType and cpg.configOption.sessionCleanUpDelay and cpg._lastSessionCleanUpTime + cpg.configOption.sessionCleanUpDelay * 60 <= now: cpg._lastSessionCleanUpTime = now _cputil.getSpecialFunction('_cpCleanUpOldSessions')() # Save original values (in case they get modified by filters) cpg.request.originalPath = cpg.request.path cpg.request.originalParamMap = cpg.request.paramMap cpg.request.originalParamList = cpg.request.paramList path = cpg.request.path if path.startswith('/'): path = path[1:] # Remove leading slash if path.endswith('/'): path = path[:-1] # Remove trailing slash # Handle static directories for urlDir, fsDir in cpg.configOption.staticContentList: if path == urlDir or path[:len(urlDir)+1]==urlDir+'/': cpg.request.isStatic = 1 fname = fsDir + path[len(urlDir):] try: stat = os.stat(fname) except OSError: raise cperror.NotFound if type(stat) == type(()): # Python2.1 modifTime = stat[9] else: modifTime = stat.st_mtime strModifTime = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(modifTime)) # Check if browser sent "if-modified-since" in request header if cpg.request.headerMap.has_key('If-Modified-Since'): # Check if if-modified-since date is the same as strModifTime if cpg.request.headerMap['If-Modified-Since'] == strModifTime: cpg.response.headerMap = {'Status': 304, 'protocolVersion': cpg.configOption.protocolVersion, 'Date': cpg.response.headerMap['Date']} cpg.response.body = '' sendResponse(wfile) return cpg.response.headerMap['Last-Modified'] = strModifTime f=open(fname, 'rb') cpg.response.body = f.read() f.close() # Set content-type based on filename extension i = path.rfind('.') if i != -1: ext = path[i:] else: ext = "" contentType = mimetypes.types_map.get(ext, "text/plain") cpg.response.headerMap['Content-Type'] = contentType sendResponse(wfile) return # Get session data if cpg.configOption.sessionStorageType and not cpg.request.isStatic: now = time.time() # First, get sessionId from cookie try: sessionId = cpg.request.simpleCookie[cpg.configOption.sessionCookieName].value except: sessionId=None if sessionId: # Load session data from wherever it was stored sessionData = _cputil.getSpecialFunction('_cpLoadSessionData')(sessionId) if sessionData == None: sessionId = None else: cpg.request.sessionMap, expirationTime = sessionData # Check that is hasn't expired if now > expirationTime: # Session expired sessionId = None # Create a new sessionId if needed if not sessionId: cpg.request.sessionMap = {} sessionId = generateSessionId() cpg.request.sessionMap['_sessionId'] = sessionId cpg.response.simpleCookie[cpg.configOption.sessionCookieName] = sessionId cpg.response.simpleCookie[cpg.configOption.sessionCookieName]['path'] = '/' cpg.response.simpleCookie[cpg.configOption.sessionCookieName]['version'] = 1 try: func, objectPathList, virtualPathList = mapPathToObject() except IndexRedirect, inst: # For an IndexRedirect, we don't go through the regular # mechanism: we return the redirect immediately newUrl = canonicalizeUrl(inst.args[0]) wfile.write('%s 302\r\n' % (cpg.response.headerMap['protocolVersion'])) cpg.response.headerMap['Location'] = newUrl for key, valueList in cpg.response.headerMap.items(): if key not in ('Status', 'protocolVersion'): if type(valueList) != type([]): valueList = [valueList] for value in valueList: wfile.write('%s: %s\r\n'%(key, value)) wfile.write('\r\n') return
def doRequest(clientAddress, remoteHost, requestLine, headers, rfile, wfile): initRequest(clientAddress, remoteHost, 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: err = "" exc_info_1 = sys.exc_info()[1] if hasattr(exc_info_1, 'args') and len(exc_info_1.args) >= 1: err = exc_info_1.args[0] try: _cputil.getSpecialFunction('_cpOnError')() # Still save session data if cpg.configOption.sessionStorageType and not cpg.request.isStatic: sessionId = cpg.response.simpleCookie[cpg.configOption.sessionCookieName].value expirationTime = time.time() + cpg.configOption.sessionTimeout * 60 _cputil.getSpecialFunction('_cpSaveSessionData')(sessionId, cpg.request.sessionMap, expirationTime) wfile.write('%s %s\r\n' % (cpg.response.headerMap['protocolVersion'], cpg.response.headerMap['Status'])) if (cpg.response.headerMap.has_key('Content-Length') and cpg.response.headerMap['Content-Length']==0): buf = StringIO.StringIO() [buf.write(x) for x in cpg.response.body] buf.seek(0) cpg.response.body = [buf.read()] cpg.response.headerMap['Content-Length'] = len(cpg.response.body[0]) for key, valueList in cpg.response.headerMap.items(): if key not in ('Status', 'protocolVersion'): if type(valueList) != type([]): valueList = [valueList] for value in valueList: wfile.write('%s: %s\r\n'%(key, value)) wfile.write('\r\n') for line in cpg.response.body: wfile.write(line) except: bodyFile = StringIO.StringIO() traceback.print_exc(file = bodyFile) body = bodyFile.getvalue() wfile.write('%s 200 OK\r\n' % cpg.configOption.protocolVersion) wfile.write('Content-Type: text/plain\r\n') wfile.write('Content-Length: %s\r\n' % len(body)) wfile.write('\r\n') wfile.write(body)
def log_message(self, format, *args): """ We have to override this to use our own logging mechanism """ _cputil.getSpecialFunction("_cpLogMessage")(format % args, "HTTP")