1
# -*- coding: iso-8859-1 -*-
3
MoinMoin - Twisted Request Implementation
5
@copyright: 2001-2003 Juergen Hermann <jh@web.de>,
6
2003-2006 MoinMoin:ThomasWaldmann
7
@license: GNU GPL, see COPYING for details.
10
from MoinMoin import log
11
logging = log.getLogger(__name__)
13
from MoinMoin.request import RequestBase, MoinMoinFinish, RemoteClosedConnection
15
class Request(RequestBase):
16
""" specialized on Twisted requests """
18
def __init__(self, twistedRequest, pagename, reactor, properties={}):
20
self.twistd = twistedRequest
21
self.reactor = reactor
24
self.http_accept_language = self.twistd.getHeader('Accept-Language')
25
self.saved_cookie = self.twistd.getHeader('Cookie')
26
self.http_user_agent = self.twistd.getHeader('User-Agent')
28
self.content_length = int(self.twistd.getHeader('Content-Length'))
29
except (TypeError, ValueError):
30
self.content_length = None
31
self.if_modified_since = self.twistd.getHeader('If-Modified-Since')
32
self.if_none_match = self.twistd.getHeader('If-None-Match')
34
# Copy values from twisted request
35
self.server_protocol = self.twistd.clientproto
36
self.server_name = self.twistd.getRequestHostname().split(':')[0]
37
self.server_port = str(self.twistd.getHost()[2])
38
self.is_ssl = self.twistd.isSecure()
39
self.path_info = '/' + '/'.join([pagename] + self.twistd.postpath)
40
self.request_method = self.twistd.method
41
self.remote_addr = self.twistd.getClientIP()
42
self.request_uri = self.twistd.uri
43
self.script_name = "/" + '/'.join(self.twistd.prepath[:-1])
45
# Values that need more work
46
self.query_string = self.splitURI(self.twistd.uri)[1]
47
self.setHttpReferer(self.twistd.getHeader('Referer'))
49
self.setURL(self.twistd.getAllHeaders())
51
##self.debugEnvironment(twistedRequest.getAllHeaders())
53
RequestBase.__init__(self, properties)
55
except MoinMoinFinish: # might be triggered by http_redirect
56
self.emit_http_headers() # send headers (important for sending MOIN_ID cookie)
59
except Exception, err:
60
# Wrap err inside an internal error if needed
61
from MoinMoin import error
62
if isinstance(err, error.FatalError):
63
self.delayedError = err
65
self.delayedError = error.InternalError(str(err))
68
""" Handle delayed errors then invoke base class run """
69
if hasattr(self, 'delayedError'):
70
self.fail(self.delayedError)
77
Twisted already parsed args, including __filename__ hacking,
78
but did not decode the values.
80
# All of the arguments, including URL and POST arguments (using keep_blank_values=1 internally).
81
return self.decodeArgs(self.twistd.args)
84
""" Read from input stream. """
85
# XXX why is that wrong?:
86
#rd = self.reactor.callFromThread(self.twistd.read)
88
# XXX do we need self.reactor.callFromThread with that?
89
# XXX if yes, why doesn't it work?
90
self.twistd.content.seek(0, 0)
92
logging.warning("calling request.read(None) might block")
93
rd = self.twistd.content.read()
95
rd = self.twistd.content.read(n)
96
#print "request.RequestTwisted.read: data=\n" + str(rd)
99
def write(self, *data):
100
""" Write to output stream. """
101
#print "request.RequestTwisted.write: data=\n" + wd
102
data = self.encode(data)
104
self.reactor.callFromThread(self.twistd.write, data)
106
raise RemoteClosedConnection()
109
pass # XXX is there a flush in twisted?
112
RequestBase.finish(self)
113
self.reactor.callFromThread(self.twistd.finish)
115
# Headers ----------------------------------------------------------
117
def _emit_http_headers(self, headers):
118
""" private method to send out preprocessed list of HTTP headers """
119
st_header, other_headers = headers[0], headers[1:]
120
status = st_header.split(':', 1)[1].lstrip()
121
status_code, status_msg = status.split(' ', 1)
122
self.twistd.setResponseCode(int(status_code), status_msg)
123
for header in other_headers:
124
key, value = header.split(':', 1)
125
value = value.lstrip()
126
if key.lower() == 'set-cookie':
127
key, value = value.split('=', 1)
128
self.twistd.addCookie(key, value)
130
self.twistd.setHeader(key, value)
132
def http_redirect(self, url):
133
""" Redirect to a fully qualified, or server-rooted URL
135
@param url: relative or absolute url, ascii using url encoding.
137
url = self.getQualifiedURL(url)
138
self.twistd.redirect(url)
139
# calling finish here will send the rest of the data to the next
140
# request. leave the finish call to run()
141
#self.twistd.finish()