Skip to content

Instantly share code, notes, and snippets.

@andrewebdev
Created June 12, 2014 19:03
Show Gist options
  • Save andrewebdev/1193efbf7cc9b870133b to your computer and use it in GitHub Desktop.
Save andrewebdev/1193efbf7cc9b870133b to your computer and use it in GitHub Desktop.
import os
import base64
from subprocess import call
from django import http
from django.conf import settings
from django_seo_js.backends import SEOBackendBase
SITE_CONF = getattr(settings, 'SITE_CONF')
BASE_URL = "%s%s" % (SITE_CONF['protocol'], SITE_CONF['domain'])
SNAPSHOTS_DIR = getattr(settings, 'SNAPSHOTS_DIR')
PHANTOM_RUNNER = os.path.join(os.path.dirname(__file__), 'phantom-runner.js')
## Backends
class PhantomJSBackend(SEOBackendBase):
"""
A custom backend for django-seo-js that will use phantomjs to
render the page, and store it in a predefined location.
"""
def get_response_for_url(self, url):
"""
Accepts a fully-qualified url.
Returns an HttpResponse, passing through all headers and the status code.
"""
if not url or "//" not in url:
raise ValueError("Missing or invalid url: %s" % url)
fragment = url.split('_escaped_fragment_=')[1]
return self.render_phantomjs_response(fragment)
def update_url(self, url):
"""
Force an update of the cache for a particular URL.
Returns True on success, False on fail.
"""
self._get_or_create_snapshot(url, force_update=True)
return True
def _get_fragment_hash(self, fragment):
return base64.urlsafe_b64encode(fragment)
def _get_or_create_snapshot(self, fragment, force_update=False):
"""
Generate and cache the html for URL using phantomjs.
"""
outfile = os.path.join(
SNAPSHOTS_DIR, "%s.html" % self._get_fragment_hash(fragment))
url = "%s/#\!%s" % (BASE_URL, fragment) # note we are escaping the '!'
if not os.path.exists(outfile) or force_update:
phantom_cmd = 'phantomjs %s %s > %s' % (PHANTOM_RUNNER, url, outfile)
call(phantom_cmd, shell=True)
return outfile
def render_phantomjs_response(self, fragment):
"""
Tries to return the requested snapshot. If it does not exist,
generate it first, save it, then return it.
"""
snapshot_file = self._get_or_create_snapshot(fragment)
snapshot_content = open(snapshot_file, 'rb').read()
return http.HttpResponse(snapshot_content, content_type="text/html")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment