0
0
mirror of https://github.com/wagtail/wagtail.git synced 2024-11-24 01:57:32 +01:00

Update the Cloudflare backend to use the v4 API

Fixes #3146
This commit is contained in:
Albert O'Connor 2016-11-08 14:23:35 -05:00 committed by Matt Westcott
parent 4dbf230d04
commit a5b544631b
7 changed files with 67 additions and 17 deletions

View File

@ -15,6 +15,7 @@ Changelog
* `PageChooserBlock` now accepts a `target_model` option to specify the required page type (Tim Heap)
* Modeladmin forms now respect `fields` / `exclude` options passed on custom model forms (Thejaswi Puthraya)
* Added new StreamField block type `StaticBlock` (Benoît Vogel)
* Updated Cloudflare cache module to use the v4 API (Albert O'Connor)
* Fix: `AbstractForm` now respects custom `get_template` methods on the page model (Gagaro)
* Fix: Use specific page model for the parent page in the explore index (Gagaro)
* Fix: Remove responsive styles in embed when there is no ratio available (Gagaro)

View File

@ -184,6 +184,7 @@ Contributors
* Thejaswi Puthraya
* Benoît Vogel
* Manuel E. Gutierrez
* Albert O'Connor
Translators
===========

View File

@ -60,12 +60,17 @@ Finally, make sure you have configured your frontend cache to accept PURGE reque
- `Squid <http://wiki.squid-cache.org/SquidFaq/OperatingSquid#How_can_I_purge_an_object_from_my_cache.3F>`_
.. _frontendcache_cloudflare:
Cloudflare
^^^^^^^^^^
Firstly, you need to register an account with Cloudflare if you haven't already got one. You can do this here: `Cloudflare Sign up <https://www.cloudflare.com/sign-up>`_
Add an item into the ``WAGTAILFRONTENDCACHE`` and set the ``BACKEND`` parameter to ``wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend``. This backend requires two extra parameters, ``EMAIL`` (your Cloudflare account email) and ``TOKEN`` (your API token from Cloudflare).
Add an item into the ``WAGTAILFRONTENDCACHE`` and set the ``BACKEND`` parameter to ``wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend``. This backend requires three extra parameters, ``EMAIL`` (your Cloudflare account email), ``TOKEN`` (your API token from Cloudflare), and ``ZONEID`` (for zone id for your domain, see below).
To find the ``ZONEID`` for your domain, read the `Cloudflare API Documentation <https://api.cloudflare.com/#getting-started-resource-ids>`_
.. code-block:: python
@ -76,6 +81,7 @@ Add an item into the ``WAGTAILFRONTENDCACHE`` and set the ``BACKEND`` parameter
'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend',
'EMAIL': 'your-cloudflare-email-address@example.com',
'TOKEN': 'your cloudflare api token',
'ZONEID': 'your cloudflare domain zone id',
},
}

View File

@ -41,6 +41,7 @@ Minor features
* ``PageChooserBlock`` now accepts a ``target_model`` option to specify the required page type (Tim Heap)
* Modeladmin forms now respect ``fields`` / ``exclude`` options passed on custom model forms (Thejaswi Puthraya)
* Added new StreamField block type ``StaticBlock`` for blocks that occupy a position in a stream but otherwise have no configuration; see :ref:`streamfield_staticblock` (Benoît Vogel)
* Updated Cloudflare cache module to use the v4 API (Albert O'Connor)
Bug fixes
@ -103,3 +104,22 @@ As a precaution against accidental data loss, this release introduces a new "bul
operations = [
migrations.RunPython(add_bulk_delete_permission, remove_bulk_delete_permission),
]
Cloudflare cache module now requires a ``ZONEID`` setting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend`` module has been updated to use Cloudflare's v4 API, replacing the previous v1 implementation (which is `unsupported as of November 9th, 2016 <https://www.cloudflare.com/docs/client-api/>`_). The new API requires users to supply a *zone identifier*, which should be passed as the ``ZONEID`` field of the ``WAGTAILFRONTENDCACHE`` setting:
.. code-block:: python
WAGTAILFRONTENDCACHE = {
'cloudflare': {
'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend',
'EMAIL': 'your-cloudflare-email-address@example.com',
'TOKEN': 'your cloudflare api token',
'ZONEID': 'your cloudflare domain zone id',
},
}
For details of how to obtain the zone identifier, see `the Cloudflare API documentation <https://api.cloudflare.com/#getting-started-resource-ids>`_.

View File

@ -31,6 +31,7 @@ install_requires = [
"html5lib>=0.999,<1",
"Unidecode>=0.04.14",
"Willow>=0.4,<0.5",
"requests>=2.11.1,<3.0",
]
# Testing dependencies

View File

@ -1,12 +1,12 @@
from __future__ import absolute_import, unicode_literals
import json
import logging
import uuid
import requests
from django.core.exceptions import ImproperlyConfigured
from django.utils.six.moves.urllib.error import HTTPError, URLError
from django.utils.six.moves.urllib.parse import urlencode, urlparse, urlunparse
from django.utils.six.moves.urllib.parse import urlparse, urlunparse
from django.utils.six.moves.urllib.request import Request, urlopen
from wagtail import __version__
@ -65,26 +65,44 @@ class CloudflareBackend(BaseBackend):
def __init__(self, params):
self.cloudflare_email = params.pop('EMAIL')
self.cloudflare_token = params.pop('TOKEN')
self.cloudflare_zoneid = params.pop('ZONEID')
def purge(self, url):
try:
response = urlopen('https://www.cloudflare.com/api_json.html', data=urlencode({
'email': self.cloudflare_email,
'tkn': self.cloudflare_token,
'a': 'zone_file_purge',
'z': urlparse(url).netloc,
'url': url
}).encode('utf-8'))
except HTTPError as e:
logger.error("Couldn't purge '%s' from Cloudflare. HTTPError: %d %s", url, e.code, e.reason)
purge_url = 'https://api.cloudflare.com/client/v4/zones/{0}/purge_cache'.format(self.cloudflare_zoneid)
headers = {
"X-Auth-Email": self.cloudflare_email,
"X-Auth-Key": self.cloudflare_token,
"Content-Type": "application/json",
}
data = {"files": [url]}
response = requests.delete(
purge_url,
json=data,
headers=headers,
)
try:
response_json = response.json()
except ValueError:
if response.status_code != 200:
response.raise_for_status()
else:
logger.error("Couldn't purge '%s' from Cloudflare. Unexpected JSON parse error.", url)
except requests.exceptions.HTTPError as e:
logger.error("Couldn't purge '%s' from Cloudflare. HTTPError: %d %s", url, e.response.status_code, e.message)
return
except URLError as e:
logger.error("Couldn't purge '%s' from Cloudflare. URLError: %s", url, e.reason)
except requests.exceptions.InvalidURL as e:
logger.error("Couldn't purge '%s' from Cloudflare. URLError: %s", url, e.message)
return
response_json = json.loads(response.read().decode('utf-8'))
if response_json['result'] == 'error':
logger.error("Couldn't purge '%s' from Cloudflare. Cloudflare error '%s'", url, response_json['msg'])
if response_json['success'] is False:
error_messages = ', '.join([err['message'] for err in response_json['errors']])
logger.error("Couldn't purge '%s' from Cloudflare. Cloudflare errors '%s'", url, error_messages)
return

View File

@ -39,6 +39,7 @@ class TestBackendConfiguration(TestCase):
'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend',
'EMAIL': 'test@test.com',
'TOKEN': 'this is the token',
'ZONEID': 'this is a zone id',
},
})
@ -94,6 +95,7 @@ class TestBackendConfiguration(TestCase):
'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend',
'EMAIL': 'test@test.com',
'TOKEN': 'this is the token',
'ZONEID': 'this is a zone id',
}
})
@ -109,6 +111,7 @@ class TestBackendConfiguration(TestCase):
'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend',
'EMAIL': 'test@test.com',
'TOKEN': 'this is the token',
'ZONEID': 'this is a zone id',
}
}, backends=['cloudflare'])