Python 웹 개발에서 서버 프로그램은 두 부분으로 나눌 수 있습니다:
서버 프로그램(클라이언트가 보낸 요청을 받고 정리하는 데 사용)
응용 프로그램( 서버 프로그램을 통해 전달된 요청 처리)
애플리케이션 개발 시 일반적으로 사용되는 기능을 Flask, Django, Tornado 등 다양한 프레임워크로 캡슐화합니다. (웹 개발을 위해 특정 프레임워크를 사용하는 것은 서비스 개발(최종 애플리케이션, 처리 백그라운드 로직)
그러나 서버 프로그램과 응용 프로그램은 서로 협력하여 사용자에게 서비스를 제공하며, 서로 다른 애플리케이션(다른 프레임워크)은 서로 다른 기능과 기능을 갖게 됩니다. 이때 서버 프로그램과 애플리케이션이 모두 이 표준을 지원할 수 있도록 하는 표준이 필요합니다. 그러면 둘이 잘 협력할 수 있습니다.
WSGI: wsgi는 Python 웹 개발을 위한 표준으로 프로토콜과 유사합니다. 서버 프로그램과 응용 프로그램 간의 협약으로, 서로 협력할 수 있도록 서로 사용하는 인터페이스와 기능을 규정합니다.
WSGI 응용 프로그램 조항 중 일부
응용 프로그램은 호출 가능한 개체입니다.
호출 가능한 개체에는 세 가지 유형이 있습니다.
함수
__call__() 메서드를 구현해야 하는 클래스
클래스 예시
이 객체는 두 개의 매개변수를 받습니다.
소스 코드를 보면 이 두 매개변수가 Environ과 start_response라는 것을 알 수 있습니다. 예:
class application:
def __call__(self, Environ, start_response):
pass
호출 가능 객체는 반복 가능한 값을 반환해야 합니다. 호출 가능 객체를 클래스로 예로 들어 보겠습니다.
class application:
def __call__(self, Environ, start_response):
return [xxx]
WSGI server 프로그램의 일부 조항
서버 프로그램이 애플리케이션을 호출해야 합니다
def run(application): #서버 프로그램이 애플리케이션을 호출합니다
eviron = {} #매개변수 설정
def start_response(xxx): #매개변수 설정
pass
result = application(environ, start_response) # 애플리케이션의 __call__ 함수를 호출합니다(여기서 애플리케이션은 클래스입니다)
def write (data ):
PASS
DEF DATA in Result:#))
Write (data)
서버 프로그램은 주로 다음과 같은 일을 합니다.
1. 애플리케이션에 필요한 매개변수를 설정합니다 🎜> 2. 애플리케이션 호출
3. 애플리케이션의 반환 결과를 반복하여 클라이언트에 전달
응용 프로그램의 경우 미들웨어는 서버 프로그램입니다. 미들웨어는 서버 프로그램으로 위장해야 합니다. 수락하고 애플리케이션을 호출합니다
DEF URLROUTING (URL_APP_MAPPING):
DEF MIDWARE_APP (ENVIRON, Start_Response): #함수를 호출할 수 있으며, 2개의 매개변수가 포함되어 반복으로 반환됩니다. value
URL = ENVINF O ']
APP = url_app_mapping[url] # 해당 URL에 해당하는 애플리케이션 가져오기
result = app(environ, start_response) # 애플리케이션 호출
결과 반환
return midware_app
midware_app 함수는 미들웨어입니다:
반면 midware_app 함수는 두 개의 매개변수를 받는 호출 가능 객체이고, 호출 가능 객체는 반복 가능한 값을 반환합니다. 그래서 서버 프로그램은 애플리케이션입니다
미들웨어(미들웨어) 작성 논리:
2. 미들웨어는 서버 프로그램으로 위장해야 함—> WSGI 서버 프로그램 요구 사항—>
Environ이라는 변수를 이해해야 합니다. WSGI에서 애플리케이션에는 두 가지 매개변수(environ 및 start_response)가 필요합니다. 이 두 매개변수는 서버 프로그램이 애플리케이션을 호출하기 전에 설정되어야 합니다. 그 중 start_response는 일반적으로 호출 가능한 메소드이고, Environ은 CGI에 정의되어 있는 사전입니다. CGI 문서 The Common Gateway Interface Spec에서 Environ의 정의를 확인하세요.
Environ의 매개변수는 다음과 같습니다.
AUTH_TYPE
CONTENT_LENGTH # HTTP 요청의 Content-Length 부분
CONTENT_TYPE #HTTP 요청의 Content-Tpye 부분
GATEWAY_INTERFACE
HTTP_* # HTTP_HOST, HTTP_ACCEPT 등 일련의 변수를 포함합니다.
PATH_INFO # URL 경로에서 초기 부분을 제외한 나머지 부분은 요청된 경로가 다음과 같은 경우 해당 애플리케이션 개체를 찾는 데 사용됩니다. 루트 경로, 이 값은 비어 있습니다. String
PATH_TRANSLATED
QUERY_STRING #URL 경로? 다음 부분
REMOTE_ADDR
REMOTE_HOST
REMOTE_IDENT
REMOTE_USER
REQUEST_METHOD #"GET", "POST" 등의 HTTP 요청 메소드
SCRipT_NAME #의 시작 부분에 해당하는 애플리케이션 URL 경로 프로그램 객체, 애플리케이션 객체가 서버의 루트에 해당하는 경우 이 값은 빈 문자열일 수 있습니다.
SERVER_NAME
SERVER_PORT
SERVER_PROTOCOL #클라이언트가 요청한 프로토콜(HTTP/1.1 HTTP/ 1.0)
SERVER_SOFTWARE
예: http://localhost:5000/aaa?666, 변수 값은 다음과 같습니다.
REQUEST_METHOD='GET'
SCRIPT_NAME =''
SERVER_NAME= 'localhost'
SERVER_PORT='5000'
PATH_INFO='/aaa'
QUERY_STRING='666'
SERVER_PROTOCOL='HTTP/1.1'
CONTENT_TYPE ='text/plain'
CONTEN_LENGTH=''
HTTP_HOST = 'localhost:8000'
HTTP_ACCEPT = 'text/html,application/xhtml+xml,application/xml;q=0.9, image/webp,*/*; q=0.8'
HTTP_ACCEPT_ENCODING = 'gzip,deflate,sdch'
HTTP_ACCEPT_LANGUAGE = 'en-US,en;q=0.8,zh;q=0.6,zh-CN; q=0.4,zh-TW; q=0.2'
HTTP_CONNECTION = 'keep-alive'
HTTP_USER_AGENT = 'Mozilla/5.0(X11; linux i686) AppleWebKit/537.36(KHTML, like Gecko) Chrome/32.0. 1700.77 Safari/537.36'
start_response() 함수의 경우:
start_response는 HTTP 응답의 시작이며 형식은 다음과 같습니다. start_response(status, response_headers, ex_info=None)
status는 200 OK와 같은 HTTP 상태 코드를 나타냅니다.
response_headers는 목록이고 목록 요소는 튜플입니다. (header_name, header_value)
exc_info는 요청 처리 중에 오류가 발생하는 경우 선택적 매개 변수입니다. , 이 매개변수가 설정되고 동시에 start_response가 호출됩니다
분석을 위해 werkzeug 공식 문서의 예제를 약간 개선했습니다(두 번째 부분의 SharedDataMiddleware 클래스를 읽은 후 이 섹션을 읽는 것이 좋습니다). of wsgi.py):
class Shortly(object):
def __init__(self, config):
self.redis = redis.Redis(config['redis_host'], config['redis_port'])
def dispatch_request(self, request):
return Response('Hello World!') #Initialize Response 클래스
def wsgi_app(self, Environ, start_response):
request = Request(environ)
response = self.dispatch_request(request ) #응답 유형은 Response 클래스입니다
print('%%%%%%%%%%%% %%%%%%%%%%%%%')
return response(environ , start_response) #Response의 __call__ 함수는 반복 객체를 반환하는 애플리케이션입니다.
def __call__(self, Environ, start_response):
print(self.wsgi_app)
print('erghrgheoghegoierge' )
return self.wsgi_app(environ, start_response)
def create_app(redis_host='localhost' , redis_port=6379, with_static=True):
app = Shortly({
'redis_host': ' redis_host,
'redis_port': redis_port
})
if with_static:
print('yes')
app.wsgi_app = SharedDataMiddleware(app .wsgi_app, { '/Static': OS.Path.join (os.Path.diRName (__file__), 'STATIC')
})
인쇄 ('333333333333333')
반환
#로컬 서버 열기
if __name__ == '__main__':
from werkzeug.serving import run_simple
app = create_app() #애플리케이션의 인스턴스 생성
run_simple('127.0.0.1', 5000, app , use_debugger=True, use_reloader=True)
Response의 소스 코드(Response는 BaseResponse를 상속합니다. BaseResponse의 소스 코드만 보면 됨)를 보면 다음과 같이 알 수 있습니다. dispatch_request() 함수에서 반환된 값은 Request의 생성자, 즉 Response입니다. 클래스가 반환되면 wsgi_app() 함수에서 요청의 값 유형이 Response이므로 wsgi_app()의 반환 값인 response(environ, start_response)는 실제로 Response 클래스의 __call__() 함수를 호출합니다.
소스 코드를 살펴보면 __call__()이 WSGI 애플리케이션이라는 것을 알 수 있습니다!
이 프로그램을 실행할 때:
22222222222222222
yes
33333333333333333
* http://127.0.0.1:5000/에서 실행 중입니다. (종료하려면 CTRL+C를 누르세요.)
* stat로 다시 시작
22222222222222222
yes
33333333333333333
왜 두 번 읽었는지 걱정하지 마세요.
이 웹 페이지를 열면 콘솔의 출력은 다음과 같습니다.
erghrgheoghegoierge
%%%%%%%%%%%%%%%%%%%%%% #원래 wsgi_app 함수에 있는 내용이 실행되었음을 나타냅니다!
127.0.0.1 - - [22/May/2015 21:01:25] "GET/HTTP/1.1" 200 -
보시다시피 이 경우 app.wsgi_app 이 메서드는 SharedDataMiddleware 클래스의 인스턴스가 되었습니다. 서버가 Environ 및 start_response를 앱에 전달한 후에도 wsgi_pp가 원래 wsgi_app의 콘텐츠를 계속 실행하는 이유가 궁금합니다.
호스트 주소에 접근하면 서버 프로그램이 사용자 요청을 수락한 다음, Environ과 start_response를 애플리케이션 앱에 전달합니다. 앱은 app.wsgi_app 함수가 실행되는 __call__ 함수를 실행합니다. 그런 다음 wsgi_app은 ShareDataMiddleware
의 __call__() 함수를 실행합니다. 여기서는 SharedDataMiddleware 클래스의 __call__() 소스 코드를 살펴봐야 합니다. 소스 코드를 보면 사용자가 정적 파일을 요청하지 않았으므로 return self.app(environ, start_response)가 실행된다는 것을 알 수 있습니다. 이 예에서는 ShareDataMiddleware 애플리케이션인 create_app()에서 볼 수 있습니다. 정의된 것은 app.wsgi_app이므로 여기에 반환되는 것은 원래 wsgi_app 함수입니다! 그럼 당연히 원래 기능이 실행되겠죠~
동시에 파일을 static 폴더에 넣은 다음 127.0.0.1/static/filename에 액세스해 보면 이제 파일을 볼 수 있습니다. !
이 예를 통해 미들웨어의 역할을 더 깊이 이해할 수 있습니다.
미들웨어는 서버 프로그램과 응용 프로그램 사이에 있으며 서버(environ 및
start_response)로부터 메시지를 받습니다. ) ), 특정 처리를 수행한 후 애플리케이션에서 처리해야 하는 부분을 애플리케이션에 전달하여 처리합니다.
또한 서버 프로그램에서는 WSGI 관련 변수도 정의해야 합니다.
wsgi.version
값은 WSGI 버전 1.0을 나타내는 (1, 0) 형식입니다. 모드(예: "https" 또는 "http" ~ 여기에서 HTTP 요청의 본문 부분을 읽을 수 있습니다. multithread
동일 프로세스의 다른 스레드에서 응용 프로그램 개체를 사용할 수 있는 경우 하나의 스레드가 동시에 호출하면 이 값은 True
wsgi.multiprocess
응용 프로그램 개체를 다른 프로세스에서 호출할 수 있는 경우 동시에 이 값은 True
wsgi.run_once
서버가 애플리케이션 객체를 동시에 호출하기를 원하는 경우 이를 포함하는 프로세스에서 한 번만 호출되며 값은 True입니다
위 내용은 WSGI가 이해하고 있는 내용입니다. 더 많은 관련 글은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!