def _GetSuccessResponse(self, request_path, server_instance): '''Returns the Response from trying to render |path| with |server_instance|. If |path| isn't found then a FileNotFoundError will be raised, such that the only responses that will be returned from this method are Ok and Redirect. ''' content_provider, serve_from, path = ( server_instance.content_providers.GetByServeFrom(request_path)) assert content_provider, 'No ContentProvider found for %s' % path redirect = Redirector( server_instance.compiled_fs_factory, content_provider.file_system).Redirect(self._request.host, path) if redirect is not None: # Absolute redirects stay absolute, relative redirects are relative to # |serve_from|; all redirects eventually need to be *served* as absolute. if not redirect.startswith('/'): redirect = '/' + posixpath.join(serve_from, redirect) return Response.Redirect(redirect, permanent=False) canonical_path = content_provider.GetCanonicalPath(path) if canonical_path != path: redirect_path = posixpath.join(serve_from, canonical_path) return Response.Redirect('/' + redirect_path, permanent=False) if request_path.endswith('/'): # Directory request hasn't been redirected by now. Default behaviour is # to redirect as though it were a file. return Response.Redirect('/' + request_path.rstrip('/'), permanent=False) if not path: # Empty-path request hasn't been redirected by now. It doesn't exist. raise FileNotFoundError('Empty path') content_and_type = content_provider.GetContentAndType(path).Get() if not content_and_type.content: logging.error('%s had empty content' % path) content = content_and_type.content if isinstance(content, Handlebar): template_content, template_warnings = ( server_instance.template_renderer.Render(content, self._request)) # HACK: the site verification file (google2ed...) doesn't have a title. content, doc_warnings = server_instance.document_renderer.Render( template_content, path, render_title=path != SITE_VERIFICATION_FILE) warnings = template_warnings + doc_warnings if warnings: sep = '\n - ' logging.warning('Rendering %s:%s%s' % (path, sep, sep.join(warnings))) content_type = content_and_type.content_type if isinstance(content, unicode): content = content.encode('utf-8') content_type += '; charset=utf-8' return Response.Ok(content, headers=_MakeHeaders(content_type))
def test_big_body_redirect(self): url = self._get_url('redirect/4k_body') # should raise redirects error, ignore body size with self.assertRaises(redirector.RDCycleRedirectsException): Redirector(10, 100).resolve_redirects(url) with self.assertRaises(redirector.RDCycleRedirectsException): Redirector(10, 10000).resolve_redirects(url)
def m_redirect(self, msg): if msg.key not in self.redirectors: logging.info('redirect [%s]%s to %s' % ( msg.protocol, msg.local, msg.remote)) r = Redirector(msg) r.start() self.redirectors[msg.key] = r return {'ok': True} return {'ok': False}
def _GetSuccessResponse(self, path, server_instance): '''Returns the Response from trying to render |path| with |server_instance|. If |path| isn't found then a FileNotFoundError will be raised, such that the only responses that will be returned from this method are Ok and Redirect. ''' content_provider, path = ( server_instance.content_providers.GetByServeFrom(path)) assert content_provider, 'No ContentProvider found for %s' % path redirect = Redirector(server_instance.compiled_fs_factory, content_provider.file_system).Redirect( self._request.host, path) if redirect is not None: return Response.Redirect(redirect, permanent=False) content_and_type = content_provider.GetContentAndType( self._request.host, path).Get() if not content_and_type.content: logging.error('%s had empty content' % path) if isinstance(content_and_type.content, Handlebar): content_and_type.content = server_instance.template_renderer.Render( content_and_type.content, self._request) return Response.Ok(content_and_type.content, headers=_MakeHeaders(content_and_type.content_type))
def test_too_many_redirects(self): redirects_limit = 10 start_url = self._get_redirects_url(redirects_limit + 1) with self.assertRaises(redirector.RDTooManyRedirectsException): Redirector( max_redirects=redirects_limit).resolve_redirects(start_url)
def test_positive_redirects(self): redirects_limit = 10 start_url = self._get_redirects_url(redirects_limit) self.assertEqual( Redirector( max_redirects=redirects_limit).resolve_redirects(start_url), self.correct_url)
def __init__(self, settings, logs, folder): self.settings = settings self.logs = logs self.folder = folder self.redirector = Redirector(self.getPort(), "192.168.2.129", 26003, packet_size=65536) self.isRedirecting = False
def factory(global_conf, **app_conf): """create a sample redirector""" assert 'app.directory' in app_conf directory = app_conf['app.directory'] assert os.path.isdir(directory) keystr = 'redirector.' args = dict([(key.split(keystr, 1)[-1], value) for key, value in app_conf.items() if key.startswith(keystr) ]) app = StaticURLParser(directory) redirector = Redirector(app, **args) return HTTPExceptionHandler(redirector)
def __init__(self, ip, ports_to, port_from, packet_size): ''' Class for managing local port redirecting.\n Redirects one port to one from multiple.\n Arguments:\n ip - Server machine IP (on the network you port forward)\n ports_to - Ports to redirect to (ports of the servers)\n port_from - Port to redirect from (port the people use)\n packet_size - Bytes per data transfer (preferably power of 2) ''' self.loop = aio_loops.RedirectorLoop self.redirectors = {} for port_to in ports_to: self.redirectors[port_to] = Redirector(ip, port_to, port_from, packet_size) self.current = None self.queue = deque()
def _GetSuccessResponse(self, path, server_instance): '''Returns the Response from trying to render |path| with |server_instance|. If |path| isn't found then a FileNotFoundError will be raised, such that the only responses that will be returned from this method are Ok and Redirect. ''' content_provider, serve_from, path = ( server_instance.content_providers.GetByServeFrom(path)) assert content_provider, 'No ContentProvider found for %s' % path redirect = Redirector(server_instance.compiled_fs_factory, content_provider.file_system).Redirect( self._request.host, path) if redirect is not None: return Response.Redirect(redirect, permanent=False) canonical_path = content_provider.GetCanonicalPath(path) if canonical_path != path: redirect_path = posixpath.join(serve_from, canonical_path) return Response.Redirect('/' + redirect_path, permanent=False) content_and_type = content_provider.GetContentAndType(path).Get() if not content_and_type.content: logging.error('%s had empty content' % path) content = content_and_type.content if isinstance(content, Handlebar): template_content, template_warnings = ( server_instance.template_renderer.Render( content, self._request)) # HACK: the site verification file (google2ed...) doesn't have a title. content, doc_warnings = server_instance.document_renderer.Render( template_content, path, render_title=path != SITE_VERIFICATION_FILE) warnings = template_warnings + doc_warnings if warnings: sep = '\n - ' logging.warning('Rendering %s:%s%s' % (path, sep, sep.join(warnings))) content_type = content_and_type.content_type if isinstance(content, unicode): content = content.encode('utf-8') content_type += '; charset=utf-8' return Response.Ok(content, headers=_MakeHeaders(content_type))
class RedirectorTest(unittest.TestCase): def setUp(self): self._redirector = Redirector( CompiledFileSystem.Factory(file_system, ObjectStoreCreator.ForTest()), file_system, 'public') def testExternalRedirection(self): self.assertEqual('http://something.absolute.com/', self._redirector.Redirect(HOST, 'index.html')) self.assertEqual( 'http://lmgtfy.com', self._redirector.Redirect(HOST, 'extensions/manifest/more-info')) def testAbsoluteRedirection(self): self.assertEqual('/apps/about_apps.html', self._redirector.Redirect(HOST, 'apps/index.html')) self.assertEqual('/index.html', self._redirector.Redirect(HOST, '')) self.assertEqual('/index.html', self._redirector.Redirect(HOST, 'home')) def testRelativeRedirection(self): self.assertEqual( '/extensions/manifest.html', self._redirector.Redirect(HOST, 'extensions/manifest/')) self.assertEqual( '/extensions/manifest.html', self._redirector.Redirect(HOST, 'extensions/manifest')) self.assertEqual('/index.html', self._redirector.Redirect(HOST, 'apps/')) def testNotFound(self): self.assertEqual(None, self._redirector.Redirect(HOST, 'not/a/real/path')) self.assertEqual( None, self._redirector.Redirect(HOST, 'public/apps/okay.html')) def testOldHosts(self): self.assertEqual( 'https://developer.chrome.com/', self._redirector.Redirect('http://code.google.com', '')) self.assertEqual( 'https://developer.chrome.com/', self._redirector.Redirect('https://code.google.com', '')) def testCron(self): self._redirector.Cron() expected_paths = set([ 'public/redirects.json', 'public/apps/redirects.json', 'public/extensions/redirects.json', 'public/extensions/manifest/redirects.json' ]) for path in expected_paths: self.assertEqual( Parse(file_system.ReadSingle(path)), # Access the cache's object store to see what files were hit during # the cron run. Returns strings parsed as JSON. self._redirector._cache._file_object_store.Get( path).Get()._cache_data)
def __init__(self, channel, object_store_creator, host_file_system, app_samples_file_system, base_path, compiled_fs_factory): self.channel = channel self.object_store_creator = object_store_creator self.host_file_system = host_file_system self.app_samples_file_system = app_samples_file_system self.compiled_host_fs_factory = compiled_fs_factory self.api_list_data_source_factory = APIListDataSource.Factory( self.compiled_host_fs_factory, svn_constants.API_PATH, svn_constants.PUBLIC_TEMPLATE_PATH) self.api_data_source_factory = APIDataSource.Factory( self.compiled_host_fs_factory, svn_constants.API_PATH) self.ref_resolver_factory = ReferenceResolver.Factory( self.api_data_source_factory, self.api_list_data_source_factory, object_store_creator) self.api_data_source_factory.SetReferenceResolverFactory( self.ref_resolver_factory) # Note: samples are super slow in the dev server because it doesn't support # async fetch, so disable them. if IsDevServer(): extension_samples_fs = EmptyDirFileSystem() else: extension_samples_fs = self.host_file_system self.samples_data_source_factory = SamplesDataSource.Factory( channel, extension_samples_fs, CompiledFileSystem.Factory(extension_samples_fs, object_store_creator), self.app_samples_file_system, CompiledFileSystem.Factory(self.app_samples_file_system, object_store_creator), self.ref_resolver_factory, svn_constants.EXAMPLES_PATH) self.api_data_source_factory.SetSamplesDataSourceFactory( self.samples_data_source_factory) self.intro_data_source_factory = IntroDataSource.Factory( self.compiled_host_fs_factory, self.ref_resolver_factory, [svn_constants.INTRO_PATH, svn_constants.ARTICLE_PATH]) self.sidenav_data_source_factory = SidenavDataSource.Factory( self.compiled_host_fs_factory, svn_constants.JSON_PATH, base_path) self.template_data_source_factory = TemplateDataSource.Factory( channel, self.api_data_source_factory, self.api_list_data_source_factory, self.intro_data_source_factory, self.samples_data_source_factory, self.sidenav_data_source_factory, self.compiled_host_fs_factory, self.ref_resolver_factory, svn_constants.PUBLIC_TEMPLATE_PATH, svn_constants.PRIVATE_TEMPLATE_PATH, base_path) self.example_zipper = ExampleZipper(self.compiled_host_fs_factory, svn_constants.DOCS_PATH) self.path_canonicalizer = PathCanonicalizer( channel, self.compiled_host_fs_factory) self.content_cache = self.compiled_host_fs_factory.CreateIdentity( ServerInstance) self.redirector = Redirector(self.compiled_host_fs_factory, self.host_file_system, svn_constants.PUBLIC_TEMPLATE_PATH)
def _GetSuccessResponse(self, request_path, server_instance): '''Returns the Response from trying to render |path| with |server_instance|. If |path| isn't found then a FileNotFoundError will be raised, such that the only responses that will be returned from this method are Ok and Redirect. ''' content_provider, serve_from, path = ( server_instance.content_providers.GetByServeFrom(request_path)) assert content_provider, 'No ContentProvider found for %s' % path redirect = Redirector( server_instance.compiled_fs_factory, content_provider.file_system).Redirect(self._request.host, path) if redirect is not None: # Absolute redirects stay absolute, relative redirects are relative to # |serve_from|; all redirects eventually need to be *served* as absolute. if not redirect.startswith(('/', 'http://', 'https://')): redirect = '/' + posixpath.join(serve_from, redirect) return Response.Redirect(redirect, permanent=False) canonical_path = content_provider.GetCanonicalPath(path) if canonical_path != path: redirect_path = posixpath.join(serve_from, canonical_path) return Response.Redirect('/' + redirect_path, permanent=False) if request_path.endswith('/'): # Directory request hasn't been redirected by now. Default behaviour is # to redirect as though it were a file. return Response.Redirect('/' + request_path.rstrip('/'), permanent=False) content_and_type = content_provider.GetContentAndType(path).Get() if not content_and_type.content: logging.error('%s had empty content' % path) content = content_and_type.content if isinstance(content, Motemplate): template_content, template_warnings = ( server_instance.template_renderer.Render(content, self._request)) # HACK: the site verification file (google2ed...) doesn't have a title. content, doc_warnings = server_instance.document_renderer.Render( template_content, path, render_title=path != SITE_VERIFICATION_FILE) warnings = template_warnings + doc_warnings if warnings: sep = '\n - ' logging.warning('Rendering %s:%s%s' % (path, sep, sep.join(warnings))) # Content was dynamic. The new etag is a hash of the content. etag = None elif content_and_type.version is not None: # Content was static. The new etag is the version of the content. Hash it # to make sure it's valid. etag = '"%s"' % hashlib.md5(str(content_and_type.version)).hexdigest() else: # Sometimes non-dynamic content does not have a version, for example # .zip files. The new etag is a hash of the content. etag = None content_type = content_and_type.content_type if isinstance(content, unicode): content = content.encode('utf-8') content_type += '; charset=utf-8' if etag is None: # Note: we're using md5 as a convenient and fast-enough way to identify # content. It's not intended to be cryptographic in any way, and this # is *not* what etags is for. That's what SSL is for, this is unrelated. etag = '"%s"' % hashlib.md5(content).hexdigest() headers = _MakeHeaders(content_type, etag=etag) if etag == self._request.headers.get('If-None-Match'): return Response.NotModified('Not Modified', headers=headers) return Response.Ok(content, headers=headers)
def __init__(self, object_store_creator, host_file_system, app_samples_file_system, base_path, compiled_fs_factory, branch_utility, host_file_system_creator): self.object_store_creator = object_store_creator self.host_file_system = host_file_system self.app_samples_file_system = app_samples_file_system self.compiled_host_fs_factory = compiled_fs_factory self.host_file_system_creator = host_file_system_creator self.availability_finder_factory = AvailabilityFinder.Factory( object_store_creator, self.compiled_host_fs_factory, branch_utility, host_file_system_creator) self.api_list_data_source_factory = APIListDataSource.Factory( self.compiled_host_fs_factory, self.host_file_system, svn_constants.API_PATH, svn_constants.PUBLIC_TEMPLATE_PATH) self.api_data_source_factory = APIDataSource.Factory( self.compiled_host_fs_factory, svn_constants.API_PATH, self.availability_finder_factory) self.ref_resolver_factory = ReferenceResolver.Factory( self.api_data_source_factory, self.api_list_data_source_factory, object_store_creator) self.api_data_source_factory.SetReferenceResolverFactory( self.ref_resolver_factory) # Note: samples are super slow in the dev server because it doesn't support # async fetch, so disable them. if IsDevServer(): extension_samples_fs = EmptyDirFileSystem() else: extension_samples_fs = self.host_file_system self.samples_data_source_factory = SamplesDataSource.Factory( extension_samples_fs, CompiledFileSystem.Factory(extension_samples_fs, object_store_creator), self.app_samples_file_system, CompiledFileSystem.Factory(self.app_samples_file_system, object_store_creator), self.ref_resolver_factory, svn_constants.EXAMPLES_PATH, base_path) self.api_data_source_factory.SetSamplesDataSourceFactory( self.samples_data_source_factory) self.intro_data_source_factory = IntroDataSource.Factory( self.compiled_host_fs_factory, self.ref_resolver_factory, [svn_constants.INTRO_PATH, svn_constants.ARTICLE_PATH]) self.sidenav_data_source_factory = SidenavDataSource.Factory( self.compiled_host_fs_factory, svn_constants.JSON_PATH) self.manifest_data_source = ManifestDataSource( self.compiled_host_fs_factory, host_file_system, '/'.join( (svn_constants.JSON_PATH, 'manifest.json')), '/'.join( (svn_constants.API_PATH, '_manifest_features.json'))) self.template_data_source_factory = TemplateDataSource.Factory( self.api_data_source_factory, self.api_list_data_source_factory, self.intro_data_source_factory, self.samples_data_source_factory, self.sidenav_data_source_factory, self.compiled_host_fs_factory, self.ref_resolver_factory, self.manifest_data_source, svn_constants.PUBLIC_TEMPLATE_PATH, svn_constants.PRIVATE_TEMPLATE_PATH, base_path) self.api_data_source_factory.SetTemplateDataSource( self.template_data_source_factory) self.example_zipper = ExampleZipper(self.compiled_host_fs_factory, self.host_file_system, svn_constants.DOCS_PATH) self.path_canonicalizer = PathCanonicalizer( self.compiled_host_fs_factory) self.redirector = Redirector(self.compiled_host_fs_factory, self.host_file_system, svn_constants.PUBLIC_TEMPLATE_PATH)
def g(): Redirector().main()
def solve(Ma, Mw): write_graph(Ma, Mw, [], 'tmp', int_weights=True) redirector_stdout = Redirector(fd=STDOUT) redirector_stderr = Redirector(fd=STDERR) redirector_stderr.start() redirector_stdout.start() solver = TSPSolver.from_tspfile('tmp') solution = solver.solve(verbose=False) redirector_stderr.stop() redirector_stdout.stop() return solution.tour if solution.found_tour else []
def solve(Ma, Mw): """ Invokes Concorde to solve a TSP instance Uses Python's Redirector library to prevent Concorde from printing unsufferably verbose messages """ STDOUT = 1 STDERR = 2 redirector_stdout = Redirector(fd=STDOUT) redirector_stderr = Redirector(fd=STDERR) # Write graph on a temporary file write_graph(Ma, Mw, filepath='tmp', int_weights=True) redirector_stderr.start() redirector_stdout.start() # Solve TSP on graph solver = TSPSolver.from_tspfile('tmp') # Get solution solution = solver.solve(verbose=False) redirector_stderr.stop() redirector_stdout.stop() """ Concorde solves only symmetric TSP instances. To circumvent this, we fill inexistent edges with large weights. Concretely, an inexistent edge is assigned with the strictest upper limit to the cost of an optimal tour, which is n (the number of nodes) times 1 (the maximum weight). If one of these edges is used in the optimal solution, we can deduce that no valid tour exists (as just one of these edges costs more than all the others combined). OBS. in this case the maximum weight 1 is multiplied by 'bins' because we are converting from floating point to integers """ if any([ Ma[i, j] == 0 for (i, j) in zip(list(solution.tour), list(solution.tour)[1:] + list(solution.tour)[:1]) ]): return None else: return list(solution.tour)
def test_no_redirects(self): self.assertEqual(Redirector().resolve_redirects(self.correct_url), self.correct_url)
class RedirectorTest(unittest.TestCase): def setUp(self): self._redirector = Redirector( CompiledFileSystem.Factory(ObjectStoreCreator.ForTest()), file_system) def testExternalRedirection(self): self.assertEqual( 'http://something.absolute.com/', self._redirector.Redirect(HOST, 'index.html')) self.assertEqual( 'http://lmgtfy.com', self._redirector.Redirect(HOST, 'extensions/manifest/more-info')) def testAbsoluteRedirection(self): self.assertEqual( '/index.html', self._redirector.Redirect(HOST, '')) self.assertEqual( '/bar.html', self._redirector.Redirect(HOST, 'apps/foo.html')) def testRelativeRedirection(self): self.assertEqual( 'apps/about_apps.html', self._redirector.Redirect(HOST, 'apps/index.html')) self.assertEqual( 'extensions/manifest.html', self._redirector.Redirect(HOST, 'extensions/manifest/')) self.assertEqual( 'extensions/manifest.html', self._redirector.Redirect(HOST, 'extensions/manifest')) self.assertEqual( 'index.html', self._redirector.Redirect(HOST, 'apps/')) self.assertEqual( 'index.html', self._redirector.Redirect(HOST, 'home')) def testNotFound(self): self.assertEqual( None, self._redirector.Redirect(HOST, 'not/a/real/path')) self.assertEqual( None, self._redirector.Redirect(HOST, 'public/apps/okay.html')) def testOldHosts(self): self.assertEqual( 'https://developer.chrome.com/', self._redirector.Redirect('http://code.google.com', '')) self.assertEqual( 'https://developer.chrome.com/', self._redirector.Redirect('https://code.google.com', '')) def testCron(self): self._redirector.Cron().Get() expected_paths = set([ 'redirects.json', 'apps/redirects.json', 'extensions/redirects.json', 'extensions/manifest/redirects.json' ]) for path in expected_paths: self.assertEqual( Parse(file_system.ReadSingle(path).Get()), # Access the cache's object store to see what files were hit during # the cron run. Returns strings parsed as JSON. # TODO(jshumway): Make a non hack version of this check. self._redirector._cache._file_object_store.Get( path).Get()._cache_data) def testDirectoryRedirection(self): # Simple redirect. self.assertEqual( 'extensions/manifest.html', self._redirector.Redirect(HOST, 'extensions/dev/manifest')) # Multiple hops with one file. self.assertEqual( 'extensions/r4/manifest.html', self._redirector.Redirect(HOST, 'extensions/r1/manifest')) # Multiple hops w/ multiple redirection files. self.assertEqual( 'extensions/r6/directory/manifest.html', self._redirector.Redirect(HOST, 'extensions/r5/manifest')) # Redirection from root directory redirector. self.assertEqual( 'apps/about_apps.html', self._redirector.Redirect(HOST, 'foo/index.html')) # Short to long. self.assertEqual( 'extensions/short/index.html', self._redirector.Redirect(HOST, 'extensions/a/very/long/dir/chain/index')) # Long to short. self.assertEqual( 'extensions/another/long/chain/index.html', self._redirector.Redirect(HOST, 'extensions/_short/index')) # Directory redirection without a redirects.json in final directory. self.assertEqual( 'extensions/noredirects2/file', self._redirector.Redirect(HOST, 'extensions/noredirects1/file')) # Directory redirection with redirects.json without rule for the filename. self.assertEqual( 'extensions/nofile2/file', self._redirector.Redirect(HOST, 'extensions/nofile1/file')) # Relative directory path. self.assertEqual( 'index.html', self._redirector.Redirect(HOST, 'relative_directory/home')) # Shallower directory redirects have priority. self.assertEqual( 'priority/GOOD/index', self._redirector.Redirect(HOST, 'priority/directory/index')) # Don't infinitely redirect. self.assertEqual('infinite_redirect/loop/index', self._redirector.Redirect(HOST, 'infinite_redirect/index')) # If a parent directory is redirected, redirect children properly. self.assertEqual('parent_redirect/b/c/index', self._redirector.Redirect(HOST, 'parent_redirect/a/c/index'))
'extensions': { 'redirects.json': json.dumps({ 'manifest': 'manifest.html' }), 'manifest': { 'redirects.json': json.dumps({ '': '../manifest.html', 'more-info': 'http://lmgtfy.com' }) } } } }) redirector = Redirector( CompiledFileSystem.Factory(file_system, ObjectStoreCreator.ForTest()), None, 'public') class RedirectorTest(unittest.TestCase): def testExternalRedirection(self): self.assertEqual( 'http://something.absolute.com/', redirector.Redirect(HOST, 'index.html')) self.assertEqual( 'http://lmgtfy.com', redirector.Redirect(HOST, 'extensions/manifest/more-info')) def testAbsoluteRedirection(self): self.assertEqual( '/apps/about_apps.html', redirector.Redirect(HOST, 'apps/index.html')) self.assertEqual(
def test_cycle_redirects(self): start_url = self._get_redirects_url(-1) with self.assertRaises(redirector.RDCycleRedirectsException): Redirector().resolve_redirects(start_url)
def test_big_body(self): content_limit = 1000 url = self._get_url('limitless_body') with self.assertRaises(redirector.RDTooBigBodyException): Redirector(content_limit=content_limit).resolve_redirects(url)
def _GetSuccessResponse(self, request_path, server_instance): '''Returns the Response from trying to render |path| with |server_instance|. If |path| isn't found then a FileNotFoundError will be raised, such that the only responses that will be returned from this method are Ok and Redirect. ''' content_provider, serve_from, path = ( server_instance.content_providers.GetByServeFrom(request_path)) assert content_provider, 'No ContentProvider found for %s' % path redirect = Redirector(server_instance.compiled_fs_factory, content_provider.file_system).Redirect( self._request.host, path) if redirect is not None: # Absolute redirects stay absolute, relative redirects are relative to # |serve_from|; all redirects eventually need to be *served* as absolute. if not redirect.startswith('/'): redirect = '/' + posixpath.join(serve_from, redirect) return Response.Redirect(redirect, permanent=False) canonical_path = content_provider.GetCanonicalPath(path) if canonical_path != path: redirect_path = posixpath.join(serve_from, canonical_path) return Response.Redirect('/' + redirect_path, permanent=False) if request_path.endswith('/'): # Directory request hasn't been redirected by now. Default behaviour is # to redirect as though it were a file. return Response.Redirect('/' + request_path.rstrip('/'), permanent=False) if not path: # Empty-path request hasn't been redirected by now. It doesn't exist. raise FileNotFoundError('Empty path') content_and_type = content_provider.GetContentAndType(path).Get() if not content_and_type.content: logging.error('%s had empty content' % path) content = content_and_type.content if isinstance(content, Handlebar): template_content, template_warnings = ( server_instance.template_renderer.Render( content, self._request)) # HACK: the site verification file (google2ed...) doesn't have a title. content, doc_warnings = server_instance.document_renderer.Render( template_content, path, render_title=path != SITE_VERIFICATION_FILE) warnings = template_warnings + doc_warnings if warnings: sep = '\n - ' logging.warning('Rendering %s:%s%s' % (path, sep, sep.join(warnings))) # Content was dynamic. The new etag is a hash of the content. etag = None elif content_and_type.version is not None: # Content was static. The new etag is the version of the content. Hash it # to make sure it's valid. etag = '"%s"' % hashlib.md5(str( content_and_type.version)).hexdigest() else: # Sometimes non-dynamic content does not have a version, for example # .zip files. The new etag is a hash of the content. etag = None content_type = content_and_type.content_type if isinstance(content, unicode): content = content.encode('utf-8') content_type += '; charset=utf-8' if etag is None: # Note: we're using md5 as a convenient and fast-enough way to identify # content. It's not intended to be cryptographic in any way, and this # is *not* what etags is for. That's what SSL is for, this is unrelated. etag = '"%s"' % hashlib.md5(content).hexdigest() headers = _MakeHeaders(content_type, etag=etag) if etag == self._request.headers.get('If-None-Match'): return Response.NotModified('Not Modified', headers=headers) return Response.Ok(content, headers=headers)
def setUp(self): self._redirector = Redirector( CompiledFileSystem.Factory(file_system, ObjectStoreCreator.ForTest()), file_system, 'public')