Skip to content

Commit

Permalink
Added optional ability to fall back to zope's native file serving - b…
Browse files Browse the repository at this point in the history
…ased on the request header HTTP_X_FORWARDED_FOR
  • Loading branch information
gogobd committed May 18, 2011
1 parent dafbbc4 commit 91a862e
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 15 deletions.
35 changes: 25 additions & 10 deletions collective/xsendfile/configure.zcml
@@ -1,25 +1,40 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:monkey="http://namespaces.plone.org/monkey"
xmlns:five="http://namespaces.zope.org/five">
xmlns:five="http://namespaces.zope.org/five"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
xmlns:i18n="http://namespaces.zope.org/i18n"
i18n_domain="collective.xsendfile"
>

<five:registerPackage package="." initialize=".zope2.initialize" />

<include package="collective.monkeypatcher" />
<!-- Control panel -->
<include package="plone.registry" />
<include package="plone.app.registry" />
<browser:page
name="xsendfile-settings"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
class=".controlpanel.xsendfileSettingsControlPanel"
permission="cmf.ManagePortal"
/>

<!-- Monkey patcher -->
<include package="collective.monkeypatcher" />
<monkey:patch
description="Add support for XSendfile"
class="plone.app.blob.field.BlobField"
original="index_html"
replacement=".utils.index_html"
/>
<!-- monkey:patch
description="Add support for XSendfile"
class="Products.ATContentTypes.content.file.ATFile"
original="index_html"
replacement=".utils.index_html"
/ -->


<genericsetup:registerProfile
name="default"
title="collective.xsendfile installation"
directory="profiles/default"
description="Installs the collective.xsendfile package"
provides="Products.GenericSetup.interfaces.EXTENSION"
/>

</configure>
7 changes: 7 additions & 0 deletions collective/xsendfile/interfaces.py
Expand Up @@ -23,6 +23,13 @@ class IxsendfileSettings(Interface):
required=False,
)

xsendfile_enable_fallback = schema.Bool(
title=_(u"Enable fallback based on HTTP_X_FORWARDED_FOR proxy header"),
description=_(u"Check if REQUEST header contains HTTP_X_FORWARDED_FOR and re-enable fallback (zope) file delivery if no proxy is detected."),
default=True,
required=False,
)

xsendfile_pathregex_search = schema.TextLine(
title=_(u"Blob-path rewriting regex"),
description=_(u"This regex will be used to modify the files path, in case you are using a different mountpoint on the xsendfile Server. If you are using nginx you have to prepend the id of the location you configured."),
Expand Down
30 changes: 25 additions & 5 deletions collective/xsendfile/utils.py
Expand Up @@ -4,11 +4,17 @@
from Products.Archetypes.utils import contentDispositionHeader
from plone.i18n.normalizer.interfaces import IUserPreferredFileNameNormalizer
import logging
from zope.component import getUtility
from plone.registry.interfaces import IRegistry
from collective.xsendfile.interfaces import IxsendfileSettings
import re

def index_html(self, instance=None, REQUEST=None, RESPONSE=None, disposition='inline'):
""" Inject X-Sendfile and X-Accel-Redirect headers into response. """

logger = logging.getLogger('collective.xsendfile')
registry = getUtility(IRegistry)
settings = registry.forInterface(IxsendfileSettings)

if REQUEST is None:
REQUEST = instance.REQUEST
Expand All @@ -29,15 +35,29 @@ def index_html(self, instance=None, REQUEST=None, RESPONSE=None, disposition='in
file_path = blob_file.name
blob_file.close()

responseheader = settings.xsendfile_responseheader
pathregex_search = settings.xsendfile_pathregex_search
pathregex_substitute = settings.xsendfile_pathregex_substitute
enable_fallback = settings.xsendfile_enable_fallback

if responseheader and pathregex_substitute:
file_path = re.sub(pathregex_search,pathregex_substitute,file_path)

RESPONSE.setHeader('Last-Modified', rfc1123_date(instance._p_mtime))
RESPONSE.setHeader("Content-Length", blob.get_size())
RESPONSE.setHeader('Content-Type', self.getContentType(instance))

if REQUEST.get('HTTP_X_FORWARDED_FOR') == '':
fallback = False
if not responseheader:
fallback = True
if enable_fallback:
if (not REQUEST.get('HTTP_X_FORWARDED_FOR')):
fallback = True

if fallback:
logger.log(logging.WARNING, "Falling back to sending object %s.%s via Zope - no HTTP_X_FORWARDED_FOR header found."%(repr(instance),repr(self), ))
return zodb_blob.open().read()
else:
logger.log(logging.INFO, "Sending object %s.%s with xsendfile headers, path: %s"%(repr(instance),repr(self), repr(file_path)))
RESPONSE.setHeader("X-Accel-Redirect", "/xsendfile"+file_path)
RESPONSE.setHeader("X-Sendfile", file_path )
return file_path
logger.log(logging.INFO, "Sending object %s.%s with xsendfile header %s, path: %s"%(repr(instance), repr(self), repr(responseheader), repr(file_path)))
RESPONSE.setHeader(responseheader, file_path)
return "collective.xsendfile - proxy missing?"
4 changes: 4 additions & 0 deletions setup.py
Expand Up @@ -26,6 +26,10 @@
'setuptools',
# -*- Extra requirements: -*-
'collective.monkeypatcher',
'plone.app.registry',
'plone.registry',
'ore.bigfile',
'z3c.form',
],
entry_points="""
# -*- Entry points: -*-
Expand Down

0 comments on commit 91a862e

Please sign in to comment.