Skip to content
Newer
Older
100644 172 lines (149 sloc) 4.92 KB
089a01a web.py 0.2
aaronsw authored May 20, 2006
1 """
2 HTTP Utilities
3 (from web.py)
4 """
5
6 __all__ = [
7 "expires", "lastmodified",
8 "prefixurl", "modified",
9 "write",
874feb3 bug fixes and web.url
anand authored Feb 17, 2007
10 "changequery", "url",
bb3ab9e @anandology removed reloader from http.py. It has been moved to application.py
anandology authored Nov 10, 2008
11 "profiler",
089a01a web.py 0.2
aaronsw authored May 20, 2006
12 ]
13
14 import sys, os, threading, urllib, urlparse
15 try: import datetime
16 except ImportError: pass
17 import net, utils, webapi as web
18
19 def prefixurl(base=''):
20 """
21 Sorry, this function is really difficult to explain.
22 Maybe some other time.
23 """
24 url = web.ctx.path.lstrip('/')
25 for i in xrange(url.count('/')):
26 base += '../'
27 if not base:
28 base = './'
29 return base
30
31 def expires(delta):
32 """
33 Outputs an `Expires` header for `delta` from now.
34 `delta` is a `timedelta` object or a number of seconds.
35 """
36 if isinstance(delta, (int, long)):
37 delta = datetime.timedelta(seconds=delta)
38 date_obj = datetime.datetime.utcnow() + delta
39 web.header('Expires', net.httpdate(date_obj))
40
41 def lastmodified(date_obj):
42 """Outputs a `Last-Modified` header for `datetime`."""
43 web.header('Last-Modified', net.httpdate(date_obj))
44
45 def modified(date=None, etag=None):
d12fbe8 @aaronsw add docstring for web.modified; enhance function slightly
aaronsw authored Nov 19, 2008
46 """
47 Checks to see if the page has been modified since the version in the
48 requester's cache.
49
50 When you publish pages, you can include `Last-Modified` and `ETag`
51 with the date the page was last modified and an opaque token for
52 the particular version, respectively. When readers reload the page,
53 the browser sends along the modification date and etag value for
54 the version it has in its cache. If the page hasn't changed,
55 the server can just return `304 Not Modified` and not have to
56 send the whole page again.
57
58 This function takes the last-modified date `date` and the ETag `etag`
59 and checks the headers to see if they match. If they do, it returns
60 `True` and sets the response status to `304 Not Modified`. It also
61 sets `Last-Modified and `ETag` output headers.
62 """
5c0d10e @anandology fix python 2.3 compatibility
anandology authored Jan 6, 2009
63 try:
64 from __builtin__ import set
65 except ImportError:
66 # for python 2.3
67 from sets import Set as set
68
69 n = set([x.strip('" ') for x in web.ctx.env.get('HTTP_IF_NONE_MATCH', '').split(',')])
089a01a web.py 0.2
aaronsw authored May 20, 2006
70 m = net.parsehttpdate(web.ctx.env.get('HTTP_IF_MODIFIED_SINCE', '').split(';')[0])
71 validate = False
72 if etag:
3ccd412 @aaronsw add etag support
aaronsw authored Oct 22, 2008
73 if '*' in n or etag in n:
74 validate = True
089a01a web.py 0.2
aaronsw authored May 20, 2006
75 if date and m:
76 # we subtract a second because
77 # HTTP dates don't have sub-second precision
78 if date-datetime.timedelta(seconds=1) <= m:
79 validate = True
d12fbe8 @aaronsw add docstring for web.modified; enhance function slightly
aaronsw authored Nov 20, 2008
80
089a01a web.py 0.2
aaronsw authored May 20, 2006
81 if validate: web.ctx.status = '304 Not Modified'
4f32f8b @aaronsw fix in web.modified
aaronsw authored Dec 11, 2008
82 if date: lastmodified(date)
83 if etag: web.header('ETag', '"' + etag + '"')
089a01a web.py 0.2
aaronsw authored May 20, 2006
84 return not validate
85
86 def write(cgi_response):
87 """
88 Converts a standard CGI-style string response into `header` and
89 `output` calls.
90 """
91 cgi_response = str(cgi_response)
92 cgi_response.replace('\r\n', '\n')
93 head, body = cgi_response.split('\n\n', 1)
94 lines = head.split('\n')
95
96 for line in lines:
97 if line.isspace():
98 continue
99 hdr, value = line.split(":", 1)
100 value = value.strip()
101 if hdr.lower() == "status":
102 web.ctx.status = value
103 else:
104 web.header(hdr, value)
105
106 web.output(body)
107
0cae750 @anandology fix changequery to make it work correctly even when the input has mul…
anandology authored Oct 23, 2009
108 def urlencode(query, doseq=0):
db64ef3 fix unicode bugs with urlencode
aaronsw authored Jul 16, 2007
109 """
110 Same as urllib.urlencode, but supports unicode strings.
111
112 >>> urlencode({'text':'foo bar'})
113 'text=foo+bar'
0cae750 @anandology fix changequery to make it work correctly even when the input has mul…
anandology authored Oct 23, 2009
114 >>> urlencode({'x': [1, 2]}, doseq=True)
115 'x=1&x=2'
db64ef3 fix unicode bugs with urlencode
aaronsw authored Jul 16, 2007
116 """
0cae750 @anandology fix changequery to make it work correctly even when the input has mul…
anandology authored Oct 23, 2009
117 def convert(value, doseq=False):
118 if doseq and isinstance(value, list):
119 return [convert(v) for v in value]
120 else:
121 return utils.utf8(value)
122
123 query = dict([(k, convert(v, doseq)) for k, v in query.items()])
124 return urllib.urlencode(query, doseq=doseq)
db64ef3 fix unicode bugs with urlencode
aaronsw authored Jul 16, 2007
125
3962c18 changequery takes optional query argument.
anand authored Aug 15, 2007
126 def changequery(query=None, **kw):
089a01a web.py 0.2
aaronsw authored May 20, 2006
127 """
128 Imagine you're at `/foo?a=1&b=2`. Then `changequery(a=3)` will return
129 `/foo?a=3&b=2` -- the same URL but with the arguments you requested
130 changed.
131 """
3962c18 changequery takes optional query argument.
anand authored Aug 15, 2007
132 if query is None:
0cae750 @anandology fix changequery to make it work correctly even when the input has mul…
anandology authored Oct 23, 2009
133 query = web.rawinput(method='get')
089a01a web.py 0.2
aaronsw authored May 20, 2006
134 for k, v in kw.iteritems():
135 if v is None:
136 query.pop(k, None)
137 else:
138 query[k] = v
53fb28d fixed bugs in changequery and redirect
anand authored Jun 25, 2007
139 out = web.ctx.path
089a01a web.py 0.2
aaronsw authored May 20, 2006
140 if query:
0cae750 @anandology fix changequery to make it work correctly even when the input has mul…
anandology authored Oct 23, 2009
141 out += '?' + urlencode(query, doseq=True)
089a01a web.py 0.2
aaronsw authored May 20, 2006
142 return out
143
3962c18 changequery takes optional query argument.
anand authored Aug 15, 2007
144 def url(path=None, **kw):
874feb3 bug fixes and web.url
anand authored Feb 17, 2007
145 """
146 Makes url by concatinating web.ctx.homepath and path and the
147 query string created using the arguments.
148 """
3962c18 changequery takes optional query argument.
anand authored Aug 15, 2007
149 if path is None:
150 path = web.ctx.path
874feb3 bug fixes and web.url
anand authored Feb 17, 2007
151 if path.startswith("/"):
152 out = web.ctx.homepath + path
153 else:
154 out = path
155
156 if kw:
db64ef3 fix unicode bugs with urlencode
aaronsw authored Jul 16, 2007
157 out += '?' + urlencode(kw)
874feb3 bug fixes and web.url
anand authored Feb 17, 2007
158
159 return out
160
089a01a web.py 0.2
aaronsw authored May 20, 2006
161 def profiler(app):
162 """Outputs basic profiling information at the bottom of each response."""
cb2115c fix profiling bug (tx spez)
aaronsw authored Nov 10, 2006
163 from utils import profile
089a01a web.py 0.2
aaronsw authored May 20, 2006
164 def profile_internal(e, o):
165 out, result = profile(app)(e, o)
3df6a15 @anandology fix web.profiler (Bug#326633)
anandology authored Feb 25, 2009
166 return list(out) + ['<pre>' + net.websafe(result) + '</pre>']
089a01a web.py 0.2
aaronsw authored May 20, 2006
167 return profile_internal
168
169 if __name__ == "__main__":
170 import doctest
171 doctest.testmod()
Something went wrong with that request. Please try again.