[FIX] website: move support for ir.attachment resources to web module

Commit 540b753bf8 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
This commit is contained in:
FalcoBolger 2015-03-26 11:44:01 +01:00 committed by Olivier Dony
parent c58121e8f1
commit 95b921d0f7
2 changed files with 39 additions and 34 deletions

View File

@ -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

View File

@ -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)