From cc254c309b9950d2c76347e7fefbab0d1efa55f8 Mon Sep 17 00:00:00 2001 From: Nejc Zupan Date: Mon, 9 Apr 2018 12:52:49 +0100 Subject: [PATCH] Add support for setting cgi-environment vars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed so that we are able to tell Plone to run in HTTPS mode on PaaS providers such as Heroku. Currently, it is achieved with the following Ugly Hackā„¢: https://github.com/plone/heroku-buildpack-plone/blob/f22284cef9d790970d309c8c4591441d24b961ec/configure_zopeconf.py#L22 --- CHANGES.rst | 3 ++ README.rst | 7 +++ src/plone/recipe/zope2instance/__init__.py | 47 +++++++++++++------ .../zope2instance/tests/zope2instance.txt | 38 +++++++++++++++ 4 files changed, 80 insertions(+), 15 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 5860b5d0..8a6c7282 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -13,6 +13,9 @@ New features: - Added support for setting `instance-home` option. [zupo] +- Added support for setting CGI environment variables. + [zupo] + Bug fixes: - *add item here* diff --git a/README.rst b/README.rst index 7157e812..d2f08a19 100644 --- a/README.rst +++ b/README.rst @@ -74,6 +74,13 @@ environment-vars zope_i18n_allowed_languages en zope_i18n_compile_mo_files true +cgi-environment-vars + Define arbitrary key-value pairs for use as CGI environment variables during + Zope's run cycle. Example:: + + cgi-environment-vars = + HTTPS ON + initialization Specify some Python initialization code to include within the generated ``sitecustomize.py`` script (Buildout >= 1.5) or within the instance script diff --git a/src/plone/recipe/zope2instance/__init__.py b/src/plone/recipe/zope2instance/__init__.py index 8bac02ee..62ad36c7 100644 --- a/src/plone/recipe/zope2instance/__init__.py +++ b/src/plone/recipe/zope2instance/__init__.py @@ -40,6 +40,24 @@ def indent(snippet, amount): return "\n".join(ws + s if s else "" for s in snippet.split('\n')) +def handle_singleline_env_vars(vars_): + # if the vars are all given on one line we need to do some work + if not '\n' in vars_: + keys = [] + values = [] + env_vars = vars_.split() + # split out the odd and even items into keys, values + for var in env_vars: + if divmod(env_vars.index(var) + 1, 2)[1]: + keys.append(var) + else: + values.append(var) + env_vars = zip(keys, values) + return '\n'.join( + ["%s %s" % (env_var[0], env_var[1]) for env_var in env_vars]) + return vars_ + + class Recipe(Scripts): def __init__(self, buildout, name, options): @@ -229,21 +247,12 @@ def build_zope_conf(self): ip_address = 'ip-address %s' % ip_address environment_vars = options.get('environment-vars', '') if environment_vars: - # if the vars are all given on one line we need to do some work - if not '\n' in environment_vars: - keys = [] - values = [] - env_vars = environment_vars.split() - # split out the odd and even items into keys, values - for var in env_vars: - if divmod(env_vars.index(var) + 1, 2)[1]: - keys.append(var) - else: - values.append(var) - env_vars = zip(keys, values) - environment_vars = '\n'.join(["%s %s" % (env_var[0], env_var[1]) - for env_var in env_vars]) - environment_vars = environment_template % environment_vars + environment_vars = environment_template % \ + handle_singleline_env_vars(environment_vars) + cgi_environment_vars = options.get('cgi-environment-vars', '') + if cgi_environment_vars: + cgi_environment_vars = cgi_environment_template % \ + handle_singleline_env_vars(cgi_environment_vars) deprecation_warnings = options.get('deprecation-warnings', '') if deprecation_warnings: @@ -593,6 +602,7 @@ def is_rs_option(name): pid_file = pid_file, lock_file = lock_file, environment_vars = environment_vars, + cgi_environment_vars = cgi_environment_vars, deprecation_warnings = deprecation_warnings, python_check_interval = python_check_interval, enable_products = enable_products, @@ -990,6 +1000,12 @@ def render_file_storage(self, file_storage, blob_storage, """ +cgi_environment_template = """ + + %s + +""" + # The template used to build zope.conf zope_conf_template="""\ %(imports_lines)s @@ -1009,6 +1025,7 @@ def render_file_storage(self, file_storage, blob_storage, %(ip_address)s %(zserver_threads)s %(environment_vars)s +%(cgi_environment_vars)s %(deprecation_warnings)s %(mailinglogger_import)s diff --git a/src/plone/recipe/zope2instance/tests/zope2instance.txt b/src/plone/recipe/zope2instance/tests/zope2instance.txt index d4296310..adb35207 100644 --- a/src/plone/recipe/zope2instance/tests/zope2instance.txt +++ b/src/plone/recipe/zope2instance/tests/zope2instance.txt @@ -1788,6 +1788,44 @@ Our environment variables should be set now:: >>> re.search(env_vars, zope_conf).group('vars') 'TZ US/Eastern\nTMP /var/tmp\nDISABLE_PTS True' +We can also specify CGI environment variables for Zope. This comes handy when +hosting on PaaS providers, such as Heroku, where we don't have a reverse-proxy +in front of Zope. For example, we can configure Zope to run in HTTPS mode:: + + >>> write('buildout.cfg', + ... ''' + ... [buildout] + ... parts = instance + ... find-links = %(sample_buildout)s/eggs + ... + ... [instance] + ... recipe = plone.recipe.zope2instance + ... eggs = + ... user = me:me + ... cgi-environment-vars = HTTPS ON + ... ''' % options) + +Let's run it:: + + >>> print system(join('bin', 'buildout')), + Uninstalling instance. + Installing instance. + Generated script '...instance'. + Generated interpreter '.../parts/instance/bin/interpreter'. + ... + +Our CGI environment variables should be set now:: + + >>> instance = os.path.join(sample_buildout, 'parts', 'instance') + >>> zope_conf = open(os.path.join(instance, 'etc', 'zope.conf')).read() + >>> zope_conf = zope_conf.replace('\\', '/') + >>> print zope_conf + %define INSTANCEHOME .../sample-buildout/parts/instance + ... + + HTTPS ON + + ... HTTP server ===========