blob: 126daf9cbac3c56cca551108c4fd48d827f20a80 [file] [log] [blame]
# Copyright (c) The PyAMF Project.
# See LICENSE.txt for details.
"""
Gateway for the Django framework.
This gateway allows you to expose functions in Django to AMF clients and
servers.
@see: U{Django homepage<http://djangoproject.com>}
@since: 0.1.0
"""
django = __import__('django.http')
http = django.http
conf = __import__('django.conf')
conf = conf.conf
import pyamf
from pyamf import remoting
from pyamf.remoting import gateway
__all__ = ['DjangoGateway']
class DjangoGateway(gateway.BaseGateway):
"""
An instance of this class is suitable as a Django view.
An example usage would be through C{urlconf}::
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^gateway/', 'yourproject.yourapp.gateway.gw_instance'),
)
where C{yourproject.yourapp.gateway.gw_instance} refers to an instance of
this class.
@ivar expose_request: The standard Django view always has the request
object as the first parameter. To disable this functionality, set this
to C{False}.
"""
csrf_exempt = True
def __init__(self, *args, **kwargs):
kwargs['expose_request'] = kwargs.get('expose_request', True)
try:
tz = conf.settings.AMF_TIME_OFFSET
except AttributeError:
tz = None
try:
debug = conf.settings.DEBUG
except AttributeError:
debug = False
kwargs['timezone_offset'] = kwargs.get('timezone_offset', tz)
kwargs['debug'] = kwargs.get('debug', debug)
gateway.BaseGateway.__init__(self, *args, **kwargs)
def getResponse(self, http_request, request):
"""
Processes the AMF request, returning an AMF response.
@param http_request: The underlying HTTP Request.
@type http_request: U{HTTPRequest<http://docs.djangoproject.com
/en/dev/ref/request-response/#httprequest-objects>}
@param request: The AMF Request.
@type request: L{Envelope<pyamf.remoting.Envelope>}
@rtype: L{Envelope<pyamf.remoting.Envelope>}
"""
response = remoting.Envelope(request.amfVersion)
for name, message in request:
http_request.amf_request = message
processor = self.getProcessor(message)
response[name] = processor(message, http_request=http_request)
return response
def __call__(self, http_request):
"""
Processes and dispatches the request.
"""
if http_request.method != 'POST':
return http.HttpResponseNotAllowed(['POST'])
stream = None
timezone_offset = self._get_timezone_offset()
# Decode the request
try:
request = remoting.decode(http_request.raw_post_data,
strict=self.strict, logger=self.logger,
timezone_offset=timezone_offset)
except (pyamf.DecodeError, IOError):
if self.logger:
self.logger.exception('Error decoding AMF request')
response = ("400 Bad Request\n\nThe request body was unable to "
"be successfully decoded.")
if self.debug:
response += "\n\nTraceback:\n\n%s" % gateway.format_exception()
# support for Django 0.96
http_response = http.HttpResponse(mimetype='text/plain',
content=response)
http_response.status_code = 400
return http_response
except (KeyboardInterrupt, SystemExit):
raise
except:
if self.logger:
self.logger.exception('Unexpected error decoding AMF request')
response = ('500 Internal Server Error\n\n'
'An unexpected error occurred.')
if self.debug:
response += "\n\nTraceback:\n\n%s" % gateway.format_exception()
return http.HttpResponseServerError(mimetype='text/plain',
content=response)
if self.logger:
self.logger.debug("AMF Request: %r" % request)
# Process the request
try:
response = self.getResponse(http_request, request)
except (KeyboardInterrupt, SystemExit):
raise
except:
if self.logger:
self.logger.exception('Error processing AMF request')
response = ("500 Internal Server Error\n\nThe request was "
"unable to be successfully processed.")
if self.debug:
response += "\n\nTraceback:\n\n%s" % gateway.format_exception()
return http.HttpResponseServerError(mimetype='text/plain',
content=response)
if self.logger:
self.logger.debug("AMF Response: %r" % response)
# Encode the response
try:
stream = remoting.encode(response, strict=self.strict,
logger=self.logger, timezone_offset=timezone_offset)
except:
if self.logger:
self.logger.exception('Error encoding AMF request')
response = ("500 Internal Server Error\n\nThe request was "
"unable to be encoded.")
if self.debug:
response += "\n\nTraceback:\n\n%s" % gateway.format_exception()
return http.HttpResponseServerError(
mimetype='text/plain', content=response)
buf = stream.getvalue()
http_response = http.HttpResponse(mimetype=remoting.CONTENT_TYPE)
http_response['Server'] = gateway.SERVER_NAME
http_response['Content-Length'] = str(len(buf))
http_response.write(buf)
return http_response