1
# -*- coding: iso-8859-1 -*-
3
MoinMoin - mod_python Request Implementation for Apache and mod_python.
5
@copyright: 2001-2003 Juergen Hermann <jh@web.de>,
6
2003-2006 MoinMoin:ThomasWaldmann
7
@license: GNU GPL, see COPYING for details.
9
from MoinMoin import log
10
logging = log.getLogger(__name__)
12
from MoinMoin import wikiutil
13
from MoinMoin.request import RequestBase, RemoteClosedConnection
15
class Request(RequestBase):
16
""" specialized on mod_python requests """
18
def __init__(self, req, properties={}):
19
""" Saves mod_pythons request and sets basic variables using
20
the req.subprocess_env, cause this provides a standard
21
way to access the values we need here.
23
@param req: the mod_python request instance
26
# flags if headers sent out contained content-type or status
32
# some mod_python 2.7.X has no get method for table objects,
33
# so we make a real dict out of it first.
34
if not hasattr(req.subprocess_env, 'get'):
35
env = dict(req.subprocess_env)
37
env = req.subprocess_env
38
self._setup_vars_from_std_env(env)
39
RequestBase.__init__(self, properties)
41
except Exception, err:
44
def fixURI(self, env):
45
""" Fix problems with script_name and path_info using
46
PythonOption directive to rewrite URI.
48
This is needed when using Apache 1 or other server which does
49
not support adding custom headers per request. With mod_python we
50
can use the PythonOption directive:
52
<Location /url/to/mywiki/>
53
PythonOption X-Moin-Location /url/to/mywiki/
56
Note that *neither* script_name *nor* path_info can be trusted
57
when Moin is invoked as a mod_python handler with apache1, so we
58
must build both using request_uri and the provided PythonOption.
60
# Be compatible with release 1.3.5 "Location" option
61
# TODO: Remove in later release, we should have one option only.
62
old_location = 'Location'
63
options_table = self.mpyreq.get_options()
64
if not hasattr(options_table, 'get'):
65
options = dict(options_table)
67
options = options_table
68
location = options.get(self.moin_location) or options.get(old_location)
70
env[self.moin_location] = location
71
# Try to recreate script_name and path_info from request_uri.
73
scriptAndPath = urlparse.urlparse(self.request_uri)[2]
74
self.script_name = location.rstrip('/')
75
path = scriptAndPath.replace(self.script_name, '', 1)
76
self.path_info = wikiutil.url_unquote(path, want_unicode=False)
78
RequestBase.fixURI(self, env)
80
def _setup_args_from_cgi_form(self):
81
""" Override to use mod_python.util.FieldStorage
83
It's little different from cgi.FieldStorage, so we need to
84
duplicate the conversion code.
86
from mod_python import util
87
form = util.FieldStorage(self.mpyreq, keep_blank_values=1) # by default this evaluates query string AND body POST data!
91
# You cannot get rid of .keys() here
92
for key in form.keys():
96
if not isinstance(values, list):
100
if isinstance(item, util.StringField):
101
fixedResult.append(item.value)
102
elif isinstance(item, util.Field) and item.filename:
103
fixedResult.append(item.file)
104
# Remember filenames with a name hack
105
args[key + '__filename__'] = item.filename
106
elif isinstance(item, str):
107
# mod_python 2.7 might return strings instead of Field objects.
108
fixedResult.append(item)
109
args[key] = fixedResult
111
return self.decodeArgs(args)
114
""" mod_python calls this with its request object. We don't
115
need it cause its already passed to __init__. So ignore
116
it and just return RequestBase.run.
118
@param req: the mod_python request instance
120
return RequestBase.run(self)
123
""" Read from input stream. """
125
logging.warning("calling request.read(None) might block")
126
return self.mpyreq.read()
128
return self.mpyreq.read(n)
130
def write(self, *data):
131
""" Write to output stream. """
132
data = self.encode(data)
134
self.mpyreq.write(data)
136
raise RemoteClosedConnection()
139
""" We can't flush it, so do nothing. """
143
""" Just return apache.OK. Status is set in req.status. """
144
RequestBase.finish(self)
145
# is it possible that we need to return something else here?
146
from mod_python import apache
149
def _emit_http_headers(self, headers):
150
""" private method to send out preprocessed list of HTTP headers """
151
st_header, ct_header, other_headers = headers[0], headers[1], headers[2:]
152
status = st_header.split(':', 1)[1].lstrip()
153
self.mpyreq.status = int(status.split(' ', 1)[0])
154
self.mpyreq.content_type = ct_header.split(':', 1)[1].lstrip()
155
for header in other_headers:
156
key, value = header.split(':', 1)
157
value = value.lstrip()
158
self.mpyreq.headers_out[key] = value
159
# this is for mod_python 2.7.X, for 3.X it's a NOP
160
self.mpyreq.send_http_header()