def callback(connection): stack = connection.connection_info("transaction_start_stack") if stack is not None: wiking.debug( "Unclosed transaction started at:\n%s\n" % (string.join(traceback.format_stack(stack), ""),) )
def _handle(self, req): # TODO: the documentation should be processed by LCG first into some # reasonable output format. Now we just search the file in all the # source directories and format it. No global navigation is used. path = self._document_path(req) wiking.debug('..', path, req.unresolved_path) variants = [lang for lang in wiking.module.Application.languages() if os.path.exists('.'.join((path, lang, 'txt')))] if not variants: # HACK: Try fallback to English if no application language variants # are available. In fact, the application should never return # content in any other language, than what is defined by # `Application.languages()', but default Wiking documentation is # often not translated to application languages and users get a # confusing error. This should avoid the confusion, but a proper # solution would be to have all documentation files translated at # least to one application language. if os.path.exists('.'.join((path, 'en', 'txt'))): variants = ['en'] else: raise NotFound() lang = req.preferred_language(variants) filename = '.'.join((path, lang, 'txt')) f = codecs.open(filename, encoding='utf-8') text = "".join(f.readlines()) f.close() content = lcg.Parser().parse(text) if len(content) == 1 and isinstance(content[0], lcg.Section): title = content[0].title() content = lcg.Container(content[0].content()) else: title = ' :: '.join(req.unresolved_path) if req.param('framed') == '1': # Used to display contextual help in an iframe (see pytis-ckeditor.js). layout = wiking.Exporter.Layout.FRAME else: layout = None return wiking.Document(title, content, lang=lang, variants=variants, layout=layout)
def handle(self, req): if not hasattr(self, "_first_request_served"): if __debug__: wiking.debug("Python optimization off.") else: wiking.debug("Python optimization on.") if wiking.cfg.debug and (wiking.cfg.profile or req.param("profile") == "1"): enable_profiling = True if not hasattr(self, "_first_request_served"): if req.param("ignore_first"): wiking.debug("Profiling disabled for the initial request.") enable_profiling = False else: wiking.debug("Profiling note: This is an initial request.") else: enable_profiling = False self._first_request_served = True if enable_profiling: import cProfile as profile import pstats import tempfile self._profile_req = req queries = [] def query_callback(query, start_time, end_time): queries.append((end_time - start_time, query)) wiking.WikingDefaultDataClass.set_query_callback(query_callback) uri = req.uri() tmpfile = tempfile.NamedTemporaryFile().name profile.run( "from wiking.handler import Handler; " "self = Handler._instance; " "self._result = self._handle(self._profile_req)", tmpfile, ) try: stats = pstats.Stats(tmpfile) stats.strip_dirs() stats.sort_stats("cumulative") wiking.debug("Profile statistics for %s:" % (uri,)) stats.stream = sys.stderr sys.stderr.write(" ") stats.print_stats() sys.stderr.flush() finally: os.remove(tmpfile) wiking.debug("Database queries for: %s" % (uri,)) for q in queries: info = ("#" if q[0] >= 0.01 else " ",) + q sys.stderr.write(" %s%0.3f %s\n" % info) sys.stderr.flush() return self._result else: # result, t1, t2 = timeit(self._handle, req) # log(OPERATIONAL, "Request processed in %.1f ms (%.1f ms CPU):" % # (1000*t2, 1000*t1), req.uri()) # return result try: return self._handle(req) finally: # We can observe pending transactions in Wiking applications, # so let's close them all after each request. if __debug__ and wiking.cfg.debug_transactions: def callback(connection): stack = connection.connection_info("transaction_start_stack") if stack is not None: wiking.debug( "Unclosed transaction started at:\n%s\n" % (string.join(traceback.format_stack(stack), ""),) ) else: callback = None wiking.WikingDefaultDataClass.close_idle_connections() wiking.WikingDefaultDataClass.rollback_connections(callback=callback)
def handle(self, req): if not hasattr(self, '_first_request_served'): if __debug__: wiking.debug("Python optimization off.") else: wiking.debug("Python optimization on.") if wiking.cfg.debug and (wiking.cfg.profile or req.param('profile') == '1'): enable_profiling = True if not hasattr(self, '_first_request_served'): if req.param('ignore_first'): # First request does a lot of unusual suff, so profiling it # usually doesn't make much sense. wiking.debug("Profiling disabled for the initial request.") enable_profiling = False else: wiking.debug("Profiling note: This is an initial request.") else: enable_profiling = False self._first_request_served = True if enable_profiling: import cProfile as profile import pstats import tempfile self._profile_req = req queries = [] def query_callback(query, start_time, end_time): queries.append((end_time - start_time, query,)) wiking.WikingDefaultDataClass.set_query_callback(query_callback) uri = req.uri() tmpfile = tempfile.NamedTemporaryFile().name profile.run('from wiking.handler import Handler; ' 'self = Handler._instance; ' 'self._result = self._handle(self._profile_req)', tmpfile) try: stats = pstats.Stats(tmpfile) stats.strip_dirs() stats.sort_stats('cumulative') wiking.debug("Profile statistics for %s:" % (uri,)) stats.stream = sys.stderr sys.stderr.write(' ') stats.print_stats() sys.stderr.flush() finally: os.remove(tmpfile) wiking.debug("Database queries for: %s" % (uri,)) for q in queries: info = ('#' if q[0] >= 0.01 else ' ',) + q sys.stderr.write(' %s%0.3f %s\n' % info) sys.stderr.flush() return self._result else: return self._handle(req)
def _handle(self, req): try: try: if wiking.cfg.maintenance and not req.uri().startswith('/_resources/'): # TODO: excluding /_resources/ is here to make stylesheets # available for the maintenance error page. The URI is # however not necassarily correct (application may change # it). Better would most likely be including some basic styles # directly in MinimalExporter. return self._handle_maintenance_mode(req) # Very basic CSRF prevention if req.param('submit') and req.header('Referer'): referer = urllib.parse.urlparse(req.header('Referer')) referer_uri = referer.scheme + '://' + referer.netloc server_uri = req.server_uri(current=True) if referer_uri != server_uri: wiking.debug("Request rejected due to CSRF protection:", referer_uri, server_uri) raise wiking.Redirect(req.server_uri(current=True)) # Regular processing starts here. try: result = self._application.handle(req) except wiking.Abort as abort: result = abort.result() if isinstance(result, (tuple, list)): # Temporary backwards compatibility conversion. content_type, data = result result = wiking.Response(data, content_type=content_type) if req.is_api_request() and isinstance(result, (lcg.Content, wiking.Document)): # This is a very generic detection of invalid API # requests. We just assume, that the clients, which # indicate that they accept JSON responses are API # clients and they are not interested in responses, which # display human readable content. raise wiking.BadRequest(_("This URI does not belong to server API.")) if isinstance(result, wiking.Document): # Perform authentication here if it was not performed before # to handle authentication exceptions now and prevent them in # export time. When the result is a Document, we will always # need to know the authenticated user in order to display the # login control at the top of the page. user = req.user() if user: password_expiration = user.password_expiration() password_change_uri = wiking.module.Application.password_change_uri(req) if ((password_change_uri and password_expiration and password_expiration <= datetime.date.today() and req.uri() != password_change_uri)): req.message(_("Your password expired."), req.ERROR) req.message(_("Access to the application is now restricted " "until you change your password.")) raise wiking.Redirect(password_change_uri) return self._serve_document(req, result) elif isinstance(result, lcg.Content): return self._serve_content(req, result) elif isinstance(result, wiking.Response): last_modified = result.last_modified() if last_modified is not None and req.cached_since(last_modified): raise wiking.NotModified() for header, value in result.headers(): req.set_header(header, value) filename = result.filename() if filename: # When the filename contains non-ascii characters, uwsgi raises: # TypeError: http header must be encodable in latin1 # Some context at: https://stackoverflow.com/questions/93551/ try: filename.encode('latin-1') except UnicodeEncodeError: filename_info = "filename*=UTF-8''" + urllib.parse.quote(filename) else: filename_info = 'filename="%s"' % filename disposition = 'inline' if result.inline() else 'attachment' req.set_header('Content-Disposition', disposition + '; ' + filename_info) return req.send_response(result.data(), content_type=result.content_type(), content_length=result.content_length(), status_code=result.status_code(), last_modified=result.last_modified()) else: raise Exception('Invalid handler result: %s' % type(result)) except wiking.NotModified as error: return req.send_response('', status_code=error.status_code(), content_type=None) except wiking.Redirect as r: return req.redirect(r.uri(), r.args(), status_code=r.status_code()) except wiking.RequestError as error: # Try to authenticate now, but ignore all errors within authentication except # for AuthenticationError. try: req.user() except wiking.RequestError: pass except wiking.AuthenticationError as auth_error: error = auth_error return self._handle_request_error(req, error) except wiking.ClosedConnection: return [] except Exception: # Any other unhandled exception is an Internal Server Error. It is # handled in a separate try/except block to chatch also errors in # except blocks of the inner level. return self._handle_request_error(req, wiking.InternalServerError())
def _handle(self, req): try: try: if wiking.cfg.maintenance and not req.uri().startswith('/_resources/'): # TODO: excluding /_resources/ is here to make stylesheets # available for the maintenance error page. The URI is # however not necassarily correct (application may change # it). Better would most likely be including some basic styles # directly in MinimalExporter. return self._handle_maintenance_mode(req) # Very basic CSRF prevention if req.param('submit') and req.header('Referer'): referer = urlparse.urlparse(req.header('Referer')) referer_uri = (referer.scheme + '://' + referer.netloc + urllib.unquote(referer.path)) request_uri = req.server_uri() + urlparse.urlparse(req.uri()).path if referer_uri != request_uri: wiking.debug("Request rejected due to CSRF protection:", referer_uri, request_uri) raise wiking.Redirect(req.server_uri(current=True)) # Regular processing starts here. try: result = self._application.handle(req) except wiking.Abort as abort: result = abort.result() if isinstance(result, (tuple, list)): # Temporary backwards compatibility conversion. content_type, data = result result = wiking.Response(data, content_type=content_type) if isinstance(result, (lcg.Content, wiking.Document)): if req.is_api_request(): # This is a very generic detection of invalid API # requests. We just assume, that the clients, which # indicate that they accept JSON responses are API # clients and they are not interested in responses, which # display human readable content. raise wiking.BadRequest(_("This URI does not belong to server API.")) # Always perform authentication (if it was not performed # before) to handle authentication exceptions here and # prevent them in export time. If the result is a # document, we will surely need to authenticate anyway, # because we need to display the login control at the top # of the page. req.user() if isinstance(result, wiking.Document): return self._serve_document(req, result) else: return self._serve_content(req, result) elif isinstance(result, wiking.Response): last_modified = result.last_modified() if last_modified is not None and req.cached_since(last_modified): raise wiking.NotModified() for header, value in result.headers(): req.set_header(header, value) filename = result.filename() if filename: req.set_header('Content-Disposition', 'attachment; filename="%s"' % filename) return req.send_response(result.data(), content_type=result.content_type(), content_length=result.content_length(), status_code=result.status_code(), last_modified=result.last_modified()) else: raise Exception('Invalid wiking handler result: %s' % type(result)) except wiking.NotModified as error: return req.send_response('', status_code=error.status_code(), content_type=None) except wiking.Redirect as r: return req.redirect(r.uri(), r.args(), status_code=r.status_code()) except wiking.RequestError as error: # Try to authenticate now, but ignore all errors within authentication except # for AuthenticationError. try: req.user() except wiking.RequestError: pass except wiking.AuthenticationError as auth_error: error = auth_error return self._handle_request_error(req, error) except wiking.ClosedConnection: return [] except Exception: # Any other unhandled exception is an Internal Server Error. It is # handled in a separate try/except block to chatch also errors in # except blocks of the inner level. einfo = sys.exc_info() self._application.send_bug_report(req, einfo) self._application.log_traceback(req, einfo) return self._handle_request_error(req, wiking.InternalServerError(einfo))