def testFirstOneWins(self): with open(join(self.directory, 'someFile'), 'w') as f: f.write("Some Contents") with open(join(self.directory2, 'someFile'), 'w') as f: f.write("Different Contents") fileServer = FileServer(documentRoot=[self.directory, self.directory2]) response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/someFile", Method="GET", Headers={})) self.assertTrue("Some Contents" in response) self.assertFalse("Different Contents" in response) fileServer = FileServer(documentRoot=[self.directory2, self.directory]) response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/someFile", Method="GET", Headers={})) self.assertTrue("Different Contents" in response) self.assertFalse("Some Contents" in response)
def testMinimumLength(self): self._setUpAuto(prefixBasedSearchKwargs=dict(minimumLength=5)) header, body = generatorToString(self.auto.handleRequest(path='/path', arguments={'prefix':['test']})).split('\r\n'*2) self.assertTrue("Content-Type: application/x-suggestions+json" in header, header) self.assertEqual("""["test", []]""", body) self.assertEqual([], [m.name for m in self.observer.calledMethods])
def testAutocompleteCSS(self): result = generatorToString(self.auto.handleRequest( path='/path/autocomplete.css', arguments={})) header,body = result.split('\r\n'*2) self.assertTrue('jqac-' in body, body[:300]) self.assertTrue('Content-Type: text/css' in header, header)
def testOpenSearchWithoutHtmlAndPort80(self): queryTemplate = '/sru?version=1.1&operation=searchRetrieve&query={searchTerms}' self.auto = be((Autocomplete( host='localhost', port=80, path='/some/path', templateQuery=queryTemplate, shortname="Web Search", description="Use this web search to search something", defaultLimit=50, defaultField='lom', ), (self.observer,), )) result = generatorToString(self.auto.handleRequest( path='/path/opensearchdescription.xml', arguments={})) header,body = result.split('\r\n'*2) self.assertTrue("Content-Type: text/xml" in header, header) self.assertEqualsWS("""<?xml version="1.0" encoding="UTF-8"?> <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <ShortName>Web Search</ShortName> <Description>Use this web search to search something</Description> <Url type="text/xml" method="get" template="http://localhost/sru?version=1.1&operation=searchRetrieve&query={searchTerms}"/> <Url type="application/x-suggestions+json" template="http://localhost/some/path?prefix={searchTerms}"/> </OpenSearchDescription>""", body)
def testListDirectoryBasePath(self): fileServer = FileServer(self.directory, allowDirectoryListing=True, basePath='/webpath/') with open(join(self.directory, "dummy.txt"), "w") as f: f.write("Dummy") mkdir(self.directory, "subdir") response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/")) self.assertTrue(response.startswith("HTTP/1.0 200 OK"), response) self.assertTrue("<title>Index of /webpath</title>" in response, response) links = [ line for line in response.split("\n") if line.startswith("<a href") ] self.assertEqual(2, len(links)) self.assertTrue( links[0].startswith('<a href="dummy.txt">dummy.txt</a>'), links[0]) self.assertTrue(links[0].endswith(' 5'), links[0]) self.assertTrue(links[1].startswith('<a href="subdir/">subdir/</a>'), links[1])
def testCreateSession(self): called = [] class MyObserver(Observable): def handleRequest(self, *args, **kwargs): session = self.ctx.session called.append({ 'args': args, 'kwargs': kwargs, 'session': session }) yield utils.okHtml yield '<ht' yield 'ml/>' self.handler.addObserver(MyObserver()) result = generatorToString( self.handler.handleRequest(RequestURI='/path', Client=('127.0.0.1', 12345), Headers={'a': 'b'})) self.assertEqual(1, len(called)) self.assertEqual({}, called[0]['session']) session = called[0]['kwargs']['session'] self.assertEqual({}, session) self.assertEqual({'a': 'b'}, called[0]['kwargs']['Headers']) self.assertTrue(('127.0.0.1', 12345), called[0]['kwargs']['Client']) header, body = result.split(utils.CRLF * 2, 1) self.assertEqual('<html/>', body) self.assertTrue('Set-Cookie' in header, header) headerParts = header.split(utils.CRLF) self.assertEqual("HTTP/1.0 200 OK", headerParts[0]) sessionCookie = [p for p in headerParts[1:] if 'Set-Cookie' in p][0] self.assertTrue(sessionCookie.startswith('Set-Cookie: session'))
def testNoProperHttpResponseStillWorks(self): handler = BasicHttpHandler() observer = CallTrace('HttpComponent') observer.returnValues['handleRequest'] = (f for f in ['Body']) dna = self.build(handler, observer) response = generatorToString(dna.all.handleRequest(RequestURI="/")) self.assertEqual('Body', response)
def testAlternativeMethod(self): handler = BasicHttpHandler(notFoundMethod=lambda path, **kwargs: 'HTTP/1.0 404\r\n\r\n%s' % path) observer = CallTrace('HttpComponent', emptyGeneratorMethods=['handleRequest']) dna = self.build(handler, observer) response = generatorToString(dna.all.handleRequest(RequestURI="/", path='/')) self.assertEqual('HTTP/1.0 404\r\n\r\n/', response) self.assertEqual(['handleRequest'], observer.calledMethodNames())
def testRedirect(self): handler = BasicHttpHandler.createWithRedirect('http://example.org/here') observer = CallTrace('HttpComponent', emptyGeneratorMethods=['handleRequest']) dna = self.build(handler, observer) response = generatorToString(dna.all.handleRequest(RequestURI="/")) self.assertEqual('HTTP/1.0 302 Found\r\nLocation: http://example.org/here\r\n\r\n', response) self.assertEqual(['handleRequest'], observer.calledMethodNames())
def test404(self): handler = BasicHttpHandler() observer = CallTrace('HttpComponent', emptyGeneratorMethods=['handleRequest']) dna = self.build(handler, observer) response = generatorToString(dna.all.handleRequest(RequestURI="/")) self.assertEqual('HTTP/1.0 404 Not Found\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<html><body>404 Not Found</body></html>', response) self.assertEqual(['handleRequest'], observer.calledMethodNames())
def testOldStyleAutocomplete(self): queryTemplate = '/sru?version=1.1&operation=searchRetrieve&query={searchTerms}' self.auto = be((Autocomplete( host='localhost', port=8000, path='/some/path', templateQuery=queryTemplate, shortname="Web Search", description="Use this web search to search something", defaultLimit=50, defaultField='lom', ), (self.observer,), )) response = SolrResponse() response.hits = ['term0', 'term&/"'] response.total = 2 response.qtime = 5 def prefixSearch(**kwargs): return response yield self.observer.methods['prefixSearch'] = prefixSearch header, body = generatorToString(self.auto.handleRequest(path='/path', arguments={'prefix':['te'], 'limit': ['5'], 'field': ['field.one']})).split('\r\n'*2) self.assertTrue("Content-Type: application/x-suggestions+json" in header, header) self.assertEqual("""["te", ["term0", "term&/\\""]]""", body) self.assertEqual(['prefixSearch'], [m.name for m in self.observer.calledMethods]) self.assertEqual({'prefix':'te', 'fieldname':'field.one', 'limit':5}, self.observer.calledMethods[0].kwargs) result = generatorToString(self.auto.handleRequest( path='/path/opensearchdescription.xml', arguments={})) header,body = result.split('\r\n'*2) self.assertTrue("Content-Type: text/xml" in header, header) self.assertEqualsWS("""<?xml version="1.0" encoding="UTF-8"?> <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <ShortName>Web Search</ShortName> <Description>Use this web search to search something</Description> <Url type="text/xml" method="get" template="http://localhost:8000/sru?version=1.1&operation=searchRetrieve&query={searchTerms}"/> <Url type="application/x-suggestions+json" template="http://localhost:8000/some/path?prefix={searchTerms}"/> </OpenSearchDescription>""", body)
def testJQueryAutocompleteJS(self): result = generatorToString(self.auto.handleRequest( path='/path/jquery.autocomplete.js', arguments={})) header,body = result.split('\r\n'*2) self.assertTrue('Extending jQuery with autocomplete' in body, body[:300]) try: self.assertTrue('Content-Type: application/x-javascript' in header, header) except AssertionError: self.assertTrue('Content-Type: application/javascript' in header, header)
def testAddHeaders(self): handler = BasicHttpHandler(additionalHeaders={'Aap': "Noot Mies", "Boom": "Vis"}) observer = CallTrace('HttpComponent') observer.returnValues['handleRequest'] = (f for f in ['HT','TP/1.0 200 OK\r\n\r\n', 'Body']) dna = self.build(handler, observer) response = generatorToString(dna.all.handleRequest(RequestURI="/")) self.assertEqual('HTTP/1.0 200 OK\r\nAap: Noot Mies\r\nBoom: Vis\r\n\r\nBody', response) self.assertEqual(['handleRequest'], observer.calledMethodNames())
def testOk(self): handler = BasicHttpHandler() observer = CallTrace('HttpComponent') observer.returnValues['handleRequest'] = (f for f in ['HTTP/1.0 200 OK\r\n\r\n', 'Body']) dna = self.build(handler, observer) response = generatorToString(dna.all.handleRequest(RequestURI="/")) self.assertEqual('HTTP/1.0 200 OK\r\n\r\nBody', response) self.assertEqual(['handleRequest'], observer.calledMethodNames())
def testOpenSearchDescriptionXml(self): result = generatorToString(self.auto.handleRequest( path='/path/opensearchdescription.xml', arguments={})) header,body = result.split('\r\n'*2) self.assertTrue("Content-Type: text/xml" in header, header) self.assertEqualsWS("""<?xml version="1.0" encoding="UTF-8"?> <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <ShortName>Web Search</ShortName> <Description>Use this web search to search something</Description> <Url type="text/xml" method="get" template="http://localhost:8000/sru?version=1.1&operation=searchRetrieve&query={searchTerms}"/> <Url type="text/html" method="get" template="http://localhost:8000/demo?q={searchTerms}"/> <Url type="application/x-suggestions+json" template="http://localhost:8000/some/path?prefix={searchTerms}"/> </OpenSearchDescription>""", body)
def testHandleRequest(self): response = SolrResponse() response.hits = ['term0', 'term&/"'] response.total = 2 response.qtime = 5 def prefixSearch(**kwargs): return response yield self.observer.methods['prefixSearch'] = prefixSearch header, body = generatorToString(self.auto.handleRequest(path='/path', arguments={'prefix':['te'], 'limit': ['5'], 'field': ['field.one']})).split('\r\n'*2) self.assertTrue("Content-Type: application/x-suggestions+json" in header, header) self.assertEqual("""["te", ["term0", "term&/\\""]]""", body) self.assertEqual(['prefixSearch'], [m.name for m in self.observer.calledMethods]) self.assertEqual({'prefix':'te', 'fieldname':'field.one', 'limit':5}, self.observer.calledMethods[0].kwargs)
def testInsertHeader(self): def handleRequest(*args, **kwargs): yield utils.okHtml yield '<ht' yield 'ml/>' newHeader = 'Set-Cookie: session=dummySessionId1234; path=/' result = generatorToString( utils.insertHeader(handleRequest(), newHeader)) header, body = result.split(utils.CRLF * 2, 1) self.assertEqual('<html/>', body) headerParts = header.split(utils.CRLF) self.assertEqual("HTTP/1.0 200 OK", headerParts[0]) self.assertTrue(newHeader in headerParts) self.assertTrue(utils.ContentTypeHeader + utils.ContentTypeHtml in headerParts)
def testPathShouldBeInDocumentRoot(self): documentRoot = join(self.directory, 'documentRoot') makedirs(documentRoot) notAllowedFile = join(self.directory, 'notAllowed.txt') with open(notAllowedFile, 'w') as f: f.write("DO NOT READ ME") fileServer = FileServer(documentRoot) response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/../" + notAllowedFile, Method="GET", Headers={})) self.assertTrue("HTTP/1.0 404 Not Found" in response, response) self.assertTrue("<title>404 Not Found</title>" in response)
def testCacheControlStuff(self): with open(join(self.directory, 'someFile'), 'w') as f: f.write("Some Contents") fileServer = FileServer(self.directory) response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/someFile", Method="GET", Headers={})) headers, body = response.split("\r\n\r\n") self.assertTrue("Date: " in headers) self.assertTrue("Last-Modified: " in headers) self.assertTrue("Expires: " in headers) headerValues = dict( tuple(a.strip() for a in line.split(':', 1)) for line in headers.split('\r\n') if ':' in line) date = timegm(parsedate(headerValues['Date'])) expires = timegm(parsedate(headerValues['Expires'])) self.assertTrue(1 > time() - date > 0, time() - date) self.assertTrue(61 * 60 > expires - date > 59 * 60, expires - date)
def testServeFileWithCorrectContentType(self): for extension, expectedType in [('.js', 'application/javascript'), ('.xhtml', 'application/xhtml+xml'), ('.png', 'image/png'), ('.xsd', 'application/xml'), ('.css', 'text/css')]: filename = 'someFile' + extension f = open(join(self.directory, filename), 'w') f.write("Some Contents") f.close() fileServer = FileServer(self.directory) response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/%s" % filename, Method="GET", Headers={})) headersList = response.split('\r\n\r\n', 1)[0].split('\r\n') self.assertTrue("HTTP/1.0 200 OK" in response) self.assertTrue("Some Contents" in response) self.assertTrue('Content-Type: %s' % expectedType in headersList, headersList)
def testProvenanceFromOaiPmh(self): def getRecord(identifier, *args, **kwargs): record = CallTrace() record.identifier = identifier record.prefixes = set(['oai_dc']) record.sets = set() record.isDeleted = False return record oaijazz = CallTrace(methods={ 'getRecord': getRecord, 'isKnownPrefix': lambda prefix: True }, onlySpecifiedMethods=True) observable = be( (Observable(), (OaiPmh(repositoryName='example', adminEmail='*****@*****.**'), (oaijazz, ), ( RetrieveToGetDataAdapter(), (MockStorage(), ), ), ( OaiProvenance( nsMap={'oai_dc': "http://www.openarchives.org/OAI/2.0/"}, baseURL=('meta', '/meta/repository/baseurl/text()'), harvestDate=('meta', '/meta/repository/harvestDate/text()'), metadataNamespace=( 'meta', '/meta/repository/metadataNamespace/text()'), identifier=('header', '/oai_dc:header/oai_dc:identifier/text()'), datestamp=('header', '/oai_dc:header/oai_dc:datestamp/text()')), (MockStorage(), ), )))) result = generatorToString( observable.all.handleRequest( Method='GET', arguments=dict(verb=['GetRecord'], identifier=["recordId"], metadataPrefix=['oai_dc']), Headers=dict(Host='oaiserver.example.org'), path='/oai', port=1234, )) _, body = result.split(CRLF * 2) provenanceResult = xpathFirst(XML(body.encode()), '//oai:about/oaiprov:provenance') self.assertXmlEquals( """<provenance xmlns="http://www.openarchives.org/OAI/2.0/provenance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/provenance http://www.openarchives.org/OAI/2.0/provenance.xsd"> <originDescription harvestDate="HARVESTDATE" altered="true"> <baseURL>BASEURL</baseURL> <identifier>recordId</identifier> <datestamp>DATESTAMP</datestamp> <metadataNamespace>METADATANAMESPACE</metadataNamespace> </originDescription> </provenance>""", provenanceResult)
def testListDirectory(self): fileServer = FileServer(self.directory) response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/")) self.assertTrue(response.startswith("HTTP/1.0 404 Not Found"), response) fileServer = FileServer(self.directory, allowDirectoryListing=True) with open(join(self.directory, "dummy.txt"), "w") as f: f.write("Dummy") subdir = mkdir(self.directory, "subdir") with open(join(self.directory, subdir, 'The "real" <deal>.txt'), "w") as f: f.write("to test escaping") response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/")) self.assertTrue(response.startswith("HTTP/1.0 200 OK"), response) self.assertTrue("<title>Index of /</title>" in response, response) links = [ line for line in response.split("\n") if line.startswith("<a href") ] self.assertEqual(2, len(links)) self.assertTrue( links[0].startswith('<a href="dummy.txt">dummy.txt</a>'), links[0]) self.assertTrue(links[0].endswith(' 5'), links[0]) self.assertTrue(links[1].startswith('<a href="subdir/">subdir/</a>'), links[1]) response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/subdir")) self.assertTrue(response.startswith("HTTP/1.0 301 Moved Permanently"), response) response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/subdir/")) self.assertTrue("<title>Index of /subdir</title>" in response, response) links = [ line for line in response.split("\n") if line.startswith("<a href") ] self.assertEqual('<a href="../">../</a>', links[0]) self.assertTrue( links[1].startswith( '''<a href='The "real" <deal>.txt'>The "real" <deal>.txt</a>''' ), links[1]) self.assertTrue(links[1].endswith(' 16'), links[1]) subdir = mkdir(self.directory, "subdir2") response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/subdir2/")) self.assertTrue("<title>Index of /subdir2</title>" in response, response) links = [ line for line in response.split("\n") if line.startswith("<a href") ] self.assertTrue(1, len(links)) hrs = [line for line in response.split("\n") if line.strip() == "<hr>"] self.assertEqual(2, len(hrs)) response = generatorToString( fileServer.handleRequest(port=80, Client=('localhost', 9000), path="/does_not_exist/")) self.assertTrue(response.startswith("HTTP/1.0 404 Not Found"), response)