1import os 2 3import cherrypy 4from cherrypy import tools 5from cherrypy.test import helper 6 7 8localDir = os.path.dirname(__file__) 9logfile = os.path.join(localDir, 'test_misc_tools.log') 10 11 12def setup_server(): 13 class Root: 14 15 @cherrypy.expose 16 def index(self): 17 yield 'Hello, world' 18 h = [('Content-Language', 'en-GB'), ('Content-Type', 'text/plain')] 19 tools.response_headers(headers=h)(index) 20 21 @cherrypy.expose 22 @cherrypy.config(**{ 23 'tools.response_headers.on': True, 24 'tools.response_headers.headers': [ 25 ('Content-Language', 'fr'), 26 ('Content-Type', 'text/plain'), 27 ], 28 'tools.log_hooks.on': True, 29 }) 30 def other(self): 31 return 'salut' 32 33 @cherrypy.config(**{'tools.accept.on': True}) 34 class Accept: 35 36 @cherrypy.expose 37 def index(self): 38 return '<a href="feed">Atom feed</a>' 39 40 @cherrypy.expose 41 @tools.accept(media='application/atom+xml') 42 def feed(self): 43 return """<?xml version="1.0" encoding="utf-8"?> 44<feed xmlns="http://www.w3.org/2005/Atom"> 45 <title>Unknown Blog</title> 46</feed>""" 47 48 @cherrypy.expose 49 def select(self): 50 # We could also write this: mtype = cherrypy.lib.accept.accept(...) 51 mtype = tools.accept.callable(['text/html', 'text/plain']) 52 if mtype == 'text/html': 53 return '<h2>Page Title</h2>' 54 else: 55 return 'PAGE TITLE' 56 57 class Referer: 58 59 @cherrypy.expose 60 def accept(self): 61 return 'Accepted!' 62 reject = accept 63 64 class AutoVary: 65 66 @cherrypy.expose 67 def index(self): 68 # Read a header directly with 'get' 69 cherrypy.request.headers.get('Accept-Encoding') 70 # Read a header directly with '__getitem__' 71 cherrypy.request.headers['Host'] 72 # Read a header directly with '__contains__' 73 'If-Modified-Since' in cherrypy.request.headers 74 # Read a header directly 75 'Range' in cherrypy.request.headers 76 # Call a lib function 77 tools.accept.callable(['text/html', 'text/plain']) 78 return 'Hello, world!' 79 80 conf = {'/referer': {'tools.referer.on': True, 81 'tools.referer.pattern': r'http://[^/]*example\.com', 82 }, 83 '/referer/reject': {'tools.referer.accept': False, 84 'tools.referer.accept_missing': True, 85 }, 86 '/autovary': {'tools.autovary.on': True}, 87 } 88 89 root = Root() 90 root.referer = Referer() 91 root.accept = Accept() 92 root.autovary = AutoVary() 93 cherrypy.tree.mount(root, config=conf) 94 cherrypy.config.update({'log.error_file': logfile}) 95 96 97class ResponseHeadersTest(helper.CPWebCase): 98 setup_server = staticmethod(setup_server) 99 100 def testResponseHeadersDecorator(self): 101 self.getPage('/') 102 self.assertHeader('Content-Language', 'en-GB') 103 self.assertHeader('Content-Type', 'text/plain;charset=utf-8') 104 105 def testResponseHeaders(self): 106 self.getPage('/other') 107 self.assertHeader('Content-Language', 'fr') 108 self.assertHeader('Content-Type', 'text/plain;charset=utf-8') 109 110 111class RefererTest(helper.CPWebCase): 112 setup_server = staticmethod(setup_server) 113 114 def testReferer(self): 115 self.getPage('/referer/accept') 116 self.assertErrorPage(403, 'Forbidden Referer header.') 117 118 self.getPage('/referer/accept', 119 headers=[('Referer', 'http://www.example.com/')]) 120 self.assertStatus(200) 121 self.assertBody('Accepted!') 122 123 # Reject 124 self.getPage('/referer/reject') 125 self.assertStatus(200) 126 self.assertBody('Accepted!') 127 128 self.getPage('/referer/reject', 129 headers=[('Referer', 'http://www.example.com/')]) 130 self.assertErrorPage(403, 'Forbidden Referer header.') 131 132 133class AcceptTest(helper.CPWebCase): 134 setup_server = staticmethod(setup_server) 135 136 def test_Accept_Tool(self): 137 # Test with no header provided 138 self.getPage('/accept/feed') 139 self.assertStatus(200) 140 self.assertInBody('<title>Unknown Blog</title>') 141 142 # Specify exact media type 143 self.getPage('/accept/feed', 144 headers=[('Accept', 'application/atom+xml')]) 145 self.assertStatus(200) 146 self.assertInBody('<title>Unknown Blog</title>') 147 148 # Specify matching media range 149 self.getPage('/accept/feed', headers=[('Accept', 'application/*')]) 150 self.assertStatus(200) 151 self.assertInBody('<title>Unknown Blog</title>') 152 153 # Specify all media ranges 154 self.getPage('/accept/feed', headers=[('Accept', '*/*')]) 155 self.assertStatus(200) 156 self.assertInBody('<title>Unknown Blog</title>') 157 158 # Specify unacceptable media types 159 self.getPage('/accept/feed', headers=[('Accept', 'text/html')]) 160 self.assertErrorPage(406, 161 'Your client sent this Accept header: text/html. ' 162 'But this resource only emits these media types: ' 163 'application/atom+xml.') 164 165 # Test resource where tool is 'on' but media is None (not set). 166 self.getPage('/accept/') 167 self.assertStatus(200) 168 self.assertBody('<a href="feed">Atom feed</a>') 169 170 def test_accept_selection(self): 171 # Try both our expected media types 172 self.getPage('/accept/select', [('Accept', 'text/html')]) 173 self.assertStatus(200) 174 self.assertBody('<h2>Page Title</h2>') 175 self.getPage('/accept/select', [('Accept', 'text/plain')]) 176 self.assertStatus(200) 177 self.assertBody('PAGE TITLE') 178 self.getPage('/accept/select', 179 [('Accept', 'text/plain, text/*;q=0.5')]) 180 self.assertStatus(200) 181 self.assertBody('PAGE TITLE') 182 183 # text/* and */* should prefer text/html since it comes first 184 # in our 'media' argument to tools.accept 185 self.getPage('/accept/select', [('Accept', 'text/*')]) 186 self.assertStatus(200) 187 self.assertBody('<h2>Page Title</h2>') 188 self.getPage('/accept/select', [('Accept', '*/*')]) 189 self.assertStatus(200) 190 self.assertBody('<h2>Page Title</h2>') 191 192 # Try unacceptable media types 193 self.getPage('/accept/select', [('Accept', 'application/xml')]) 194 self.assertErrorPage( 195 406, 196 'Your client sent this Accept header: application/xml. ' 197 'But this resource only emits these media types: ' 198 'text/html, text/plain.') 199 200 201class AutoVaryTest(helper.CPWebCase): 202 setup_server = staticmethod(setup_server) 203 204 def testAutoVary(self): 205 self.getPage('/autovary/') 206 self.assertHeader( 207 'Vary', 208 'Accept, Accept-Charset, Accept-Encoding, ' 209 'Host, If-Modified-Since, Range' 210 ) 211