Mercurial > p > roundup > code
diff roundup/cgi/client.py @ 6638:e1588ae185dc issue2550923_computed_property
merge from default branch. Fix travis.ci so CI builds don't error out
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Thu, 21 Apr 2022 16:54:17 -0400 |
| parents | 91ab3e0ffcd0 |
| children | 33616bc80baf |
line wrap: on
line diff
--- a/roundup/cgi/client.py Fri Oct 08 00:37:16 2021 -0400 +++ b/roundup/cgi/client.py Thu Apr 21 16:54:17 2022 -0400 @@ -31,8 +31,8 @@ from roundup.exceptions import LoginError, Reject, RejectRaw, \ Unauthorised, UsageError from roundup.cgi.exceptions import ( - FormError, NotFound, NotModified, Redirect, SendFile, SendStaticFile, - DetectorError, SeriousError) + FormError, IndexerQueryError, NotFound, NotModified, Redirect, + SendFile, SendStaticFile, DetectorError, SeriousError) from roundup.cgi.form_parser import FormParser from roundup.mailer import Mailer, MessageSendError from roundup.cgi import accept_language @@ -340,7 +340,10 @@ # Key can be explicitly file basename - value applied to just that file # takes precedence over mime type. # Key can be mime type - all files of that mimetype will get the value - Cache_Control = {} + Cache_Control = { + 'application/javascript': "public, max-age=1209600", # 2 weeks + 'text/css': "public, max-age=4838400", # 8 weeks/2 months + } # list of valid http compression (Content-Encoding) algorithms # we have available @@ -645,8 +648,11 @@ # type header set by rest handler # self.setHeader("Content-Type", "text/xml") - self.setHeader("Content-Length", str(len(output))) - self.write(output) + if self.response_code == 204: # no body with 204 + self.write("") + else: + self.setHeader("Content-Length", str(len(output))) + self.write(output) def add_ok_message(self, msg, escape=True): add_message(self._ok_message, msg, escape) @@ -848,7 +854,7 @@ else: # in debug mode, only write error to screen. self.write_html(e.html) - except: + except Exception as e: # Something has gone badly wrong. Therefore, we should # make sure that the response code indicates failure. if self.response_code == http_.client.OK: @@ -1775,7 +1781,6 @@ """ # spit out headers - self.additional_headers['Content-Type'] = mime_type self.additional_headers['Last-Modified'] = email.utils.formatdate(lmt) ims = None @@ -1796,6 +1801,9 @@ self.setVary("Accept-Encoding") raise NotModified + # don't set until we are sure we are sending a response body. + self.additional_headers['Content-Type'] = mime_type + if filename: self.write_file(filename) else: @@ -1915,7 +1923,11 @@ } pt = self.instance.templates.load(tplname) # let the template render figure stuff out - result = pt.render(self, None, None, **args) + try: + result = pt.render(self, None, None, **args) + except IndexerQueryError as e: + result = self.renderError(e.args[0]) + self.additional_headers['Content-Type'] = pt.content_type if self.env.get('CGI_SHOW_TIMING', ''): if self.env['CGI_SHOW_TIMING'].upper() == 'COMMENT': @@ -1962,6 +1974,46 @@ else: exec('raise exc_info[0], exc_info[1], exc_info[2]') # nosec + def renderError(self, error, response_code=400, use_template=True): + self.response_code = response_code + + # see if error message already logged add if not + if error not in self._error_message: + self.add_error_message(error, escape=True) + + # allow use of template for a specific code + trial_templates = [] + if use_template: + if response_code == 400: + trial_templates = [ "400" ] + else: + trial_templates = [ str(response_code), "400" ] + + tplname = None + for rcode in trial_templates: + try: + tplname = self.selectTemplate(self.classname, rcode) + break + except templating.NoTemplate: + pass + + if not tplname: + # call string of serious error to get basic html + # response. + return str(SeriousError(error)) + + args = { + 'ok_message': self._ok_message, + 'error_message': self._error_message + } + + try: + pt = self.instance.templates.load(tplname) + return pt.render(self, None, None, **args) + except Exception: + # report original error + return str(SeriousError(error)) + # these are the actions that are available actions = ( ('edit', actions.EditItemAction), @@ -2163,6 +2215,14 @@ self.additional_headers['Content-Length'] = str(len(new_content)) self.additional_headers['Content-Encoding'] = encoder self.setVary('Accept-Encoding') + try: + current_etag = self.additional_headers['ETag'] + except KeyError: + pass # etag not set for non-rest endpoints + else: + etag_end = current_etag.rindex('"') + self.additional_headers['ETag'] = ( current_etag[:etag_end] + + '-' + encoder + current_etag[etag_end:]) return new_content @@ -2196,6 +2256,8 @@ if 'Content-Type' not in self.additional_headers: self.additional_headers['Content-Type'] = \ 'text/html; charset=%s' % self.charset + if 'Content-Length' not in self.additional_headers: + self.additional_headers['Content-Length'] = str(len(content)) self.header() if self.env['REQUEST_METHOD'] == 'HEAD': @@ -2479,9 +2541,15 @@ self.write(content) def setHeader(self, header, value): - """Override a header to be returned to the user's browser. + """Override or delete a header to be returned to the user's browser. """ - self.additional_headers[header] = value + if value is None: + try: + del(self.additional_headers[header]) + except KeyError: + pass + else: + self.additional_headers[header] = value def header(self, headers=None, response=None): """Put up the appropriate header. @@ -2497,6 +2565,9 @@ if headers.get('Content-Type', 'text/html') == 'text/html': headers['Content-Type'] = 'text/html; charset=utf-8' + if response in [ 204, 304]: # has no body so no content-type + del(headers['Content-Type']) + headers = list(headers.items()) for ((path, name), (value, expire)) in self._cookies.items():
