Skip to content

Instantly share code, notes, and snippets.

@ninapavlich
Created July 29, 2016 17:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ninapavlich/b299b8ea1320ec4a4ad8d8f65ad9f079 to your computer and use it in GitHub Desktop.
Save ninapavlich/b299b8ea1320ec4a4ad8d8f65ad9f079 to your computer and use it in GitHub Desktop.
Optimized proxy view for Django
from django.conf import settings
from django.conf.urls import patterns, url, include
from django.conf.urls import patterns
from django.views.decorators.csrf import csrf_exempt
from .views cached_api_proxy_view
urlpatterns = patterns('')
urlpatterns += patterns('',
url('proxy/(?P<path>.*)', csrf_exempt(cached_api_proxy_view)),
)
from django.conf import settings
from django.core.cache import cache
from django.core.urlresolvers import resolve
#NOTE -- this requires django-proxy==1.0.2
from proxy.views import proxy_view
def cached_api_proxy_view(request, path):
"""
This function handles caching logic for the proxy
"""
cache_eligible = is_proxy_cache_eligible(request, path)
if cache_eligible:
cachekey = get_proxy_cache_key(request, path)
response = cache.get( cachekey )
if not response:
response = api_proxy_view(request, path)
"""
Only cache it if it was successful, no one wants broken things
"""
if( response.status_code == 200 ):
cache.set( cachekey, response, get_proxy_cache_duration(request, path) )
else:
response = api_proxy_view(request, path)
return response
def api_proxy_view(request, path):
"""
This function handles executing the actual proxy
"""
if is_internal_view(request, path):
view, args, kwargs = resolve("/"+path)
kwargs['request'] = request
request.GET = request.GET.copy()
request.GET.update(get_extra_params(request, path))
return view(*args, **kwargs)
else:
extra_requests_args = {
'params':get_extra_params(request, path)
}
return proxy_view(request, get_remote_url(request, path), extra_requests_args)
def is_proxy_cache_eligible(request, path):
#Override this logic!
"""
Typically we don't want to cache a POST method, but there may be other
custom view you don't want to cache either.
"""
if request.method == "GET":
return True
else:
return False
def get_proxy_cache_key(request, path):
#Override this logic!
"""
If GET variables return custom content, then include them in the cache key:
"""
full_path = "%s?%s"%(path, request.GET.urlencode())
"""
If users get user-specific content, then you can include the user's session
key in the cache key. This obviously creates a lot more cache entries, so
use carefully.
"""
return 'proxy-view-%s-for-%s'%(full_path, request.session._session_key)
def get_extra_params(request, path):
#Override this logic!
if request.user.is_authenticated():
username = request.user.username
return {
"api_key" : request.user.api_key.key,
"username" : request.user.username
}
else:
return {}
def is_internal_view(request, path):
#Override this logic!
return True
def get_remote_url(request, path):
#Override this logic!
return settings.PROXY_HOST+'/'+path
def get_proxy_cache_duration(request, path):
#Override this logic!
return settings.CACHE_API_SECONDS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment