Package web :: Package web :: Module http
[hide private]
[frames] | no frames]

Source Code for Module web.web.http

  1  """ 
  2  HTTP Utilities 
  3  (from web.py) 
  4  """ 
  5   
  6  __all__ = [ 
  7    "expires", "lastmodified",  
  8    "prefixurl", "modified",  
  9    "changequery", "url", 
 10    "profiler", 
 11  ] 
 12   
 13  import sys, os, threading, urllib, urlparse 
 14  try: import datetime 
 15  except ImportError: pass 
 16  import net, utils, webapi as web 
 17   
18 -def prefixurl(base=''):
19 """ 20 Sorry, this function is really difficult to explain. 21 Maybe some other time. 22 """ 23 url = web.ctx.path.lstrip('/') 24 for i in xrange(url.count('/')): 25 base += '../' 26 if not base: 27 base = './' 28 return base
29
30 -def expires(delta):
31 """ 32 Outputs an `Expires` header for `delta` from now. 33 `delta` is a `timedelta` object or a number of seconds. 34 """ 35 if isinstance(delta, (int, long)): 36 delta = datetime.timedelta(seconds=delta) 37 date_obj = datetime.datetime.utcnow() + delta 38 web.header('Expires', net.httpdate(date_obj))
39
40 -def lastmodified(date_obj):
41 """Outputs a `Last-Modified` header for `datetime`.""" 42 web.header('Last-Modified', net.httpdate(date_obj))
43
44 -def modified(date=None, etag=None):
45 """ 46 Checks to see if the page has been modified since the version in the 47 requester's cache. 48 49 When you publish pages, you can include `Last-Modified` and `ETag` 50 with the date the page was last modified and an opaque token for 51 the particular version, respectively. When readers reload the page, 52 the browser sends along the modification date and etag value for 53 the version it has in its cache. If the page hasn't changed, 54 the server can just return `304 Not Modified` and not have to 55 send the whole page again. 56 57 This function takes the last-modified date `date` and the ETag `etag` 58 and checks the headers to see if they match. If they do, it returns 59 `True`, or otherwise it raises NotModified error. It also sets 60 `Last-Modified` and `ETag` output headers. 61 """ 62 try: 63 from __builtin__ import set 64 except ImportError: 65 # for python 2.3 66 from sets import Set as set 67 68 n = set([x.strip('" ') for x in web.ctx.env.get('HTTP_IF_NONE_MATCH', '').split(',')]) 69 m = net.parsehttpdate(web.ctx.env.get('HTTP_IF_MODIFIED_SINCE', '').split(';')[0]) 70 validate = False 71 if etag: 72 if '*' in n or etag in n: 73 validate = True 74 if date and m: 75 # we subtract a second because 76 # HTTP dates don't have sub-second precision 77 if date-datetime.timedelta(seconds=1) <= m: 78 validate = True 79 80 if date: lastmodified(date) 81 if etag: web.header('ETag', '"' + etag + '"') 82 if validate: 83 raise web.notmodified() 84 else: 85 return True
86
87 -def urlencode(query, doseq=0):
88 """ 89 Same as urllib.urlencode, but supports unicode strings. 90 91 >>> urlencode({'text':'foo bar'}) 92 'text=foo+bar' 93 >>> urlencode({'x': [1, 2]}, doseq=True) 94 'x=1&x=2' 95 """ 96 def convert(value, doseq=False): 97 if doseq and isinstance(value, list): 98 return [convert(v) for v in value] 99 else: 100 return utils.utf8(value)
101 102 query = dict([(k, convert(v, doseq)) for k, v in query.items()]) 103 return urllib.urlencode(query, doseq=doseq) 104
105 -def changequery(query=None, **kw):
106 """ 107 Imagine you're at `/foo?a=1&b=2`. Then `changequery(a=3)` will return 108 `/foo?a=3&b=2` -- the same URL but with the arguments you requested 109 changed. 110 """ 111 if query is None: 112 query = web.rawinput(method='get') 113 for k, v in kw.iteritems(): 114 if v is None: 115 query.pop(k, None) 116 else: 117 query[k] = v 118 out = web.ctx.path 119 if query: 120 out += '?' + urlencode(query, doseq=True) 121 return out
122
123 -def url(path=None, doseq=False, **kw):
124 """ 125 Makes url by concatinating web.ctx.homepath and path and the 126 query string created using the arguments. 127 """ 128 if path is None: 129 path = web.ctx.path 130 if path.startswith("/"): 131 out = web.ctx.homepath + path 132 else: 133 out = path 134 135 if kw: 136 out += '?' + urlencode(kw, doseq=doseq) 137 138 return out
139
140 -def profiler(app):
141 """Outputs basic profiling information at the bottom of each response.""" 142 from utils import profile 143 def profile_internal(e, o): 144 out, result = profile(app)(e, o) 145 return list(out) + ['<pre>' + net.websafe(result) + '</pre>']
146 return profile_internal 147 148 if __name__ == "__main__": 149 import doctest 150 doctest.testmod() 151