日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > php >内容正文

php

flask 路由 php文件,Flask 请求处理流程(一):WSGI 和 路由

發(fā)布時(shí)間:2023/12/15 php 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 flask 路由 php文件,Flask 请求处理流程(一):WSGI 和 路由 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

flask 一個(gè)基于 python 實(shí)現(xiàn)的Web開(kāi)發(fā)微框架,主要依賴(lài):

Werkzeug:一個(gè) python 的 WSGI 工具包,也可以作為一個(gè) Web 框架的底層庫(kù)。

Jinja2:為 python 提供的一個(gè)功能齊全的模板引擎

flask 只建立 Werkezug 和 Jinja2 的橋梁,前者實(shí)現(xiàn)一個(gè)合適的 WSGI 應(yīng)用,后者處理模板。 Flask 也綁定了一些通用的標(biāo)準(zhǔn)庫(kù)包,比如 logging 。其它所有一切取決于擴(kuò)展。

一、WSGI

WSGI(Web Server Gateway Interface)的本質(zhì)是一種約定,是 Python web 開(kāi)發(fā)中 web 服務(wù)器與 web 應(yīng)用程序之間數(shù)據(jù)交互的約定。它封裝了接受 HTTP 請(qǐng)求、解析 HTTP 請(qǐng)求、發(fā)送 HTTP,響應(yīng)等等的這些底層的代碼和操作,使開(kāi)發(fā)者可以高效的編寫(xiě)Web應(yīng)用。

網(wǎng)關(guān)協(xié)議的本質(zhì)是為了解耦,實(shí)現(xiàn) web 服務(wù)器(提供 web 服務(wù))和 web 應(yīng)用程序(資源處理)的分離,WSGI 就是一個(gè)支持 WSGI 的 web 服務(wù)器與 Python web 應(yīng)用程序之間的約定。

WSGI 服務(wù)器

一個(gè) WSGI 服務(wù)器需要實(shí)現(xiàn)兩個(gè)函數(shù):

1、解析 http 請(qǐng)求,為應(yīng)用程序提供 environ 字典

def get_environ(self):

env = {}

env['wsgi.version'] = (1, 0)

env['wsgi.url_scheme'] = 'http'

env['wsgi.input'] = StringIO.StringIO(self.request_data)

env['wsgi.errors'] = sys.stderr

env['wsgi.multithread'] = False

env['wsgi.multiprocess'] = False

env['wsgi.run_once'] = False

env['REQUEST_METHOD'] = self.request_method # GET

env['PATH_INFO'] = self.path # /hello

env['SERVER_NAME'] = self.server_name # localhost

env['SERVER_PORT'] = str(self.server_port) # 8888

return env

2、實(shí)現(xiàn) start_response 函數(shù)

def start_response(self, status, response_headers, exc_info=None):

# Add necessary server headers

server_headers = [

('Date', 'Tue, 31 Mar 2015 12:54:48 GMT'),

('Server', 'WSGIServer 0.2'),

]

self.headers_set = [status, response_headers + server_headers]

# To adhere to WSGI specification the start_response must return

# a 'write' callable. We simplicity's sake we'll ignore that detail

# for now.

服務(wù)器與應(yīng)用程序交互過(guò)程

主要過(guò)程是:

服務(wù)器從客戶(hù)端獲取到請(qǐng)求,然后通過(guò) get_env 獲得 env 變量。再調(diào)用應(yīng)用程序,傳入 env 變量(字典) 和 start_response 函數(shù), 并獲得響應(yīng)。最后將響應(yīng)返回給客戶(hù)端。

代碼如下:

def handle_one_request(self):

self.request_data = request_data = self.client_connection.recv(1024)

print(''.join(

'< {line}\n'.format(line=line)

for line in request_data.splitlines()

))

self.parse_request(request_data)

env = self.get_environ() #獲取 environ

result = self.application(env, self.start_response) #調(diào)用應(yīng)用程序

self.finish_response(result)

在上述這個(gè)過(guò)程中,Python 應(yīng)用程序主要工作就是根據(jù)輸入的 environ 字典信息生成相應(yīng)的 http 報(bào)文返回給服務(wù)器。

下面是一個(gè)簡(jiǎn)單的例子:

from wsgiref.simple_server import make_server

def simple_app(environ, start_response):

status = '200 OK'

response_headers = [('Content-type', 'text/plain')]

start_response(status, response_headers)

return [u"This is hello wsgi app".encode('utf8')]

httpd = make_server('', 8000, simple_app)

print "Serving on port 8000..."

httpd.serve_forever()

其中:

environ: 一個(gè)包含全部 HTTP 請(qǐng)求信息的字典,由 WSGI Server 解包 HTTP 請(qǐng)求生成。

start_response: 一個(gè) WSGI Server 提供的函數(shù),調(diào)用可以發(fā)送響應(yīng)的狀態(tài)碼和 HTTP 報(bào)文頭, 函數(shù)在返回前必須調(diào)用一次 start_response()。

simple_app() 應(yīng)當(dāng)返回一個(gè)可以迭代的對(duì)象(HTTP正文)。

simple_app() 函數(shù)由 WSGI Server 直接調(diào)用和提供參數(shù)。

Python 內(nèi)置了一個(gè) WSGIREF 的 WSGI Server,不過(guò)性能不是很好,一般只用在開(kāi)發(fā)環(huán)境。可以選擇其他的如 Gunicorn。

總結(jié)

flask 中實(shí)現(xiàn) WSGI 接口

1.通過(guò) __call__ 方法將 Flask 對(duì)象變?yōu)榭烧{(diào)用

def __call__(self, environ, start_response):

"""Shortcut for :attr:`wsgi_app`."""

return self.wsgi_app(environ, start_response)

2. 實(shí)現(xiàn) wsgi_app 函數(shù)處理 web 服務(wù)器轉(zhuǎn)發(fā)的請(qǐng)求

def wsgi_app(self, environ, start_response):

"""

The actual WSGI application.

:param environ: a WSGI environment

:param start_response: a callable accepting a status code,

a list of headers and

an optional exception context to start the responseresponse

"""

ctx = self.request_context(environ)

error = None

try:

try:

ctx.push()

response = self.full_dispatch_request()

except Exception as e:

error = e

response = self.handle_exception(e)

except:

error = sys.exc_info()[1]

raise

return response(environ, start_response)

finally:

if self.should_ignore_error(error):

error = None

ctx.auto_pop(error)

二、路由

Flask 類(lèi)中支持路由功能的數(shù)據(jù)結(jié)構(gòu),在 __init__ 函數(shù)中初始化:

url_rule_class = Rule

self.url_map = Map()

self.view_functions = {}

Rule 和 Map 是 werkzeug 中實(shí)現(xiàn)的 路由類(lèi) 和 映射類(lèi)。

>>> m = Map([

... # Static URLs

... Rule('/', endpoint='static/index'),

... Rule('/about', endpoint='static/about'),

... Rule('/help', endpoint='static/help'),

... # Knowledge Base

... Subdomain('something', [

... Rule('/', endpoint='something/index'),

... Rule('/browse/', endpoint='something/browse'),

... Rule('/browse//', endpoint='something/browse'),

... Rule('/browse//', endpoint='something/browse')

... ])

... ], default_subdomain='www')

通過(guò) Map 我們就可以實(shí)現(xiàn)動(dòng)態(tài)路由的功能。這里我們注意到 Map 類(lèi)先建立了 url 到 endpoint 的映射,而不是直接映射到函數(shù),這是為什么呢?

主要是兩個(gè)原因:

一是為了實(shí)現(xiàn)動(dòng)態(tài)路由功能,

二是為不同的 url 映射到同一個(gè)視圖函數(shù)提供了便利。

而 view_functions 是一個(gè)字典,它負(fù)責(zé)建立 endpoint 和視圖函數(shù)之間的映射關(guān)系。

下面是一個(gè)小實(shí)驗(yàn),證明我們所說(shuō)的映射關(guān)系:

>>> from flask import Flask

>>> app = Flask(__name__)

>>> @app.route('/')

... def index():

... return "hello world"

...

>>> app.url_map

Map([ index>,

' (HEAD, GET, OPTIONS) -> static>])

>>> app.view_functions

{'index': , 'static': >}

這里我們可以看到

index>,'index':

通過(guò) endpoint 這個(gè)中間量,我們讓把 路由 和 函數(shù) 建立了映射關(guān)系。

要注意一下,為什么會(huì)有 '/static/' 這個(gè)路由呢,這是因?yàn)樵诔跏蓟瘯r(shí) flask 調(diào)用了 add_url_rule 函數(shù)做了如下綁定:

if self.has_static_folder:

assert bool(static_host) == host_matching, 'Invalid static_host/host_matching combination'

self.add_url_rule(

self.static_url_path + '/',

endpoint='static',

host=static_host,

view_func=self.send_static_file

)

總結(jié)

注冊(cè)路由

在 flask 中注冊(cè)路由有兩種方式,

一種是用 route 裝飾器,如上所示,@app.route()

另一種是直接調(diào)用 add_url_rule 函數(shù)綁定視圖類(lèi),

但是本質(zhì)上二者都是調(diào)用 add_url_rule 函數(shù),下面我們來(lái)看一下 add_url_rule 函數(shù)的實(shí)現(xiàn)。

在 Flask 的 add_url_rule 函數(shù)很長(zhǎng),但是核心的代碼為以下幾行:

self.url_map.add(rule)

rule = self.url_rule_class(rule, methods=methods, **options)

self.view_functions[endpoint] = view_func

1. 裝飾器

def route(self, rule, **options):

def decorator(f):

endpoint = options.pop('endpoint', None)

self.add_url_rule(rule, endpoint, f, **options)

return f

return decorator

2. 視圖類(lèi)

class CounterAPI(MethodView):

def get(self):

return session.get('counter', 0)

def post(self):

session['counter'] = session.get('counter', 0) + 1

return 'OK'

app.add_url_rule('/counter', view_func=CounterAPI.as_view('counter'))

注冊(cè)路由之后,flask 就需要分發(fā)路由,調(diào)用相應(yīng)的視圖函數(shù)。

def dispatch_request(self):

req = _request_ctx_stack.top.request

if req.routing_exception is not None:

self.raise_routing_exception(req)

rule = req.url_rule

if getattr(rule, 'provide_automatic_options', False) \

and req.method == 'OPTIONS':

return self.make_default_options_response()

return self.view_functions[rule.endpoint](**req.view_args)

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的flask 路由 php文件,Flask 请求处理流程(一):WSGI 和 路由的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。