author | Tero Marttila <terom@fixme.fi> |
Mon, 16 Feb 2009 22:40:35 +0200 | |
changeset 86 | 6ff1140586d6 |
parent 73 | 1554d3d083b8 |
permissions | -rw-r--r-- |
7 | 1 |
""" |
2 |
WSGI HTTP utility code |
|
3 |
""" |
|
4 |
||
5 |
# for utility functions |
|
6 |
import cgi |
|
7 |
||
8 |
# for header handling |
|
9 |
import wsgiref.headers |
|
10 |
||
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
11 |
# for path handling |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
12 |
import os.path |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
13 |
|
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
14 |
def request_url (env) : |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
15 |
""" |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
16 |
Attempt to reconstruct the URL of the given request environment. |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
17 |
|
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
18 |
Works best when env is a WSGI-compliant env dict |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
19 |
""" |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
20 |
|
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
21 |
# HTTP/HTTPs scheme |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
22 |
scheme = env.get('wsgi.url_scheme', '[???]') |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
23 |
|
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
24 |
# the host |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
25 |
host = env.get('HTTP_HOST', '[???]') |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
26 |
|
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
27 |
# the path |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
28 |
path = env.get('REQUEST_URI', '[???]') |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
29 |
|
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
30 |
# return |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
31 |
return "%s://%s%s" % (scheme, host, path) |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
32 |
|
7 | 33 |
class Request (object) : |
34 |
""" |
|
35 |
HTTP Request with associated metadata |
|
36 |
""" |
|
37 |
||
38 |
def __init__ (self, env) : |
|
39 |
""" |
|
40 |
Parse env data |
|
41 |
""" |
|
42 |
||
43 |
# store env |
|
44 |
self.env = env |
|
45 |
||
46 |
# get the querystring |
|
47 |
self.arg_str = env.get('QUERY_STRING', '') |
|
48 |
||
49 |
# parse query args |
|
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
50 |
self.arg_dict = cgi.parse_qs(self.arg_str, keep_blank_values=True) |
55 | 51 |
|
52 |
# load post data? |
|
53 |
if self.is_post() : |
|
54 |
# content-type of post data |
|
55 |
content_type = self.env.get('CONTENT_TYPE', 'application/x-www-form-urlencoded') |
|
56 |
||
57 |
# valid content-type? |
|
58 |
# XXX: how to handle errors? |
|
59 |
assert any(content_type.startswith(x) for x in ( |
|
60 |
'application/x-www-form-urlencoded', |
|
61 |
'multipart/form-data' |
|
62 |
)) |
|
63 |
||
64 |
# input stream |
|
65 |
input = self.env['wsgi.input'] |
|
66 |
||
67 |
# use cgi.FieldStorage to parse this |
|
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
68 |
self.post_data = cgi.FieldStorage(fp=input, environ=self.env, keep_blank_values=True) |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
69 |
|
55 | 70 |
else : |
71 |
# no post data |
|
72 |
self.post_data = None |
|
42
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
73 |
|
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
74 |
@property |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
75 |
def site_host (self) : |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
76 |
""" |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
77 |
Returns the site's hostname (DNS name) |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
78 |
""" |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
79 |
|
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
80 |
return self.env['HTTP_HOST'] |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
81 |
|
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
82 |
@property |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
83 |
def site_root (self) : |
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
84 |
""" |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
85 |
Returns the URL path to the requested script's directory with no trailing slash, i.e. |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
86 |
|
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
87 |
/ -> |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
88 |
/foo.cgi -> |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
89 |
/foo/bar.cgi -> /foo |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
90 |
""" |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
91 |
|
14
b88d23696b98
add cache/template dir, and fix get_script_dir to give '' for root
Tero Marttila <terom@fixme.fi>
parents:
10
diff
changeset
|
92 |
return os.path.dirname(self.env['SCRIPT_NAME']).rstrip('/') |
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
93 |
|
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
94 |
def _normalize_path (self, path) : |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
95 |
""" |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
96 |
Normalizes an URL path to remove back-references, but keep any trailing-slash indicator |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
97 |
""" |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
98 |
|
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
99 |
# keep trailing / postfix |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
100 |
path_postfix = '/' if path.endswith('/') else '' |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
101 |
|
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
102 |
# avoid nasty '.' paths |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
103 |
if path : |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
104 |
return os.path.normpath(path) + path_postfix |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
105 |
|
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
106 |
else : |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
107 |
return '' |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
108 |
|
42
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
109 |
@property |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
110 |
def page_prefix (self) : |
10
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
111 |
""" |
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
112 |
Returns the URL path root for page URLs, based on REQUEST_URI with PATH_INFO removed. This will have a |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
113 |
a preceeding slash, but no trailing slash, unless it's empty: |
10
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
114 |
|
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
115 |
/ -> |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
116 |
/foo.cgi -> /foo.cgi |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
117 |
/foo.cgi/index -> /foo.cgi |
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
118 |
/foo.cgi/quux/bar/ -> /foo.cgi |
10
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
119 |
/quux/foo.cgi/bar -> /quux/foo.cgi |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
120 |
/bar -> |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
121 |
""" |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
122 |
|
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
123 |
# request uri path without the query string |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
124 |
request_path = self._normalize_path(self.env.get('REQUEST_URI', '').split('?', 1)[0]) |
10
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
125 |
|
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
126 |
# path info |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
127 |
page_name = self.get_page_name() |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
128 |
|
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
129 |
# special-case for empty page_name |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
130 |
if not page_name : |
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
131 |
return request_path.rstrip('/') |
10
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
132 |
|
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
133 |
# sanity-check |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
134 |
assert request_path.endswith(page_name) |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
135 |
|
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
136 |
# trim |
d83b10c210e3
some vodoo for generating correct URLs
Tero Marttila <terom@fixme.fi>
parents:
9
diff
changeset
|
137 |
return request_path[:-len(page_name)].rstrip('/') |
42
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
138 |
|
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
139 |
def get_page_name (self) : |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
140 |
""" |
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
141 |
Returns the requested page path with no leading slash, but preserved trailing slash: |
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
142 |
|
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
143 |
/foo.cgi -> |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
144 |
/foo.cgi/ -> |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
145 |
/foo.cgi/bar -> bar |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
146 |
/foo.cgi/quux/ -> quux/ |
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
147 |
/foo/../ -> foo/ |
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
148 |
""" |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
149 |
|
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
150 |
# the normalized PATH_INFO |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
151 |
return self._normalize_path(self.env.get('PATH_INFO')).lstrip('/') |
42
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
152 |
|
49
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
153 |
def get_arg (self, name, default=None) : |
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
154 |
""" |
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
155 |
Get a single value for an argument with the given key, or the default if missing. |
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
156 |
|
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
157 |
This evaluates valueless query args (?foo&bar=) as empty strings. |
49
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
158 |
""" |
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
159 |
|
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
160 |
if name in self.arg_dict : |
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
161 |
return self.arg_dict[name][0] |
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
162 |
|
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
163 |
else : |
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
164 |
return default |
9b097385b463
remove name from URLType, handle it separately in SimpleValueLabel + improve query argument handling
Tero Marttila <terom@fixme.fi>
parents:
46
diff
changeset
|
165 |
|
42
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
166 |
def get_args (self) : |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
167 |
""" |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
168 |
Iterate over all available (key, value) pairs from the query string |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
169 |
""" |
5a72c00c4ae4
more fiddling around with the irclogs layout/css, add query args to URL
Tero Marttila <terom@fixme.fi>
parents:
25
diff
changeset
|
170 |
|
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
171 |
return cgi.parse_qsl(self.arg_str, keep_blank_values=True) |
55 | 172 |
|
173 |
def is_post (self) : |
|
174 |
""" |
|
175 |
Is this a POST request? |
|
176 |
""" |
|
177 |
||
178 |
# just check REQUEST_METHOD |
|
179 |
return (self.env['REQUEST_METHOD'].upper() == 'POST') |
|
180 |
||
69
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
181 |
class _nodefault : pass |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
182 |
def get_post (self, name, default=_nodefault) : |
55 | 183 |
""" |
69
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
184 |
Get the value of the given POST field. |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
185 |
|
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
186 |
If the optional `default` arg is given, it is returned if the key is not found |
55 | 187 |
""" |
188 |
||
189 |
# sanity-check |
|
73
1554d3d083b8
add a http.request_url utility function, start writing some unit tests (now for http.Request), fix some issues
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
190 |
assert self.post_data is not None |
55 | 191 |
|
69
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
192 |
if name in self.post_data : |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
193 |
# return the FieldStorage value |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
194 |
return self.post_data[name].value |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
195 |
|
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
196 |
elif default != self._nodefault : |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
197 |
# return the default value |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
198 |
return default |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
199 |
|
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
200 |
else : |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
201 |
# fail |
2e93ba90fb92
add support for default values to http.Request.get_post
Tero Marttila <terom@fixme.fi>
parents:
57
diff
changeset
|
202 |
raise KeyError(name) |
7 | 203 |
|
204 |
class Response (object) : |
|
205 |
""" |
|
206 |
HTTP Response with headers and data |
|
207 |
""" |
|
208 |
||
25
8f143b1ce0d1
lowercase qmsk.net, and use UTF-8 for the HTTP encoding, not utf8
Tero Marttila <terom@fixme.fi>
parents:
14
diff
changeset
|
209 |
def __init__ (self, data, content_type='text/html', status='200 OK', charset='UTF-8') : |
7 | 210 |
""" |
57
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
211 |
Create the response. The Content-type header is built from the given values. |
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
212 |
|
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
213 |
The given data must be a string-like object, which will be encoded with the given charset, or None, |
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
214 |
whereupon an empty response body will be sent. |
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
215 |
|
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
216 |
The content_type argument can also be forced to None to not send a Content-type header (e.g. for |
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
217 |
redirects). |
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
218 |
|
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
219 |
The charset can be given as None to not encode the output (for binary data). |
7 | 220 |
""" |
221 |
||
222 |
# store info |
|
223 |
self.status = status |
|
224 |
self.data = data |
|
225 |
self.charset = charset |
|
226 |
||
227 |
# headers |
|
228 |
self.headers = wsgiref.headers.Headers([]) |
|
229 |
||
230 |
# add Content-type header? |
|
231 |
if content_type : |
|
232 |
self.add_header('Content-type', content_type, charset=charset) |
|
233 |
||
234 |
def add_header (self, name, value, **params) : |
|
235 |
""" |
|
236 |
Add response header with the given name/value, plus option params |
|
237 |
||
238 |
XXX: uses the wsgiref.headers code, not sure how that behaves re multiple headers with the same name, etc |
|
239 |
""" |
|
240 |
||
241 |
self.headers.add_header(name, value, **params) |
|
242 |
||
243 |
def get_status (self) : |
|
244 |
""" |
|
245 |
Returns response status string (XXX Foo) |
|
246 |
""" |
|
247 |
||
248 |
return self.status |
|
249 |
||
250 |
def get_headers (self) : |
|
251 |
""" |
|
252 |
Returns the list of header (name, value) pairs |
|
253 |
""" |
|
254 |
||
255 |
return self.headers.items() |
|
256 |
||
257 |
def get_data (self) : |
|
258 |
""" |
|
259 |
Returns the response data - as an encoded string |
|
260 |
""" |
|
261 |
||
262 |
if self.data : |
|
57
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
263 |
if self.charset : |
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
264 |
return self.data.encode(self.charset) |
7 | 265 |
|
57
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
266 |
else : |
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
267 |
return self.data |
2ed89377f339
support binary responses, i.e. no charset
Tero Marttila <terom@fixme.fi>
parents:
55
diff
changeset
|
268 |
|
7 | 269 |
else : |
270 |
return '' |
|
271 |
||
272 |
class ErrorResponse (Response) : |
|
273 |
""" |
|
274 |
A response with an error code / message |
|
275 |
""" |
|
276 |
||
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
277 |
def __init__ (self, status, message, details=None) : |
7 | 278 |
""" |
279 |
Build a plain error message response with the given status/message |
|
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
280 |
|
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
281 |
@param status HTTP status code |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
282 |
@param message short message to describe errors |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
283 |
@param details optional details, plaintext |
7 | 284 |
""" |
285 |
||
286 |
data = """\ |
|
287 |
<html><head><title>%(title)s</title></head><body> |
|
288 |
<h1>%(title)s</h1> |
|
289 |
<p>%(message)s</p> |
|
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
290 |
%(details)s |
7 | 291 |
</body></html> |
292 |
""" % dict( |
|
293 |
title = status, |
|
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
294 |
message = message, |
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
295 |
details = '<pre>%s</pre>' % details if details else '' |
7 | 296 |
) |
297 |
||
298 |
super(ErrorResponse, self).__init__(data, status=status) |
|
299 |
||
300 |
class ResponseError (Exception) : |
|
301 |
""" |
|
302 |
An exception that results in a specfic 4xx ErrorResponse message to the client |
|
303 |
""" |
|
304 |
||
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
305 |
def __init__ (self, message, status='400 Bad Request', details=None) : |
7 | 306 |
self.status = status |
307 |
self.message = message |
|
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
308 |
self.details = details |
7 | 309 |
|
310 |
super(ResponseError, self).__init__(message) |
|
311 |
||
312 |
def get_response (self) : |
|
8
0ce1f471e9d7
and it works, a lot better than before
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
313 |
return ErrorResponse(self.status, self.message, self.details) |
7 | 314 |
|
315 |
class Redirect (Response) : |
|
316 |
""" |
|
317 |
Redirect response |
|
318 |
""" |
|
319 |
||
320 |
def __init__ (self, url) : |
|
321 |
""" |
|
322 |
Redirect to given *absolute* URL |
|
323 |
""" |
|
324 |
||
325 |
# no content-type or data |
|
326 |
super(Redirect, self).__init__(None, content_type=None, status='302 Found') |
|
327 |
||
328 |
# add Location: header |
|
329 |
self.add_header("Location", url) |
|
330 |
||
331 |