自己做网站现实么,wordpress 博客不显示,个人网页设计作业,wordpress背景高斯模糊session 的 源码 1.session 和 cookie 的 区别#xff1a; 答#xff1a; cookie 它是保存在浏览器的键值对。 session 它是保存在服务端的键值对。 它 依赖cookie 存在。 流程#xff1a; 一个服务端#xff0c; 一个客户端第一次来 服务端 去 客户端 发来的请求里的…session 的 源码 1.session 和 cookie 的 区别 答 cookie 它是保存在浏览器的键值对。 session 它是保存在服务端的键值对。 它 依赖cookie 存在。 流程 一个服务端 一个客户端第一次来 服务端 去 客户端 发来的请求里的cookie 里面找一个 随机字符串。 新用户没有服务端就会为客户端创建一个随机字符串发到它的cookie里并且保存到服务端。 下次这个客户端又来了那么这次服务端就可以获取到了随机字符串。 根据这个随机字符串看看你以前有没有在session里面放数据。对比 如果数据更新是会先更新到内存里面请求返回到时候在会把内存的数据保存的session。 session { pc随机字符串: {}, } 当请求第一次来生成随机字符串发给用户的cookie保存到session字段中。其实就是调用stark中介将随机字符串和对应的值放到local房主里 以后去取的时候top就行了。 请求处理完毕就将session持久化存到数据库存到redis存到加密cookie中。 2.分析session源码 1.请求刚进来先走Flask类的__call__方法。 2.用到类和方法。 3. 细分 0.app.run() run_simple(host, port, self, **options) #第一 hold 住 对象过来就执行 __call__方法. 1.__call__ 跳入 2.self.wsgi_app 跳入 def wsgi_app(self, environ, start_response): 2.1 如何封装 push 跳入 3. push跳入之后 _request_ctx_stack跳入 request 和 session 都会放入local 中。 3.1 刚开始处理session 4.self.wsgi_app. 处理函数 full_dispatch_request()跳入 5.full_dispatch_request 6.full_dispatch_request。对返回值进行封装请求完了之后 after。 finalize_request跳入 7.finalize_request process_response跳入 8.process_response 9. self.wsgi_app 里。 4.超级细分 三部曲 1. 上下文的处理: 他做的是 把requestsession 的请求相关信息放到local里。赋值给RequestContext对象 首先. if __name__ __main__:app.run()app.__call__() #第一 ps: __call__ 跳入 def __call__(self, environ, start_response):Shortcut for :attr:wsgi_app.
return self.wsgi_app(environ, start_response) #第二请求开始的地方也是结束的地方 ps: wsgi_app 跳入 def wsgi_app(self, environ, start_response): #第三{唯一标识:{stack:[ResquestContext对象(request,session)]}}#第四: 开始之前做的事情。两件事处理了request,session,将这两个数据封装到local中。ctx self.request_context(environ) #将request信息封装到Request(environ)对象并赋值给了 RequestContext对象ctx.push()error Nonetry:try:response self.full_dispatch_request() #第七执行before装饰器函数视图函数after装饰器函数except Exception as e: #如果请求出现异常error eresponse self.handle_exception(e) # 信号6 第2/3/4/5/got_request_exceptionexcept:error sys.exc_info()[1]raisereturn response(environ, start_response)finally:if self.should_ignore_error(error):error Nonectx.auto_pop(error) # 结束了 #ctx是request-Context对象 信号7 里面做了 第6信号 ps: request_context 跳入 def request_context(self, environ):return RequestContext(self, environ) ps RequestContext 跳入 class RequestContext(object):def __init__(self, app, environ, requestNone):self.app appif request is None: #如果request 为空request app.request_class(environ) # app.request_class就是request对象,app就是flask对象self.request requestself.url_adapter app.create_url_adapter(self.request)self.flashes Noneself.session None# Request contexts can be pushed multiple times and interleaved with# other request contexts. Now only if the last level is popped we# get rid of them. Additionally if an application context is missing# one is created implicitly so for each level we add this informationself._implicit_app_ctx_stack []# indicator if the context was preserved. Next time another context# is pushed the preserved context is popped.self.preserved False# remembers the exception for pop if there is one in case the context# preservation kicks in.self._preserved_exc None# Functions that should be executed after the request on the response# object. These will be called before the regular after_request# functions.self._after_request_functions []self.match_request()def _get_g(self):return _app_ctx_stack.top.gdef _set_g(self, value):_app_ctx_stack.top.g valueg property(_get_g, _set_g)del _get_g, _set_gdef copy(self):Creates a copy of this request context with the same request object.This can be used to move a request context to a different greenlet.Because the actual request object is the same this cannot be used tomove a request context to a different thread unless access to therequest object is locked... versionadded:: 0.10return self.__class__(self.app,environself.request.environ,requestself.request)def match_request(self):Can be overridden by a subclass to hook into the matchingof the request.try:url_rule, self.request.view_args \self.url_adapter.match(return_ruleTrue)self.request.url_rule url_ruleexcept HTTPException as e:self.request.routing_exception edef push(self):Binds the request context to the current context.# If an exception occurs in debug mode or if context preservation is# activated under exception situations exactly one context stays# on the stack. The rationale is that you want to access that# information under debug situations. However if someone forgets to# pop that context again we want to make sure that on the next push# its invalidated, otherwise we run at risk that something leaks# memory. This is usually only a problem in test suite since this# functionality is not active in production environments.top _request_ctx_stack.top # 取值if top is not None and top.preserved:top.pop(top._preserved_exc)# Before we push the request context we have to ensure that there# is an application context.app_ctx _app_ctx_stack.topif app_ctx is None or app_ctx.app ! self.app:app_ctx self.app.app_context() # 信号1 把app放到 local里。app_ctx.push() # 信号2AppContext(self)的push 里面做了触发执行 第1信号appcontext_pushedself._implicit_app_ctx_stack.append(app_ctx) # 信号3 把上面app_ctx对象加进来以后可以取else:self._implicit_app_ctx_stack.append(None)if hasattr(sys, exc_clear):sys.exc_clear()_request_ctx_stack.push(self) #第五将requestContext对象(request,session)的引用只要一修改都修改了添加到local中。# Open the session at the moment that the request context is# available. This allows a custom open_session method to use the# request context (e.g. code that access database information# stored on g instead of the appcontext).#self.session_interface.open_session(self, request) self.app.open_session(self.request)#return self.session_interface.open_session(self, request)#return SecureCookieSessionInterface().open_session(sekf,request) 经过一段处理session就不是None了self.session self.app.open_session(self.request) #第六刚开始处理session。self.app 表示flask 对象if self.session is None: # self 表示requestContext对象.请求一开始进来为空self.session self.app.make_null_session() # 走这里最后还是指null_session_class NullSession。def pop(self, exc_sentinel):Pops the request context and unbinds it by doing that. This willalso trigger the execution of functions registered by the:meth:~flask.Flask.teardown_request decorator... versionchanged:: 0.9Added the exc argument.app_ctx self._implicit_app_ctx_stack.pop()try:clear_request Falseif not self._implicit_app_ctx_stack:self.preserved Falseself._preserved_exc Noneif exc is _sentinel:exc sys.exc_info()[1]self.app.do_teardown_request(exc) # 信号7。2 第6信号 request_tearing_down# If this interpreter supports clearing the exception information# we do that now. This will only go into effect on Python 2.x,# on 3.x it disappears automatically at the end of the exception# stack.if hasattr(sys, exc_clear):sys.exc_clear()request_close getattr(self.request, close, None)if request_close is not None:request_close()clear_request Truefinally:rv _request_ctx_stack.pop()# get rid of circular dependencies at the end of the request# so that we dont require the GC to be active.if clear_request:rv.request.environ[werkzeug.request] None# Get rid of the app as well if necessary.if app_ctx is not None:app_ctx.pop(exc) # 信号8pop属Appcontxt 跳入 它做了触发了 第7信号 appcontext_tearing_downassert rv is self, Popped wrong request context. \(%r instead of %r) % (rv, self)def auto_pop(self, exc):if self.request.environ.get(flask._preserve_context) or \(exc is not None and self.app.preserve_context_on_exception):self.preserved Trueself._preserved_exc excelse:self.pop(exc) #信号7.1 跳入def __enter__(self):self.push()return selfdef __exit__(self, exc_type, exc_value, tb):# do not pop the request stack if we are in debug mode and an# exception happened. This will allow the debugger to still# access the request object in the interactive shell. Furthermore# the context can be force kept alive for the test client.# See flask.testing for how this works.self.auto_pop(exc_value)if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None:reraise(exc_type, exc_value, tb)def __repr__(self):return %s \%s\ [%s] of %s % (self.__class__.__name__,self.request.url,self.request.method,self.app.name,) ps: 这里我们暂时先可以看下 session 和 request 一开进来都None。 接着我们返回从push 方法进入 def wsgi_app(self, environ, start_response): #第三{唯一标识:{stack:[ResquestContext对象(request,session)]}}#第四: 开始之前做的事情。两件事处理了request,session,将这两个数据封装到local中。ctx self.request_context(environ) #将request信息封装到Request(environ)对象并赋值给了 RequestContext对象ctx.push() ps push 跳入看看里面都执行了什么 _request_ctx_stack LocalStack() ps: LocalStack() 跳入 def __init__(self):self._local Local() ps Local () 跳入 执行setattr 方法 def __setattr__(self, name, value):ident self.__ident_func__()storage self.__storage__try:storage[ident][name] valueexcept KeyError:storage[ident] {name: value} 返回 #self.session_interface.open_session(self, request) self.app.open_session(self.request)#return self.session_interface.open_session(self, request)#return SecureCookieSessionInterface().open_session(sekf,request) 经过一段处理session就不是None了self.session self.app.open_session(self.request) #第六刚开始处理session。self.app 表示flask 对象if self.session is None: # self 表示requestContext对象.请求一开始进来为空self.session self.app.make_null_session() # 走这里最后还是指null_session_class NullSession。 ps open_session 跳入 def open_session(self, request):return self.session_interface.open_session(self, request) ps session_interface 跳入 session_interface SecureCookieSessionInterface() ps SecureCookieSessionInterface() 跳入 class SecureCookieSessionInterface(SessionInterface): #: the salt that should be applied on top of the secret key for the#: signing of cookie based sessions.salt cookie-session#: the hash function to use for the signature. The default is sha1digest_method staticmethod(hashlib.sha1)#: the name of the itsdangerous supported key derivation. The default#: is hmac.key_derivation hmac#: A python serializer for the payload. The default is a compact#: JSON derived serializer with support for some extra Python types#: such as datetime objects or tuples.serializer session_json_serializersession_class SecureCookieSession #其实最后返回的还是个字典的形式 ps: SecureCookieSession跳入 class SecureCookieSession(CallbackDict, SessionMixin):Base class for sessions based on signed cookies.def __init__(self, initialNone):def on_update(self):self.modified TrueCallbackDict.__init__(self, initial, on_update)self.modified False ps: CallbackDict 跳入 class CallbackDict(UpdateDictMixin, dict): #dict 字典A dict that calls a function passed every time something is changed.The function is passed the dict instance. ps 从这可以看出它最后继承是 dict 字典。 返回 return self.session_interface.open_session(self, request) ps 从open_session 进入 def open_session(self, app, request):s self.get_signing_serializer(app) # 加密if s is None:return Noneval request.cookies.get(app.session_cookie_name) #request:请求的对象去cookie中获取session作为key对应的值。if not val: #没有return self.session_class() #返回session_classmax_age total_seconds(app.permanent_session_lifetime)try:data s.loads(val, max_agemax_age) #序列化解密return self.session_class(data)except BadSignature:return self.session_class() ps 进行一系列处理最后的返回的 session_class 是以字典形式存的。 小结 以上的流程就是上下文处理的过程。 简单的来说上下文处理做的就是把请求的数据给封装到了 local 里。 2. 视图函数处理 首先 def wsgi_app(self, environ, start_response): #第三{唯一标识:{stack:[ResquestContext对象(request,session)]}}#第四: 开始之前做的事情。两件事处理了request,session,将这两个数据封装到local中。ctx self.request_context(environ) #将request信息封装到Request(environ)对象并赋值给了 RequestContext对象ctx.push()error Nonetry:try:response self.full_dispatch_request() #第七执行before装饰器函数视图函数after装饰器函数except Exception as e: #如果请求出现异常error eresponse self.handle_exception(e) # 信号6 第2/3/4/5/got_request_exceptionexcept:error sys.exc_info()[1]raisereturn response(environ, start_response)finally:if self.should_ignore_error(error):error Nonectx.auto_pop(error) # 结束了 #ctx是request-Context对象 信号7 里面做了 第6信号 ps full_dispatch_request 跳入 def full_dispatch_request(self):Dispatches the request and on top of that performs requestpre and postprocessing as well as HTTP exception catching anderror handling... versionadded:: 0.7self.try_trigger_before_first_request_functions() #第八 执行before_first_request 装饰的所有函数try:request_started.send(self) #信号4 请求刚进来执行触发了 第2信号request_started.rv self.preprocess_request() #第九 执行 before_request 装饰的所有函数if rv is None:rv self.dispatch_request()except Exception as e:rv self.handle_user_exception(e)return self.finalize_request(rv) #第十 执行after_request 装饰的所有函数session保存 ps finalize_request 跳入 def finalize_request(self, rv, from_error_handlerFalse):Given the return value from a view function this finalizesthe request by converting it into a response and invoking thepostprocessing functions. This is invoked for both normalrequest dispatching as well as error handlers.Because this means that it might be called as a result of afailure a special safe mode is available which can be enabledwith the from_error_handler flag. If enabled, failures inresponse processing will be logged and otherwise ignored.:internal:response self.make_response(rv)try:response self.process_response(response) #第11: 进入process_responserequest_finished.send(self, responseresponse) #信号5第5信号 request_finished 执行之前视图函数如果有模板语法会先执行第34信号 before_render_template template-renderedexcept Exception:if not from_error_handler:raiseself.logger.exception(Request finalizing failed with an error while handling an error)return response ps process_session 跳入 def process_response(self, response):Can be overridden in order to modify the response objectbefore its sent to the WSGI server. By default this willcall all the :meth:after_request decorated functions... versionchanged:: 0.5As of Flask 0.5 the functions registered for after requestexecution are called in reverse order of registration.:param response: a :attr:response_class object.:return: a new response object or the same, has to be aninstance of :attr:response_class.ctx _request_ctx_stack.topbp ctx.request.blueprintfuncs ctx._after_request_functionsif bp is not None and bp in self.after_request_funcs:funcs chain(funcs, reversed(self.after_request_funcs[bp]))if None in self.after_request_funcs:funcs chain(funcs, reversed(self.after_request_funcs[None]))for handler in funcs: # 执行 after_request 装饰的所有函数response handler(response)if not self.session_interface.is_null_session(ctx.session): #最后处理sessionself.save_session(ctx.session, response)return response ps save_session 跳入 def save_session(self, session, response):Saves the session if it needs updates. For the defaultimplementation, check :meth:open_session. Instead of overriding thismethod we recommend replacing the :class:session_interface.:param session: the session to be saved (a:class:~werkzeug.contrib.securecookie.SecureCookieobject):param response: an instance of :attr:response_classreturn self.session_interface.save_session(self, session, response) ps save_session 跳入 3. 保存返回 def save_session(self, app, session, response):domain self.get_cookie_domain(app)path self.get_cookie_path(app)# Delete case. If there is no session we bail early.# If the session was modified to be empty we remove the# whole cookie.if not session:if session.modified:response.delete_cookie(app.session_cookie_name,domaindomain, pathpath)return# Modification case. There are upsides and downsides to# emitting a set-cookie header each request. The behavior# is controlled by the :meth:should_set_cookie method# which performs a quick check to figure out if the cookie# should be set or not. This is controlled by the# SESSION_REFRESH_EACH_REQUEST config flag as well as# the permanent flag on the session itself.if not self.should_set_cookie(app, session):returnhttponly self.get_cookie_httponly(app)secure self.get_cookie_secure(app)expires self.get_expiration_time(app, session)val self.get_signing_serializer(app).dumps(dict(session)) #内存中的session字典进行加密也有序列化response.set_cookie(app.session_cookie_name, val,expiresexpires, httponlyhttponly,domaindomain, pathpath, securesecure) #存到加密的cookie里。 ps: 最后 加密存到cookie里 返回 执行 finally ctx.auto_pop(error) # 结束了 #ctx是request-Context对象 信号7 里面做了 第6信号 ps: auto_pop 跳入 def auto_pop(self, exc):if self.request.environ.get(flask._preserve_context) or \(exc is not None and self.app.preserve_context_on_exception):self.preserved Trueself._preserved_exc excelse:self.pop(exc) #信号7.1 跳入 ps self.pop(exc) 跳入 def pop(self, exc_sentinel):Pops the request context and unbinds it by doing that. This willalso trigger the execution of functions registered by the:meth:~flask.Flask.teardown_request decorator... versionchanged:: 0.9Added the exc argument.app_ctx self._implicit_app_ctx_stack.pop()try:clear_request Falseif not self._implicit_app_ctx_stack:self.preserved Falseself._preserved_exc Noneif exc is _sentinel:exc sys.exc_info()[1]self.app.do_teardown_request(exc) # 信号7。2 第6信号 request_tearing_down# If this interpreter supports clearing the exception information# we do that now. This will only go into effect on Python 2.x,# on 3.x it disappears automatically at the end of the exception# stack.if hasattr(sys, exc_clear):sys.exc_clear()request_close getattr(self.request, close, None)if request_close is not None:request_close()clear_request Truefinally:rv _request_ctx_stack.pop() #把ContentText对象 POP 出来 ps: 把ContentText对象 POP 出来 结束。 转载于:https://www.cnblogs.com/zhongbokun/p/8245569.html