1
2
3
4 """
5 Gateway for the Django framework.
6
7 This gateway allows you to expose functions in Django to AMF clients and
8 servers.
9
10 @see: U{Django homepage (external)<http://djangoproject.com>}
11
12 @since: 0.1.0
13 """
14
15 django = __import__('django.http')
16 http = django.http
17 conf = __import__('django.conf')
18 conf = conf.conf
19
20 import pyamf
21 from pyamf import remoting
22 from pyamf.remoting import gateway
23
24 __all__ = ['DjangoGateway']
25
26
28 """
29 An instance of this class is suitable as a Django view.
30
31 An example usage would be through C{urlconf}::
32
33 from django.conf.urls.defaults import *
34
35 urlpatterns = patterns('',
36 (r'^gateway/', 'yourproject.yourapp.gateway.gw_instance'),
37 )
38
39 where C{yourproject.yourapp.gateway.gw_instance} refers to an instance of
40 this class.
41
42 @ivar expose_request: The standard Django view always has the request
43 object as the first parameter. To disable this functionality, set this
44 to C{False}.
45 @type expose_request: C{bool}
46 """
47
49 kwargs['expose_request'] = kwargs.get('expose_request', True)
50
51 try:
52 tz = conf.settings.AMF_TIME_OFFSET
53 except AttributeError:
54 tz = None
55
56 try:
57 debug = conf.settings.DEBUG
58 except AttributeError:
59 debug = False
60
61 kwargs['timezone_offset'] = kwargs.get('timezone_offset', tz)
62 kwargs['debug'] = kwargs.get('debug', debug)
63
64 gateway.BaseGateway.__init__(self, *args, **kwargs)
65
67 """
68 Processes the AMF request, returning an AMF response.
69
70 @param http_request: The underlying HTTP Request.
71 @type http_request: C{HTTPRequest<django.core.http.HTTPRequest>}
72 @param request: The AMF Request.
73 @type request: L{Envelope<pyamf.remoting.Envelope>}
74 @rtype: L{Envelope<pyamf.remoting.Envelope>}
75 @return: The AMF Response.
76 """
77 response = remoting.Envelope(request.amfVersion, request.clientType)
78
79 for name, message in request:
80 http_request.amf_request = message
81
82 processor = self.getProcessor(message)
83 response[name] = processor(message, http_request=http_request)
84
85 return response
86
88 """
89 Processes and dispatches the request.
90
91 @param http_request: The C{HTTPRequest} object.
92 @type http_request: C{HTTPRequest}
93 @return: The response to the request.
94 @rtype: C{HTTPResponse}
95 """
96 if http_request.method != 'POST':
97 return http.HttpResponseNotAllowed(['POST'])
98
99 stream = None
100 timezone_offset = self._get_timezone_offset()
101
102
103 try:
104 request = remoting.decode(http_request.raw_post_data,
105 strict=self.strict, logger=self.logger,
106 timezone_offset=timezone_offset)
107 except (pyamf.DecodeError, IOError):
108 fe = gateway.format_exception()
109
110 if self.logger:
111 self.logger.exception(fe)
112
113 response = "400 Bad Request\n\nThe request body was unable to " \
114 "be successfully decoded."
115
116 if self.debug:
117 response += "\n\nTraceback:\n\n%s" % fe
118
119 return http.HttpResponseBadRequest(mimetype='text/plain', content=response)
120 except (KeyboardInterrupt, SystemExit):
121 raise
122 except:
123 fe = gateway.format_exception()
124
125 if self.logger:
126 self.logger.exception(fe)
127
128 response = ('500 Internal Server Error\n\n'
129 'An unexpected error occurred.')
130
131 if self.debug:
132 response += "\n\nTraceback:\n\n%s" % fe
133
134 return http.HttpResponseServerError(mimetype='text/plain',
135 content=response)
136
137 if self.logger:
138 self.logger.info("AMF Request: %r" % request)
139
140
141 try:
142 response = self.getResponse(http_request, request)
143 except (KeyboardInterrupt, SystemExit):
144 raise
145 except:
146 fe = gateway.format_exception()
147
148 if self.logger:
149 self.logger.exception(fe)
150
151 response = "500 Internal Server Error\n\nThe request was " \
152 "unable to be successfully processed."
153
154 if self.debug:
155 response += "\n\nTraceback:\n\n%s" % fe
156
157 return http.HttpResponseServerError(mimetype='text/plain',
158 content=response)
159
160 if self.logger:
161 self.logger.info("AMF Response: %r" % response)
162
163
164 try:
165 stream = remoting.encode(response, strict=self.strict,
166 logger=self.logger, timezone_offset=timezone_offset)
167 except:
168 fe = gateway.format_exception()
169
170 if self.logger:
171 self.logger.exception(fe)
172
173 response = ("500 Internal Server Error\n\nThe request was "
174 "unable to be encoded.")
175
176 if self.debug:
177 response += "\n\nTraceback:\n\n%s" % fe
178
179 return http.HttpResponseServerError(mimetype='text/plain', content=response)
180
181 buf = stream.getvalue()
182
183 http_response = http.HttpResponse(mimetype=remoting.CONTENT_TYPE)
184 http_response['Server'] = gateway.SERVER_NAME
185 http_response['Content-Length'] = str(len(buf))
186
187 http_response.write(buf)
188
189 return http_response
190