浏览 4001 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-05-27
最后修改:2009-05-27
接上篇 在Python3.0中处理web请求-继续封装wsgi : 这次加入了Cookies封装,session支持,从线程作用域获取request,response等。目前session还不能被持久化
# -*- coding: utf-8 -*- import socketserver, re, cgi, io, urllib.parse from wsgiref.simple_server import WSGIServer import threading, time, urllib, guid from http.cookies import SimpleCookie ctx = context = threading.local() class AppException(Exception): pass class SessionPool(object): sessionIdKey = "psessionid" """存储Session的地方""" def __init__(self, session_store_time=30): """初始化Session池 @param session_store_time:session存储时间,单位:分钟 """ self.session_store_time = session_store_time self.sessions = {} def getSession(self, key): """从池中获取Session""" if(key in self.sessions): session = self.sessions[key] if(session.isTimeOut()): self.removeSession(session.sessionId) else: return session return None def createSession(self): """创建一个新的Session""" sessionId = self.newSessionId() session = Session(sessionId, self.session_store_time) self.sessions[sessionId] = session return session def removeSession(self, key): """删除Session""" #self.sessions.remove(key) if(key in self.sessions): del self.sessions[key] def newSessionId(self, ip=None): """创建一个新的SessionId""" return guid.generate(ip) def getSessionByCookie(self, cookie, response=None, create=True): """根据Cookie信息找到session""" sessionId = cookie.get(SessionPool.sessionIdKey, None) if(sessionId is not None): sessionId = sessionId.value session = self.getSession(sessionId) if(session is not None): session.lastAccessTime = time.time() return session if(create): session = self.createSession() response.putCookie(SessionPool.sessionIdKey, session.sessionId) return session return None def saveSessions(self): pass class Session(dict): """一个客户端会话""" def __init__(self, sid, store_time): self.sessionId = sid self.lastAccessTime = self.createTime = time.time() self.maxInactiveInterval = store_time # session存储时间,单位:分钟 def isTimeOut(self): """判断是否已超时""" return time.time() - self.lastAccessTime > self.maxInactiveInterval * 60 class Request(object): """保存客户端请求信息""" def __init__(self, env, sessions): self.env = env self.winput = env["wsgi.input"] self.method = env["REQUEST_METHOD"] # 获取请求方法(GET or POST) self.__attrs = {} self.attributes = {} self.encoding = "UTF-8" self.cookies = SimpleCookie(env.get("HTTP_COOKIE","")) self.response = ctx.response self.sessionPool = sessions def __getattr__(self, attr): if(attr == "params" and "params" not in self.__attrs): # 获取客户端请求参数 fp = None if(self.method == "POST"): #如果请求时以POST方式提交的,则以POST方式处理,否则以GET方式处理 content = self.winput.read(int(self.env.get("CONTENT_LENGTH","0"))) #fp = io.StringIO(content.decode(self.encoding)) fp = io.StringIO(urllib.parse.unquote(content.decode("ISO-8859-1"),encoding=self.encoding)) self.fs = cgi.FieldStorage(fp = fp, environ=self.env, keep_blank_values=1)# 创建FieldStorage self.params = {} for key in self.fs.keys(): self.params[key] = self.fs[key].value self.__attrs["params"] = self.params if(attr == "session" and "session" not in self.__attrs): # 该request中不存在session则创建一个 self.session = self.sessionPool.getSessionByCookie(self.cookies, self.response) return self.session return self.__attrs[attr] class Response(object): """对客户端进行响应""" def __init__(self, start_response, write = None): self.encoding = "UTF-8" self.start_response = start_response self._write = write self.cookies = None self.headers = {} def write(self, string): """向流中写数据 @param string:要写到流中的字符串 """ if(self._write is None): __headers = [("Content-type","text/html;charset="+self.encoding)] if(self.cookies is not None): t = ('Set-Cookie', self.cookies.output(header="")) __headers.append(t) for k, v in self.headers.items(): t = (k,v) __headers.append(t) self._write = self.start_response("200 OK", __headers) self._write(string.encode(self.encoding).decode("ISO-8859-1")) def redirect(self, url): """跳转""" if(self._write is not None): raise AppException("响应流已写入数据,无法进行跳转。") self.start_response("302 OK", [("Location",url)]) def putCookie(self, key, value, expires=1000000, path='/'): """添加Cookie信息""" if(self.cookies is None): self.cookies = SimpleCookie() self.cookies[key] = urllib.parse.quote(value) self.cookies[key]["expires"] = expires self.cookies[key]['path'] = path def addHeaders(key, value): self.headers[key] = value #WSGIServer必须放在后面…否则没有异步效果 class ThreadingWSGIServer(socketserver.ThreadingMixIn, WSGIServer): """一个使用多线程处理请求的WSGI服务类""" pass class WSGIApplication(object): """WSGI服务器程序""" def __init__(self, urls=None): self.urls = urls # URL映射 self.sessions = SessionPool(1) def getHandlerByUrl(self, url): """根据URL获取处理程序,如果没有找到该处理程序则返回None""" url = url.replace("//","/") # 避免输入错误引起的url解释错误 urlArr = url.split('/') for setUrl in self.urls.keys(): setUrlArr = setUrl.split("/") #print(setUrl.replace("*",r'\w*')) if(len(setUrlArr) == len(urlArr)): for i in range(len(urlArr)): if(i == len(urlArr) - 1 and (setUrlArr[i] == '*' or setUrlArr[i] == urlArr[i] or ('*' in setUrlArr[i] and re.search(setUrlArr[i].replace("*",r'\w*'),urlArr[i])))): return self.urls[setUrl] if(setUrlArr[i] == '*' or setUrlArr[i]==' '): continue; if(setUrlArr[i] != urlArr[i]): break; def make_app(self): """建立WSGI响应程序""" def wsgi_app(env, start_response): print("start request....") #print(";\n".join([k+"="+str(v) for k, v in env.items()])) url = env["PATH_INFO"] # 获取当前请求URL handlerCls = self.getHandlerByUrl(url) if(handlerCls is None): # 未经定义的url处理 start_response("500 OK", [("Content-type","text/html;charset=utf-8")]) return "Error URL" if(not hasattr(handlerCls,"doGET") and not hasattr(handlerCls,"doPOST")): # 映射错误 start_response("500 OK", [("Content-type","text/html;charset=utf-8")]) return "Error Mapping" response = Response(start_response) ctx.response = response request = Request(env, self.sessions) ctx.request = request # 将request和response放入当前线程作用域中,方便访问 try: handler = handlerCls(request, response) except TypeError as e: handler = handlerCls() methodName = "do" + request.method returnValue = None try: returnValue = getattr(handler,methodName)(request, response) except TypeError as e: returnValue = getattr(handler,methodName)() if(returnValue is None): returnValue=[] print("end request....") return returnValue return wsgi_app def make_server(self, serverIp='', port=8080, test=False): """建立一个默认服务器 @param test: 是否只是做一次测试 """ from wsgiref.simple_server import make_server # 加载模块 httpd = make_server(serverIp, port, self.make_app(), server_class=ThreadingWSGIServer) if test: # 如果只是测试 httpd.handle_request() # 处理单次请求 else: httpd.serve_forever() # 处理多次请求 return True def main(): app = WSGIApplication(urls={"/a/*":TestHandler, "/a/b/*.do":TestHandler}) app.make_server(test=False,port=9000) class TestHandler(object): def __init__(self): pass def doGET(self): ctx.request.encoding='UTF-8' session = ctx.request.session if("x" in ctx.request.params): session["x"] = ctx.request.params["x"] #time.sleep(3) ctx.response.write("Hello "+session["x"]) def doPOST(self): #request.encoding='UTF-8' #response.write(request.params["name"]) ctx.response.redirect("/a/x") if __name__=="__main__": main() #input()
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |