import os import cherrypy from cherrypy import tools from cherrypy.test import helper localDir = os.path.dirname(__file__) logfile = os.path.join(localDir, 'test_misc_tools.log') def setup_server(): class Root: @cherrypy.expose def index(self): yield 'Hello, world' h = [('Content-Language', 'en-GB'), ('Content-Type', 'text/plain')] tools.response_headers(headers=h)(index) @cherrypy.expose @cherrypy.config(**{ 'tools.response_headers.on': True, 'tools.response_headers.headers': [ ('Content-Language', 'fr'), ('Content-Type', 'text/plain'), ], 'tools.log_hooks.on': True, }) def other(self): return 'salut' @cherrypy.config(**{'tools.accept.on': True}) class Accept: @cherrypy.expose def index(self): return 'Atom feed' @cherrypy.expose @tools.accept(media='application/atom+xml') def feed(self): return """ Unknown Blog """ @cherrypy.expose def select(self): # We could also write this: mtype = cherrypy.lib.accept.accept(...) mtype = tools.accept.callable(['text/html', 'text/plain']) if mtype == 'text/html': return '

Page Title

' else: return 'PAGE TITLE' class Referer: @cherrypy.expose def accept(self): return 'Accepted!' reject = accept class AutoVary: @cherrypy.expose def index(self): # Read a header directly with 'get' ae = cherrypy.request.headers.get('Accept-Encoding') # Read a header directly with '__getitem__' cl = cherrypy.request.headers['Host'] # Read a header directly with '__contains__' hasif = 'If-Modified-Since' in cherrypy.request.headers # Read a header directly with 'has_key' if hasattr(dict, 'has_key'): # Python 2 has = cherrypy.request.headers.has_key('Range') else: # Python 3 has = 'Range' in cherrypy.request.headers # Call a lib function mtype = tools.accept.callable(['text/html', 'text/plain']) return 'Hello, world!' conf = {'/referer': {'tools.referer.on': True, 'tools.referer.pattern': r'http://[^/]*example\.com', }, '/referer/reject': {'tools.referer.accept': False, 'tools.referer.accept_missing': True, }, '/autovary': {'tools.autovary.on': True}, } root = Root() root.referer = Referer() root.accept = Accept() root.autovary = AutoVary() cherrypy.tree.mount(root, config=conf) cherrypy.config.update({'log.error_file': logfile}) class ResponseHeadersTest(helper.CPWebCase): setup_server = staticmethod(setup_server) def testResponseHeadersDecorator(self): self.getPage('/') self.assertHeader('Content-Language', 'en-GB') self.assertHeader('Content-Type', 'text/plain;charset=utf-8') def testResponseHeaders(self): self.getPage('/other') self.assertHeader('Content-Language', 'fr') self.assertHeader('Content-Type', 'text/plain;charset=utf-8') class RefererTest(helper.CPWebCase): setup_server = staticmethod(setup_server) def testReferer(self): self.getPage('/referer/accept') self.assertErrorPage(403, 'Forbidden Referer header.') self.getPage('/referer/accept', headers=[('Referer', 'http://www.example.com/')]) self.assertStatus(200) self.assertBody('Accepted!') # Reject self.getPage('/referer/reject') self.assertStatus(200) self.assertBody('Accepted!') self.getPage('/referer/reject', headers=[('Referer', 'http://www.example.com/')]) self.assertErrorPage(403, 'Forbidden Referer header.') class AcceptTest(helper.CPWebCase): setup_server = staticmethod(setup_server) def test_Accept_Tool(self): # Test with no header provided self.getPage('/accept/feed') self.assertStatus(200) self.assertInBody('Unknown Blog') # Specify exact media type self.getPage('/accept/feed', headers=[('Accept', 'application/atom+xml')]) self.assertStatus(200) self.assertInBody('Unknown Blog') # Specify matching media range self.getPage('/accept/feed', headers=[('Accept', 'application/*')]) self.assertStatus(200) self.assertInBody('Unknown Blog') # Specify all media ranges self.getPage('/accept/feed', headers=[('Accept', '*/*')]) self.assertStatus(200) self.assertInBody('Unknown Blog') # Specify unacceptable media types self.getPage('/accept/feed', headers=[('Accept', 'text/html')]) self.assertErrorPage(406, 'Your client sent this Accept header: text/html. ' 'But this resource only emits these media types: ' 'application/atom+xml.') # Test resource where tool is 'on' but media is None (not set). self.getPage('/accept/') self.assertStatus(200) self.assertBody('Atom feed') def test_accept_selection(self): # Try both our expected media types self.getPage('/accept/select', [('Accept', 'text/html')]) self.assertStatus(200) self.assertBody('

Page Title

') self.getPage('/accept/select', [('Accept', 'text/plain')]) self.assertStatus(200) self.assertBody('PAGE TITLE') self.getPage('/accept/select', [('Accept', 'text/plain, text/*;q=0.5')]) self.assertStatus(200) self.assertBody('PAGE TITLE') # text/* and */* should prefer text/html since it comes first # in our 'media' argument to tools.accept self.getPage('/accept/select', [('Accept', 'text/*')]) self.assertStatus(200) self.assertBody('

Page Title

') self.getPage('/accept/select', [('Accept', '*/*')]) self.assertStatus(200) self.assertBody('

Page Title

') # Try unacceptable media types self.getPage('/accept/select', [('Accept', 'application/xml')]) self.assertErrorPage( 406, 'Your client sent this Accept header: application/xml. ' 'But this resource only emits these media types: ' 'text/html, text/plain.') class AutoVaryTest(helper.CPWebCase): setup_server = staticmethod(setup_server) def testAutoVary(self): self.getPage('/autovary/') self.assertHeader( 'Vary', 'Accept, Accept-Charset, Accept-Encoding, ' 'Host, If-Modified-Since, Range' )