kopia lustrzana https://github.com/wagtail/wagtail
Merge branch 'kaedroho-frontendcache-without-requests'
commit
bc9c7f3f01
|
@ -30,6 +30,7 @@ Changelog
|
|||
* Fix: H2 elements in rich text fields were accidentally given a click() binding when put insite a collapsible multi field panel
|
||||
* Fix: The wagtailimages module is now compatible with remote storage backends that do not allow reopening closed files
|
||||
* Fix: Search no longer crashes when auto-indexing a model that doesn't have an id field (Scot Hacker)
|
||||
* Fix: The `wagtailfrontendcache` module's HTTP backend has been rewritten to reliably direct requests to the configured cache hostname
|
||||
|
||||
|
||||
1.0 (16.07.2015)
|
||||
|
|
|
@ -66,6 +66,7 @@ Bug fixes
|
|||
* H2 elements in rich text fields were accidentally given a click() binding when put insite a collapsible multi field panel
|
||||
* The ``wagtailimages`` module is now compatible with remote storage backends that do not allow reopening closed files
|
||||
* Search no longer crashes when auto-indexing a model that doesn't have an ``id`` field
|
||||
* The ``wagtailfrontendcache`` module's HTTP backend has been rewritten to reliably direct requests to the configured cache hostname
|
||||
|
||||
|
||||
Upgrade considerations
|
||||
|
|
1
setup.py
1
setup.py
|
@ -33,7 +33,6 @@ install_requires = [
|
|||
"beautifulsoup4>=4.3.2",
|
||||
"html5lib==0.999",
|
||||
"Unidecode>=0.04.14",
|
||||
'requests>=2.0.0',
|
||||
"Willow==0.2.1",
|
||||
]
|
||||
|
||||
|
|
1
tox.ini
1
tox.ini
|
@ -28,7 +28,6 @@ deps =
|
|||
html5lib==0.999
|
||||
Unidecode>=0.04.14
|
||||
six==1.7.3
|
||||
requests==2.3.0
|
||||
elasticsearch==1.1.0
|
||||
mock==1.0.1
|
||||
python-dateutil==2.2
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import logging
|
||||
import requests
|
||||
import json
|
||||
|
||||
from django.utils.six.moves.urllib.parse import urlparse
|
||||
from django.utils.six.moves.urllib.parse import urlparse, urlunparse, urlencode
|
||||
from django.utils.six.moves.urllib.request import Request, urlopen
|
||||
from django.utils.six.moves.urllib.error import URLError, HTTPError
|
||||
|
||||
from requests.adapters import HTTPAdapter
|
||||
from wagtail.wagtailcore import __version__
|
||||
|
||||
|
||||
logger = logging.getLogger('wagtail.frontendcache')
|
||||
|
@ -15,44 +17,41 @@ class BaseBackend(object):
|
|||
|
||||
|
||||
class HTTPBackend(BaseBackend):
|
||||
|
||||
class CustomHTTPAdapter(HTTPAdapter):
|
||||
"""
|
||||
Requests will always send requests to whatever server is in the netloc
|
||||
part of the URL. This is a problem with purging the cache as this netloc
|
||||
may point to a different server (such as an nginx instance running in
|
||||
front of the cache).
|
||||
|
||||
This class allows us to send a purge request directly to the cache server
|
||||
with the host header still set correctly. It does this by changing the "url"
|
||||
parameter of get_connection to always point to the cache server. Requests
|
||||
will then use this connection to purge the page.
|
||||
"""
|
||||
def __init__(self, cache_url):
|
||||
self.cache_url = cache_url
|
||||
super(HTTPBackend.CustomHTTPAdapter, self).__init__()
|
||||
|
||||
def get_connection(self, url, proxies=None):
|
||||
return super(HTTPBackend.CustomHTTPAdapter, self).get_connection(self.cache_url, proxies)
|
||||
|
||||
|
||||
def __init__(self, params):
|
||||
self.cache_location = params.pop('LOCATION')
|
||||
|
||||
self.session = requests.Session()
|
||||
self.session.mount('http://', self.CustomHTTPAdapter(self.cache_location))
|
||||
location_url_parsed = urlparse(params.pop('LOCATION'))
|
||||
self.cache_scheme = location_url_parsed.scheme
|
||||
self.cache_netloc = location_url_parsed.netloc
|
||||
|
||||
def purge(self, url):
|
||||
try:
|
||||
response = self.session.request('PURGE', url)
|
||||
except requests.ConnectionError:
|
||||
logger.error("Couldn't purge '%s' from HTTP cache: Connection error", url)
|
||||
return
|
||||
url_parsed = urlparse(url)
|
||||
host = url_parsed.hostname
|
||||
|
||||
# Check for error
|
||||
if response.status_code != 200:
|
||||
logger.error("Couldn't purge '%s' from HTTP cache: Didn't recieve a 200 response (instead, we got '%d %s')", url, response.status_code, response.reason)
|
||||
return
|
||||
# Append port to host if it is set in the original URL
|
||||
if url_parsed.port:
|
||||
host += (':' + str(url_parsed.port))
|
||||
|
||||
request = Request(
|
||||
url=urlunparse([
|
||||
self.cache_scheme,
|
||||
self.cache_netloc,
|
||||
url_parsed.path,
|
||||
url_parsed.params,
|
||||
url_parsed.query,
|
||||
url_parsed.fragment
|
||||
]),
|
||||
headers={
|
||||
'Host': host,
|
||||
'User-Agent': 'Wagtail-frontendcache/' + __version__
|
||||
},
|
||||
method='PURGE'
|
||||
)
|
||||
|
||||
try:
|
||||
urlopen(request)
|
||||
except HTTPError as e:
|
||||
logger.error("Couldn't purge '%s' from HTTP cache. HTTPError: %d %s", url, e.code, e.reason)
|
||||
except URLError as e:
|
||||
logger.error("Couldn't purge '%s' from HTTP cache. URLError: %s", url, e.reason)
|
||||
|
||||
|
||||
class CloudflareBackend(BaseBackend):
|
||||
|
@ -62,23 +61,21 @@ class CloudflareBackend(BaseBackend):
|
|||
|
||||
def purge(self, url):
|
||||
try:
|
||||
response = requests.post('https://www.cloudflare.com/api_json.html', {
|
||||
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
|
||||
})
|
||||
except requests.ConnectionError:
|
||||
logger.error("Couldn't purge '%s' from Cloudflare: Connection error", url)
|
||||
}).encode('utf-8'))
|
||||
except HTTPError as e:
|
||||
logger.error("Couldn't purge '%s' from Cloudflare. HTTPError: %d %s", url, e.code, e.reason)
|
||||
return
|
||||
except URLError as e:
|
||||
logger.error("Couldn't purge '%s' from Cloudflare. URLError: %s", url, e.reason)
|
||||
return
|
||||
|
||||
# Check for error
|
||||
if response.status_code != 200:
|
||||
logger.error("Couldn't purge '%s' from Cloudflare: Didn't recieve a 200 response (instead, we got '%d %s')", url, response.status_code, response.reason)
|
||||
return
|
||||
|
||||
response_json = response.json()
|
||||
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'])
|
||||
logger.error("Couldn't purge '%s' from Cloudflare. Cloudflare error '%s'", url, response_json['msg'])
|
||||
return
|
||||
|
|
|
@ -25,7 +25,8 @@ class TestBackendConfiguration(TestCase):
|
|||
self.assertEqual(set(backends.keys()), set(['varnish']))
|
||||
self.assertIsInstance(backends['varnish'], HTTPBackend)
|
||||
|
||||
self.assertEqual(backends['varnish'].cache_location, 'http://localhost:8000')
|
||||
self.assertEqual(backends['varnish'].cache_scheme, 'http')
|
||||
self.assertEqual(backends['varnish'].cache_netloc, 'localhost:8000')
|
||||
|
||||
def test_cloudflare(self):
|
||||
backends = get_backends(backend_settings={
|
||||
|
@ -78,7 +79,8 @@ class TestBackendConfiguration(TestCase):
|
|||
|
||||
self.assertEqual(set(backends.keys()), set(['default']))
|
||||
self.assertIsInstance(backends['default'], HTTPBackend)
|
||||
self.assertEqual(backends['default'].cache_location, 'http://localhost:8000')
|
||||
self.assertEqual(backends['default'].cache_scheme, 'http')
|
||||
self.assertEqual(backends['default'].cache_netloc, 'localhost:8000')
|
||||
|
||||
|
||||
PURGED_URLS = []
|
||||
|
|
Ładowanie…
Reference in New Issue