Ticket #2407: CGI.py

File CGI.py, 8.0 KB (added by Martin, 18 years ago)

The CGI Handler classes

Line 
1#-*- coding: iso-8859-1 -*-
2# Copyright (C) 2006 Martin Glueck. All rights reserved
3# 351 Bienterra Trail, #2, Rockford, IL, 61107, martin.glueck@insightbb.com
4# ****************************************************************************
5#
6# This library is free software; you can redistribute it and/or
7# modify it under the terms of the GNU Library General Public
8# License as published by the Free Software Foundation; either
9# version 2 of the License, or (at your option) any later version.
10#
11# This library is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14# Library General Public License for more details.
15#
16# You should have received a copy of the GNU Library General Public
17# License along with this library; if not, write to the Free
18# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19# ****************************************************************************
20#
21#++
22# Name
23# django.core.handlers.CGI
24#
25# Purpose
26# A CGI Handler for Django
27#
28# Revision Dates
29# 14-Jul-2006 (MG) Creation
30# ««revision-date»»···
31#--
32
33import django
34import sys
35from django import http
36from django.core.handlers.base import BaseHandler
37from django.core import signals
38from django.dispatch import dispatcher
39from django.utils import datastructures
40
41__all__ = ["CGI_Handler"]
42
43# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
44STATUS_CODE_TEXT = \
45 { 100 : "CONTINUE"
46 , 101 : "SWITCHING PROTOCOLS"
47 , 200 : "OK"
48 , 201 : "CREATED"
49 , 202 : "ACCEPTED"
50 , 203 : "NON-AUTHORITATIVE INFORMATION"
51 , 204 : "NO CONTENT"
52 , 205 : "RESET CONTENT"
53 , 206 : "PARTIAL CONTENT"
54 , 300 : "MULTIPLE CHOICES"
55 , 301 : "MOVED PERMANENTLY"
56 , 302 : "FOUND"
57 , 303 : "SEE OTHER"
58 , 304 : "NOT MODIFIED"
59 , 305 : "USE PROXY"
60 , 306 : "RESERVED"
61 , 307 : "TEMPORARY REDIRECT"
62 , 400 : "BAD REQUEST"
63 , 401 : "UNAUTHORIZED"
64 , 402 : "PAYMENT REQUIRED"
65 , 403 : "FORBIDDEN"
66 , 404 : "NOT FOUND"
67 , 405 : "METHOD NOT ALLOWED"
68 , 406 : "NOT ACCEPTABLE"
69 , 407 : "PROXY AUTHENTICATION REQUIRED"
70 , 408 : "REQUEST TIMEOUT"
71 , 409 : "CONFLICT"
72 , 410 : "GONE"
73 , 411 : "LENGTH REQUIRED"
74 , 412 : "PRECONDITION FAILED"
75 , 413 : "REQUEST ENTITY TOO LARGE"
76 , 414 : "REQUEST-URI TOO LONG"
77 , 415 : "UNSUPPORTED MEDIA TYPE"
78 , 416 : "REQUESTED RANGE NOT SATISFIABLE"
79 , 417 : "EXPECTATION FAILED"
80 , 500 : "INTERNAL SERVER ERROR"
81 , 501 : "NOT IMPLEMENTED"
82 , 502 : "BAD GATEWAY"
83 , 503 : "SERVICE UNAVAILABLE"
84 , 504 : "GATEWAY TIMEOUT"
85 , 505 : "HTTP VERSION NOT SUPPORTED"
86 }
87
88class CGI_Request (http.HttpRequest) :
89 """A Request from a normal CGI interface."""
90
91 _request = None
92 _get = None
93 _post = None
94 _cookies = None
95 _files = None
96
97 def __init__ (self, environ) :
98 ### don't chain up, we set the dict's here as properties
99 ### super (CGI_Request, self).__init__ (self, environ)
100 self.environ = environ
101 self.path = environ.get ("REDIRECT_URL", "/")
102 self.META = environ
103 self.method = environ.get ("REQUEST_METHOD", "GET").upper()
104 # end def __init__
105
106 def __repr__(self):
107 return "\n".join \
108 ( ( "<%s" % (self.__class__.__name__)
109 , " GET: %r" % (self.GET)
110 , " POST: %r" % (self.POST)
111 , " COOKIES: %r" % (self.COOKIES)
112 , " META: %r" % (self.META)
113 , ">"
114 )
115 )
116 # end def __repr__
117
118 def get_full_path(self):
119 return '%s%s' % \
120 ( self.path
121 , self.environ.get ("QUERY_STRING", "")
122 and ("?" + self.environ ["QUERY_STRING"])
123 or ''
124 )
125 # end def get_full_path
126
127 def _load_post_and_files(self):
128 # Populates self._post and self._files
129 if self.method == "POST" :
130 if self.environ.get ("CONTENT_TYPE", "").startswith ("multipart") :
131 header_dict = dict\
132 ( [ (k, v) for k, v in self.environ.iteritems ()
133 if k.startswith('HTTP_')
134 ]
135 )
136 header_dict ["Content-Type"] = self.environ.get \
137 ("CONTENT_TYPE", "")
138 (self._post, self._files
139 ) = http.parse_file_upload (header_dict, self.raw_post_data)
140 else :
141 self._post = http.QueryDict (self.raw_post_data)
142 self._files = datastructures.MultiValueDict ()
143 else:
144 self._post = http.QueryDict ("")
145 self._files = datastructures.MultiValueDict ()
146 # end def _load_post_and_files
147
148 def _get_request(self):
149 if self._request is None :
150 self._request = datastructures.MergeDict (self.POST, self.GET)
151 return self._request
152 # end def _get_request
153
154 def _get_get(self):
155 if self._get is None :
156 self._get = http.QueryDict (self.environ.get ("QUERY_STRING", ""))
157 return self._get
158 # end def _get_get
159
160 def _set_get(self, get) :
161 self._get = get
162 # end def _set_get
163
164 def _get_post(self):
165 if self._post is None:
166 self._load_post_and_files ()
167 return self._post
168 # end def _get_post
169
170 def _set_post(self, post):
171 self._post = post
172 # end def _set_post
173
174 def _get_cookies(self):
175 if self._cookies is None :
176 self._cookies = http.parse_cookie \
177 (self.environ.get ("HTTP_COOKIE", ""))
178 return self._cookies
179 # end def _get_cookies
180
181 def _set_cookies(self, cookies):
182 self._cookies = cookies
183 # end def _set_cookies
184
185 def _get_files(self):
186 if self._files is None :
187 self._load_post_and_files ()
188 return self._files
189 # end def _get_files
190
191 def _get_raw_post_data(self):
192 try:
193 return self._raw_post_data
194 except AttributeError:
195 self._raw_post_data = sys.stdin.read \
196 (int (self.environ ["CONTENT_LENGTH"]))
197 return self._raw_post_data
198 # end def _get_raw_post_data
199
200 GET = property (_get_get, _set_get)
201 POST = property (_get_post, _set_post)
202 COOKIES = property (_get_cookies, _set_cookies)
203 FILES = property (_get_files)
204 REQUEST = property (_get_request)
205 raw_post_data = property (_get_raw_post_data)
206
207# end class CGI_Request
208
209class CGI_Handler (BaseHandler) :
210 """The handler for a CGI request."""
211
212 def __call__ (self, environ, start_response) :
213 from django.conf import settings
214
215 # Set up middleware if needed. We couldn't do this earlier, because
216 # settings weren't available.
217 if self._request_middleware is None:
218 self.load_middleware ()
219
220 dispatcher.send (signal = signals.request_started)
221 try:
222 request = CGI_Request (environ)
223 response = self.get_response (request.path, request)
224 # Apply response middleware
225 for middleware_method in self._response_middleware:
226 response = middleware_method (request, response)
227 finally:
228 dispatcher.send (signal = signals.request_finished)
229
230 status_text = STATUS_CODE_TEXT.get \
231 (response.status_code, "UNKNOWN STATUS CODE")
232 status = '%s %s' % (response.status_code, status_text)
233 response_headers = response.headers.items ()
234 for c in response.cookies.values ():
235 response_headers.append (('Set-Cookie', c.output(header='')))
236 start_response (status, response_headers)
237 return response.iterator
238 # end def __call__
239
240# end class CGI_Handler
241
242
243### __END__ django.core.handerls.CGI
Back to Top