From 95b921d0f7cffd3b2546db8949f3c30b2b120335 Mon Sep 17 00:00:00 2001 From: FalcoBolger Date: Thu, 26 Mar 2015 11:44:01 +0100 Subject: [PATCH] [FIX] website: move support for ir.attachment resources to web module Commit 540b753bf84f118b6863bac699f52c2c418a7f30 introduced support for resources stored as ir.attachment records in asset bundles too. This is specifically useful for customizations. However the HTTP route for reaching those resources when they are *not* in a bundle was originally created in the `website` module (as a special handling for 404 requests) This means that these dynamic resources would only be partially supported when `website` is not installed, causing various problems: - missing resources in debug mode where bundles are skipped - errors when trying to define new client-side Qweb templates via XML resources - which are loaded with a direct request - ... This commit moves back the supporting code to the web module. The `mimetype` column is not present in ir.attachment without the `website` module, but sniffing it based on the attachment name works fine at serving time too. Closes #6002 --- addons/website/models/ir_http.py | 35 +--------------------------- openerp/addons/base/ir/ir_http.py | 38 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 7da212998c8..c45a203f4da 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -import datetime -import hashlib import logging import os import re @@ -76,7 +74,7 @@ class ir_http(orm.AbstractModel): if self.geo_ip_resolver and request.httprequest.remote_addr: record = self.geo_ip_resolver.record_by_addr(request.httprequest.remote_addr) or {} request.session['geoip'] = record - + if request.website_enabled: try: if func: @@ -163,38 +161,7 @@ class ir_http(orm.AbstractModel): path += '?' + request.httprequest.query_string return werkzeug.utils.redirect(path, code=301) - def _serve_attachment(self): - domain = [('type', '=', 'binary'), ('url', '=', request.httprequest.path)] - attach = self.pool['ir.attachment'].search_read(request.cr, openerp.SUPERUSER_ID, domain, ['__last_update', 'datas', 'mimetype'], context=request.context) - if attach: - wdate = attach[0]['__last_update'] - datas = attach[0]['datas'] - response = werkzeug.wrappers.Response() - server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT - try: - response.last_modified = datetime.datetime.strptime(wdate, server_format + '.%f') - except ValueError: - # just in case we have a timestamp without microseconds - response.last_modified = datetime.datetime.strptime(wdate, server_format) - - response.set_etag(hashlib.sha1(datas).hexdigest()) - response.make_conditional(request.httprequest) - - if response.status_code == 304: - return response - - response.mimetype = attach[0]['mimetype'] or 'application/octet-stream' - response.data = datas.decode('base64') - return response - def _handle_exception(self, exception, code=500): - # This is done first as the attachment path may - # not match any HTTP controller, so the request - # may not be website-enabled. - attach = self._serve_attachment() - if attach: - return attach - is_website_request = bool(getattr(request, 'website_enabled', False) and request.website) if not is_website_request: # Don't touch non website requests exception handling diff --git a/openerp/addons/base/ir/ir_http.py b/openerp/addons/base/ir/ir_http.py index 8c4f8bed82b..0c82d4f1cfd 100644 --- a/openerp/addons/base/ir/ir_http.py +++ b/openerp/addons/base/ir/ir_http.py @@ -1,10 +1,14 @@ #---------------------------------------------------------- # ir_http modular http routing #---------------------------------------------------------- +import datetime +import hashlib import logging +import mimetypes import re import sys +import werkzeug import werkzeug.exceptions import werkzeug.routing import werkzeug.urls @@ -94,7 +98,41 @@ class ir_http(osv.AbstractModel): raise openerp.exceptions.AccessDenied() return auth_method + def _serve_attachment(self): + domain = [('type', '=', 'binary'), ('url', '=', request.httprequest.path)] + attach = self.pool['ir.attachment'].search_read( + request.cr, openerp.SUPERUSER_ID, domain, + ['__last_update', 'datas', 'datas_fname'], + context=request.context) + if attach: + wdate = attach[0]['__last_update'] + datas = attach[0]['datas'] + response = werkzeug.wrappers.Response() + server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT + try: + response.last_modified = datetime.datetime.strptime(wdate, server_format + '.%f') + except ValueError: + # just in case we have a timestamp without microseconds + response.last_modified = datetime.datetime.strptime(wdate, server_format) + + response.set_etag(hashlib.sha1(datas).hexdigest()) + response.make_conditional(request.httprequest) + + if response.status_code == 304: + return response + + response.mimetype = (mimetypes.guess_type(attach[0]['datas_fname'])[0] or + 'application/octet-stream') + response.data = datas.decode('base64') + return response + def _handle_exception(self, exception): + # This is done first as the attachment path may + # not match any HTTP controller. + attach = self._serve_attachment() + if attach: + return attach + # If handle_exception returns something different than None, it will be used as a response try: return request._handle_exception(exception)