werkzeug에서 서버 처리 요청의 실현
-> self._handle_request_noblock()/usr/lib/python2.7/SocketServer.py(295)_handle_request_noblock()-> self.process_request(request, client_address)/usr/lib/python2.7/SocketServer.py(321)process_request()-> self.finish_request(request, client_address)/usr/lib/python2.7/SocketServer.py(334)finish_request()-> self.RequestHandlerClass(request, client_address, self)/usr/lib/python2.7/SocketServer.py(649)__init__()-> self.handle()/home/steinliber/flask-source-code/env/local/lib/python2.7/site-packages/werkzeug/serving.py(217)handle()-> rv = BaseHTTPRequestHandler.handle(self)/usr/lib/python2.7/BaseHTTPServer.py(340)handle()-> self.handle_one_request()/home/steinliber/flask-source-code/env/local/lib/python2.7/site-packages/werkzeug/serving.py(252)handle_one_request()-> return self.run_wsgi()/home/steinliber/flask-source-code/env/local/lib/python2.7/site-packages/werkzeug/serving.py(194)run_wsgi()-> execute(self.server.app)/home/steinliber/flask-source-code/env/local/lib/python2.7/site-packages/werkzeug/serving.py(184)execute()-> for data in application_iter:/home/steinliber/flask-source-code/env/local/lib/python2.7/site-packages/werkzeug/debug/__init__.py(199)debug_application()
먼저 방금 만들어진 HTTPServer에서 보낸 요청을 처리하고 요청한 내용,headers,method 등을 얻으며 HTTPBASEREquestHandler를 초기화하여 이 값을 모두 HTTPBASEREquestHandler의 속성으로 설정합니다.WSGIRequestHandler는 HTTPBASEREquestHandler를 계승한 것이기 때문에 그는 이러한 속성을 이용하여 APP가 실행되는 environ을 구축할 수 있다.HTTPServer에서 Handle 메서드가 호출되고 WSGIRequestHandler의 원본은 다음과 같습니다.
class WSGIRequestHandler(BaseHTTPRequestHandler, object):
"""A request handler that implements WSGI dispatching."""
@property
def server_version(self):
return 'Werkzeug/' + werkzeug.__version__
def make_environ(self):
request_url = url_parse(self.path)
def shutdown_server():
self.server.shutdown_signal = True
url_scheme = self.server.ssl_context is None and 'http' or 'https'
path_info = url_unquote(request_url.path)
environ = {
'wsgi.version': (1, 0),
'wsgi.url_scheme': url_scheme,
'wsgi.input': self.rfile,
'wsgi.errors': sys.stderr,
'wsgi.multithread': self.server.multithread,
'wsgi.multiprocess': self.server.multiprocess,
'wsgi.run_once': False,
'werkzeug.server.shutdown': shutdown_server,
'SERVER_SOFTWARE': self.server_version,
'REQUEST_METHOD': self.command,
'SCRIPT_NAME': '',
'PATH_INFO': wsgi_encoding_dance(path_info),
'QUERY_STRING': wsgi_encoding_dance(request_url.query),
'CONTENT_TYPE': self.headers.get('Content-Type', ''),
'CONTENT_LENGTH': self.headers.get('Content-Length', ''),
'REMOTE_ADDR': self.client_address[0],
'REMOTE_PORT': self.client_address[1],
'SERVER_NAME': self.server.server_address[0],
'SERVER_PORT': str(self.server.server_address[1]),
'SERVER_PROTOCOL': self.request_version
}
for key, value in self.headers.items():
key = 'HTTP_' + key.upper().replace('-', '_')
if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
environ[key] = value
if request_url.netloc:
environ['HTTP_HOST'] = request_url.netloc
return environ
def run_wsgi(self):
if self.headers.get('Expect', '').lower().strip() == '100-continue':
self.wfile.write(b'HTTP/1.1 100 Continue\r
\r
')
self.environ = environ = self.make_environ()
headers_set = []
headers_sent = []
def write(data):
assert headers_set, 'write() before start_response'
if not headers_sent:
status, response_headers = headers_sent[:] = headers_set
try:
code, msg = status.split(None, 1)
except ValueError:
code, msg = status, ""
self.send_response(int(code), msg)
header_keys = set()
for key, value in response_headers:
self.send_header(key, value)
key = key.lower()
header_keys.add(key)
if 'content-length' not in header_keys:
self.close_connection = True
self.send_header('Connection', 'close')
if 'server' not in header_keys:
self.send_header('Server', self.version_string())
if 'date' not in header_keys:
self.send_header('Date', self.date_time_string())
self.end_headers()
assert isinstance(data, bytes), 'applications must write bytes'
self.wfile.write(data)
self.wfile.flush()
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if headers_sent:
reraise(*exc_info)
finally:
exc_info = None
elif headers_set:
raise AssertionError('Headers already set')
headers_set[:] = [status, response_headers]
return write
def execute(app):
application_iter = app(environ, start_response)
try:
for data in application_iter:
write(data)
if not headers_sent:
write(b'')
finally:
if hasattr(application_iter, 'close'):
application_iter.close()
application_iter = None
try:
execute(self.server.app)
except (socket.error, socket.timeout) as e:
self.connection_dropped(e, environ)
except Exception:
if self.server.passthrough_errors:
raise
from werkzeug.debug.tbtools import get_current_traceback
traceback = get_current_traceback(ignore_system_exceptions=True)
try:
# if we haven't yet sent the headers but they are set
# we roll back to be able to set them again.
if not headers_sent:
del headers_set[:]
execute(InternalServerError())
except Exception:
pass
self.server.log('error', 'Error on request:
%s',
traceback.plaintext)
def handle(self):
"""Handles a request ignoring dropped connections."""
rv = None
try:
rv = BaseHTTPRequestHandler.handle(self)
except (socket.error, socket.timeout) as e:
self.connection_dropped(e)
except Exception:
if self.server.ssl_context is None or not is_ssl_error():
raise
if self.server.shutdown_signal:
self.initiate_shutdown()
return rv
def initiate_shutdown(self):
"""A horrible, horrible way to kill the server for Python 2.6 and
later. It's the best we can do.
"""
# Windows does not provide SIGKILL, go with SIGTERM then.
sig = getattr(signal, 'SIGKILL', signal.SIGTERM)
# reloader active
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
os.kill(os.getpid(), sig)
# python 2.7
self.server._BaseServer__shutdown_request = True
# python 2.6
self.server._BaseServer__serving = False
def connection_dropped(self, error, environ=None):
"""Called if the connection was closed by the client. By default
nothing happens.
"""
def handle_one_request(self):
"""Handle a single HTTP request."""
self.raw_requestline = self.rfile.readline()
if not self.raw_requestline:
self.close_connection = 1
elif self.parse_request():
return self.run_wsgi()
def send_response(self, code, message=None):
"""Send the response header and log the response code."""
self.log_request(code)
if message is None:
message = code in self.responses and self.responses[code][0] or ''
if self.request_version != 'HTTP/0.9':
hdr = "%s %d %s\r
" % (self.protocol_version, code, message)
self.wfile.write(hdr.encode('ascii'))
def version_string(self):
return BaseHTTPRequestHandler.version_string(self).strip()
def address_string(self):
return self.environ['REMOTE_ADDR']
def log_request(self, code='-', size='-'):
self.log('info', '"%s" %s %s', self.requestline, code, size)
def log_error(self, *args):
self.log('error', *args)
def log_message(self, format, *args):
self.log('info', format, *args)
def log(self, type, message, *args):
_log(type, '%s - - [%s] %s
' % (self.address_string(),
self.log_date_time_string(),
message % args))
그중의 핸들 방법은 BASEREquestHandler의 핸들 방법을 포장합니다. socket에 오류가 발생하거나 시간이 초과되면 링크를 계속 시도합니다. initiate_shutdown은 종료 신호를 받았을 때 서버를 강제로 닫습니다. 이 핸들 방법은 공식 문서에서 핸들을 되돌려줍니다_one_request 방법, HTTP 요청을 받고 run_u를 호출합니다.wsgi 방법으로 처리,runnu에서ssgi에서 이전에 클래스 속성으로 설정된 Request 환경 변수를 environ 사전에 저장합니다.이것은 WSGI의 규범입니다. 서버는 앱에 엔비론과 start_를 제공해야 합니다.response 두 개의 매개 변수,start_response 메서드는 status와 reponse_를 설정합니다.headers, 구체적으로 PEP333규범을 볼 수 있습니다.그리고 excute를 실행하려고 시도합니다. 만약에 socket이 발생하면.error 또는 socket.timeout 이외의 오류는 debug 모드에서 디버그 페이지로 되돌아옵니다.
다음 excute 함수에서 그는 APP를 호출하여 엔비론과 start_를 전달한다response 두 개의 매개 변수는 WSGI 규범에 따라 교체 가능한 대상을 얻어서 write를 호출해서 이 데이터를 써야 합니다.write 방법에서 그는 먼저 start_를 확정할 것이다response가 먼저 호출됩니다. 우선 headers를 보내지 않으면 headers_set의 status 및response_header가 보낸 다음에 얻은 데이터를 보내면 서버 측의 임무가 기본적으로 완성됩니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.