Source code for wasp_general.network.web.tornado

# -*- coding: utf-8 -*-
# wasp_general/network/web/tornado.py
#
# Copyright (C) 2016 the wasp-general authors and contributors
# <see AUTHORS file>
#
# This file is part of wasp-general.
#
# Wasp-general is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Wasp-general is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with wasp-general.  If not, see <http://www.gnu.org/licenses/>.

# TODO: document the code
# TODO: write tests for the code

# noinspection PyUnresolvedReferences
from wasp_general.version import __author__, __version__, __credits__, __license__, __copyright__, __email__
# noinspection PyUnresolvedReferences
from wasp_general.version import __status__

import weakref
from tornado.web import RequestHandler

from wasp_general.network.web.proto import WWebResponseProto
from wasp_general.verify import verify_type
from wasp_general.network.web.headers import WHTTPHeaders
from wasp_general.network.web.session import WWebSessionAdapter
from wasp_general.network.web.request import WWebRequest
from wasp_general.network.web.cookies import WHTTPCookieJar


[docs]class WTornadoRequestHandler(RequestHandler): """ According to http://www.tornadoweb.org/en/stable/web.html, requesthandlers are not thread safe """ def __init__(self, wasp_web_service, application, request, **kwargs): RequestHandler.__init__(self, application, request, **kwargs) self.__sessions = {} self.__wasp_web_service = wasp_web_service
[docs] def compute_etag(self): pass
def __handle_request(self): fileno = self.request.connection.stream.socket.fileno() def close_session(): if fileno in self.__sessions.keys(): del self.__sessions[fileno] else: pass # very strange if fileno in self.__sessions.keys(): session = self.__sessions[fileno] else: session = WTornadoSessionAdapter(self, close_session) self.__sessions[fileno] = session self.__wasp_web_service.process_request(session)
[docs] def get(self, *args, **kwargs): self.__handle_request()
[docs] def head(self, *args, **kwargs): self.__handle_request()
[docs] def post(self, *args, **kwargs): self.__handle_request()
[docs] def delete(self, *args, **kwargs): self.__handle_request()
[docs] def patch(self, *args, **kwargs): self.__handle_request()
[docs] def put(self, *args, **kwargs): self.__handle_request()
[docs] def options(self, *args, **kwargs): self.__handle_request()
@classmethod def __handler__(self, wasp_web_service): class Hanlder(WTornadoRequestHandler): def __init__(self, application, request, **kwargs): WTornadoRequestHandler.__init__(self, wasp_web_service, application, request, **kwargs) return Hanlder
[docs]class WTornadoSessionAdapter(WWebSessionAdapter): def __init__(self, request_handler, cleanup_handler): def weakref_handler(socket_ref): self.session_close() self.__request_handler = request_handler self.__socket_ref = weakref.ref(request_handler.request.connection.stream.socket, weakref_handler) self.__protocol_version = request_handler.request.version[len('HTTP/'):] self.__protocol = request_handler.request.protocol self.__cleanup_handler = cleanup_handler
[docs] def accepted_socket(self): return self.__socket_ref()
[docs] def protocol_version(self): return self.__protocol_version
[docs] def protocol(self): return self.__protocol
[docs] def read_request(self): handler_headers = self.__request_handler.request.headers headers = WHTTPHeaders() for header_name in handler_headers.keys(): headers.add_headers(header_name, *handler_headers.get_list(header_name)) for cookie in WHTTPCookieJar.import_simple_cookie(self.__request_handler.cookies): headers.set_cookie_jar().add_cookie(cookie) request = WWebRequest( self, self.__request_handler.request.method, self.__request_handler.request.path, headers=headers.ro() ) #! todo: fix #request.set_request_body() return request
[docs] @verify_type(request=WWebRequest, reponse=WWebResponseProto, pushed_responses=WWebResponseProto) def write_response(self, request, response, *pushed_responses): status = response.status() headers = response.headers() response_data = response.response_data() if status is not None: self.__request_handler.set_status(status) if headers is not None: headers = headers.switch_name_style(self.protocol_version()) for header_name in headers.headers(): for header_value in headers[header_name]: self.__request_handler.add_header(header_name, header_value) content_type = headers.content_type() if content_type is not None: self.__request_handler.set_header(headers.normalize_name('Content-Type'), content_type) elif response_data is not None: self.__request_handler.set_header( headers.normalize_name('Content-Type'), 'application/octet-stream' ) for cookie in headers.set_cookie_jar(): self.__request_handler.set_cookie( cookie.name(), cookie.value(), **cookie.attrs_as_dict() ) if response_data is not None: self.__request_handler.write(response_data)
[docs] def session_close(self): self.__cleanup_handler()