def lookup_app(self, environ): # Check again if the branch is blocked from being served, this is # mostly for tests. It's already checked in apps/transport.py if not self.branch.get_config().get_user_option_as_bool('http_serve', default=True): raise httpexceptions.HTTPNotFound() self._url_base = environ['SCRIPT_NAME'] self._path_info = environ['PATH_INFO'] self._static_url_base = environ.get('loggerhead.static.url') if self._static_url_base is None: self._static_url_base = self._url_base self._environ = environ if self.served_url is _DEFAULT: public_branch = self.public_branch_url() if public_branch is not None: self.served_url = public_branch else: self.served_url = wsgiref.util.application_uri(environ) for hook in self.hooks['controller']: controller = hook(self, environ) if controller is not None: return controller path = request.path_info_pop(environ) if not path: raise httpexceptions.HTTPMovedPermanently( self.absolute_url('/changes')) if path == 'static': return static_app elif path == '+json': environ['loggerhead.as_json'] = True path = request.path_info_pop(environ) cls = self.controllers_dict.get(path) if cls is not None: return cls(self, self.get_history) raise httpexceptions.HTTPNotFound()
def _resolve_map_match(self, map_match, path_info, controllers, use_default=True): # Get the controller class controller_name = map_match.pop('controller', None) controller = controllers.get(controller_name, None) if controller is None: raise httpexceptions.HTTPNotFound("No controller for " + path_info) # Resolve action method on controller # This is the easiest way to make the controller/action accessible for # url_for invocations. Specifically, grids. action = map_match.pop('action', 'index') method = getattr(controller, action, None) if method is None and not use_default: # Skip default, we do this, for example, when we want to fail # through to another mapper. raise httpexceptions.HTTPNotFound("No action for " + path_info) if method is None: # no matching method, we try for a default method = getattr(controller, 'default', None) if method is None: raise httpexceptions.HTTPNotFound("No action for " + path_info) # Is the method exposed if not getattr(method, 'exposed', False): raise httpexceptions.HTTPNotFound("Action not exposed for " + path_info) # Is the method callable if not callable(method): raise httpexceptions.HTTPNotFound("Action not callable for " + path_info) return (controller_name, controller, action, method)
def handle_request(self, environ, start_response): # Grab the request_id (should have been set by middleware) request_id = environ.get('request_id', 'unknown') # Map url using routes path_info = environ.get('PATH_INFO', '') map = self.mapper.match(path_info, environ) if path_info.startswith('/api'): environ['is_api_request'] = True controllers = self.api_controllers else: environ['is_api_request'] = False controllers = self.controllers if map == None: raise httpexceptions.HTTPNotFound("No route for " + path_info) self.trace(path_info=path_info, map=map) # Setup routes rc = routes.request_config() rc.mapper = self.mapper rc.mapper_dict = map rc.environ = environ # Setup the transaction trans = self.transaction_factory(environ) trans.request_id = request_id rc.redirect = trans.response.send_redirect # Get the controller class controller_name = map.pop('controller', None) controller = controllers.get(controller_name, None) if controller_name is None: raise httpexceptions.HTTPNotFound("No controller for " + path_info) # Resolve action method on controller action = map.pop('action', 'index') # This is the easiest way to make the controller/action accessible for # url_for invocations. Specifically, grids. trans.controller = controller_name trans.action = action method = getattr(controller, action, None) if method is None: method = getattr(controller, 'default', None) if method is None: raise httpexceptions.HTTPNotFound("No action for " + path_info) # Is the method exposed if not getattr(method, 'exposed', False): raise httpexceptions.HTTPNotFound("Action not exposed for " + path_info) # Is the method callable if not callable(method): raise httpexceptions.HTTPNotFound("Action not callable for " + path_info) # Combine mapper args and query string / form args and call kwargs = trans.request.params.mixed() kwargs.update(map) # Special key for AJAX debugging, remove to avoid confusing methods kwargs.pop('_', None) try: body = method(trans, **kwargs) except Exception, e: body = self.handle_controller_exception(e, trans, **kwargs) if not body: raise
def __call__(self, environ, start_response): """ Call interface as specified by WSGI. Wraps the environment in user friendly objects, finds the appropriate method to handle the request and calls it. """ # Map url using routes path_info = environ.get('PATH_INFO', '') map = self.mapper.match(path_info, environ) if map is None: environ['is_api_request'] = True map = self.api_mapper.match(path_info, environ) mapper = self.api_mapper controllers = self.api_controllers else: mapper = self.mapper controllers = self.controllers if map == None: raise httpexceptions.HTTPNotFound("No route for " + path_info) # Setup routes rc = routes.request_config() rc.mapper = mapper rc.mapper_dict = map rc.environ = environ # Setup the transaction trans = self.transaction_factory(environ) rc.redirect = trans.response.send_redirect # Get the controller class controller_name = map.pop('controller', None) controller = controllers.get(controller_name, None) if controller_name is None: raise httpexceptions.HTTPNotFound("No controller for " + path_info) # Resolve action method on controller action = map.pop('action', 'index') method = getattr(controller, action, None) if method is None: method = getattr(controller, 'default', None) if method is None: raise httpexceptions.HTTPNotFound("No action for " + path_info) # Is the method exposed if not getattr(method, 'exposed', False): raise httpexceptions.HTTPNotFound("Action not exposed for " + path_info) # Is the method callable if not callable(method): raise httpexceptions.HTTPNotFound("Action not callable for " + path_info) # Combine mapper args and query string / form args and call kwargs = trans.request.params.mixed() kwargs.update(map) # Special key for AJAX debugging, remove to avoid confusing methods kwargs.pop('_', None) try: body = method(trans, **kwargs) except Exception, e: body = self.handle_controller_exception(e, trans, **kwargs) if not body: raise
def __call__(self, environ, start_response): # /download/<rev_id>/<filename> h = self._history args = self.get_args(environ) if len(args) < 2: raise httpexceptions.HTTPMovedPermanently( self._branch.absolute_url('/changes')) revid = h.fix_revid(args[0]) try: path, filename, content = h.get_file(args[1], revid) except (NoSuchFile, NoSuchRevision): # Compatibility API for /download/rev_id/file_id/<filename> try: path, filename, content = h.get_file_by_fileid( args[1].encode('UTF-8'), revid) except (NoSuchId, NoSuchRevision): raise httpexceptions.HTTPNotFound() mime_type, encoding = mimetypes.guess_type(filename) if mime_type is None: mime_type = 'application/octet-stream' self.log.info('/download %s @ %s (%d bytes)', path, h.get_revno(revid), len(content)) encoded_filename = self.encode_filename(filename) headers = [ ('Content-Type', mime_type), ('Content-Length', str(len(content))), ('Content-Disposition', "attachment; filename*=utf-8''%s" % (encoded_filename,)), ] start_response('200 OK', headers) return [content]
def not_found(self, environ, start_response, debug_message=None): exc = httpexceptions.HTTPNotFound( 'The resource at %s could not be found' % request.construct_url(environ), comment='SCRIPT_NAME=%r; PATH_INFO=%r; looking in %r; debug: %s' % (environ.get('SCRIPT_NAME'), environ.get('PATH_INFO'), self.directory, debug_message or '(none)')) return exc.wsgi_application(environ, start_response)
def handle_request(self, environ, start_response, body_renderer=None): # Grab the request_id (should have been set by middleware) request_id = environ.get('request_id', 'unknown') # Map url using routes path_info = environ.get('PATH_INFO', '') client_match = self.clientside_routes.match(path_info, environ) map_match = self.mapper.match(path_info, environ) or client_match if path_info.startswith('/api'): environ['is_api_request'] = True controllers = self.api_controllers else: environ['is_api_request'] = False controllers = self.controllers if map_match is None: raise httpexceptions.HTTPNotFound("No route for " + path_info) self.trace(path_info=path_info, map_match=map_match) # Setup routes rc = routes.request_config() rc.mapper = self.mapper rc.mapper_dict = map_match rc.environ = environ # Setup the transaction trans = self.transaction_factory(environ) trans.request_id = request_id rc.redirect = trans.response.send_redirect # Resolve mapping to controller/method try: # We don't use default methods if there's a clientside match for this route. use_default = client_match is None controller_name, controller, action, method = self._resolve_map_match( map_match, path_info, controllers, use_default=use_default) except httpexceptions.HTTPNotFound: # Failed, let's check client routes if not environ['is_api_request'] and client_match is not None: controller_name, controller, action, method = self._resolve_map_match( client_match, path_info, controllers) else: raise trans.controller = controller_name trans.action = action environ['controller_action_key'] = "%s.%s.%s" % ( 'api' if environ['is_api_request'] else 'web', controller_name, action or 'default') # Combine mapper args and query string / form args and call kwargs = trans.request.params.mixed() kwargs.update(map_match) # Special key for AJAX debugging, remove to avoid confusing methods kwargs.pop('_', None) try: body = method(trans, **kwargs) except Exception as e: body = self.handle_controller_exception(e, trans, **kwargs) if not body: raise body_renderer = body_renderer or self._render_body return body_renderer(trans, body, environ, start_response)
def serve_file(filename): """Create a WSGI application that return a static file In: - ``filename`` -- path of the file to serve Return: - a WSGI application """ return httpexceptions.HTTPNotFound( ) if filename is None else fileapp.FileApp(filename)
def new_application(environ, start_response): try: return application(environ, start_response) except (IOError, OSError), e: import errno from paste import httpexceptions if e.errno == errno.ENOENT: raise httpexceptions.HTTPNotFound() elif e.errno == errno.EACCES: raise httpexceptions.HTTPForbidden() else: raise
def debug(self, environ, start_response): assert request.path_info_pop(environ) == '_debug' next_part = request.path_info_pop(environ) method = getattr(self, next_part, None) if not method: exc = httpexceptions.HTTPNotFound( '%r not found when parsing %r' % (next_part, wsgilib.construct_url(environ))) return exc.wsgi_application(environ, start_response) if not getattr(method, 'exposed', False): exc = httpexceptions.HTTPForbidden('%r not allowed' % next_part) return exc.wsgi_application(environ, start_response) return method(environ, start_response)
def lookup_app(self, environ): # Check again if the branch is blocked from being served, this is # mostly for tests. It's already checked in apps/transport.py if self.branch.get_config().get_user_option('http_serve') == 'False': raise httpexceptions.HTTPNotFound() self._url_base = environ['SCRIPT_NAME'] self._static_url_base = environ.get('loggerhead.static.url') if self._static_url_base is None: self._static_url_base = self._url_base self._environ = environ if self.served_url is _DEFAULT: public_branch = self.public_branch_url() if public_branch is not None: self.served_url = public_branch else: # Loggerhead only supports serving .bzr/ on local branches, so # we shouldn't suggest something that won't work. try: util.local_path_from_url(self.branch.base) self.served_url = self.url([]) except breezy.errors.InvalidURL: self.served_url = None for hook in self.hooks['controller']: controller = hook(self, environ) if controller is not None: return controller path = request.path_info_pop(environ) if not path: raise httpexceptions.HTTPMovedPermanently( self.absolute_url('/changes')) if path == 'static': return static_app elif path == '+json': environ['loggerhead.as_json'] = True path = request.path_info_pop(environ) cls = self.controllers_dict.get(path) if cls is not None: return cls(self, self.get_history) raise httpexceptions.HTTPNotFound()
def not_found_app(self, environ, start_response): mapper = environ.get('paste.urlmap_object') if mapper: matches = [p for p, a in mapper.applications] extra = 'defined apps: %s' % (',\n '.join(map(repr, matches))) else: extra = '' extra += '\nSCRIPT_NAME: %r' % html.escape(environ.get('SCRIPT_NAME')) extra += '\nPATH_INFO: %r' % html.escape(environ.get('PATH_INFO')) extra += '\nHTTP_HOST: %r' % html.escape(environ.get('HTTP_HOST')) app = httpexceptions.HTTPNotFound( environ['PATH_INFO'], comment=html.escape(extra)).wsgi_application return app(environ, start_response)
def app_for_bazaar_data(self, relpath): if relpath == '/.bzr/smart': root_transport = get_transport_for_thread(self.root.base) wsgi_app = wsgi.SmartWSGIApp(root_transport) return wsgi.RelpathSetter(wsgi_app, '', 'loggerhead.path_info') else: # TODO: Use something here that uses the transport API # rather than relying on the local filesystem API. base = self.transport.base try: path = util.local_path_from_url(base) except errors.InvalidURL: raise httpexceptions.HTTPNotFound() else: return urlparser.make_static(None, path)
def not_found_exception(self, environ, start_response, debug_message=None): """add??? :param environ: add??? :param start_response: add?? :param debug_message: add???. Default value is ``None`` :returns: add??? """ exc = httpexceptions.HTTPNotFound( 'The resource at %s could not be found' % paste_request.construct_url(environ), comment='SCRIPT_NAME=%r; PATH_INFO=%r; debug: %s' % (environ.get('SCRIPT_NAME'), environ.get('PATH_INFO'), debug_message or '(none)')) return exc.wsgi_application(environ, start_response)
def __call__(self, environ, start_response): path = environ['PATH_INFO'] try: b = branch.Branch.open_from_transport(self.transport) except errors.NotBranchError: if path.startswith('/.bzr'): self.check_serveable(LocationConfig(self.transport.base)) return self.app_for_bazaar_data(path)(environ, start_response) if not self.transport.listable() or not self.transport.has('.'): raise httpexceptions.HTTPNotFound() return self.app_for_non_branch(environ)(environ, start_response) else: self.check_serveable(b.get_config()) if path.startswith('/.bzr'): return self.app_for_bazaar_data(path)(environ, start_response) else: return self.app_for_branch(b)(environ, start_response)
def dispatch(self, controller, environ, start_response): """Dispatches to a controller, will instantiate the controller if necessary. Override this to change how the controller dispatch is handled. """ log_debug = self.log_debug if not controller: if log_debug: log.debug("No controller found, returning 404 HTTP Not Found") not_found = httpexceptions.HTTPNotFound() return not_found.wsgi_application(environ, start_response) match = environ['pylons.routes_dict'] # Older subclass of Controller if inspect.isclass(controller) and \ not issubclass(controller, WSGIController) and \ issubclass(controller, Controller): controller = controller() controller.start_response = start_response controller._pylons_log_debug = log_debug if log_debug: log.debug("Calling older Controller subclass") return controller(**match) # If it's a class, instantiate it if not hasattr(controller, '__class__') or \ getattr(controller, '__class__') == type: if log_debug: log.debug("Controller appears to be a class, instantiating") controller = controller() controller._pylons_log_debug = log_debug # Controller is assumed to handle a WSGI call if log_debug: log.debug("Calling controller class with WSGI interface") return controller(environ, start_response)
def handle_request(self, environ, start_response): # Grab the request_id (should have been set by middleware) request_id = environ.get('request_id', 'unknown') # Map url using routes path_info = environ.get('PATH_INFO', '') map = self.mapper.match(path_info, environ) if path_info.startswith('/api'): environ['is_api_request'] = True controllers = self.api_controllers else: environ['is_api_request'] = False controllers = self.controllers if map is None: raise httpexceptions.HTTPNotFound("No route for " + path_info) self.trace(path_info=path_info, map=map) # Setup routes rc = routes.request_config() rc.mapper = self.mapper rc.mapper_dict = map rc.environ = environ # Setup the transaction trans = self.transaction_factory(environ) trans.request_id = request_id rc.redirect = trans.response.send_redirect # Get the controller class controller_name = map.pop('controller', None) controller = controllers.get(controller_name, None) if controller_name is None: raise httpexceptions.HTTPNotFound("No controller for " + path_info) # Resolve action method on controller action = map.pop('action', 'index') # This is the easiest way to make the controller/action accessible for # url_for invocations. Specifically, grids. trans.controller = controller_name trans.action = action method = getattr(controller, action, None) if method is None: method = getattr(controller, 'default', None) if method is None: raise httpexceptions.HTTPNotFound("No action for " + path_info) # Is the method exposed if not getattr(method, 'exposed', False): raise httpexceptions.HTTPNotFound("Action not exposed for " + path_info) # Is the method callable if not callable(method): raise httpexceptions.HTTPNotFound("Action not callable for " + path_info) environ['controller_action_key'] = "%s.%s.%s" % ( 'api' if environ['is_api_request'] else 'web', controller_name, action or 'default') # Combine mapper args and query string / form args and call kwargs = trans.request.params.mixed() kwargs.update(map) # Special key for AJAX debugging, remove to avoid confusing methods kwargs.pop('_', None) try: body = method(trans, **kwargs) except Exception as e: body = self.handle_controller_exception(e, trans, **kwargs) if not body: raise # Now figure out what we got back and try to get it to the browser in # a smart way if callable(body): # Assume the callable is another WSGI application to run return body(environ, start_response) elif isinstance(body, types.FileType): # Stream the file back to the browser return send_file(start_response, trans, body) elif isinstance(body, tarfile.ExFileObject): # Stream the tarfile member back to the browser body = iterate_file(body) start_response(trans.response.wsgi_status(), trans.response.wsgi_headeritems()) return body else: start_response(trans.response.wsgi_status(), trans.response.wsgi_headeritems()) return self.make_body_iterable(trans, body)
def check_serveable(self, config): value = config.get_user_option('http_serve') if value is None: return elif not _bools.get(value.lower(), True): raise httpexceptions.HTTPNotFound()
def error_extra_path(self, environ, start_response): exc = httpexceptions.HTTPNotFound( 'The trailing path %r is not allowed' % environ['PATH_INFO']) return exc.wsgi_application(environ, start_response)
def not_found(self, environ, start_response, debug_message=None): exc = httpexceptions.HTTPNotFound( 'The resource at %s could not be found' % request.construct_url(environ), comment=debug_message) return exc.wsgi_application(environ, start_response)
def check_serveable(self, config): if not config.get_user_option_as_bool('http_serve', default=True): raise httpexceptions.HTTPNotFound()
def __call__(self, environ, start_response): if environ['HTTP_HOST'] == self.domain: environ['PATH_INFO'] = self.static_path.rstrip( '/') + environ['PATH_INFO'] return self.app(environ, start_response) raise httpexceptions.HTTPNotFound()
def __call__(self, environ, start_response): """ Call interface as specified by WSGI. Wraps the environment in user friendly objects, finds the appropriate method to handle the request and calls it. """ # Setup the transaction trans = self.transaction_factory(environ) # Map url using routes path_info = trans.request.path_info map = self.mapper.match(path_info) if map == None: raise httpexceptions.HTTPNotFound("No route for " + path_info) # Save the complete mapper dict, we pop things off so they don't get passed down raw_map = dict(map) # Get the controller class controller_name = map.pop('controller', None) controller = self.controllers.get(controller_name, None) if controller_name is None: raise httpexceptions.HTTPNotFound("No controller for " + path_info) # Resolve action method on controller action = map.pop('action', 'index') method = getattr(controller, action, None) if method is None: method = getattr(controller, 'default', None) if method is None: raise httpexceptions.HTTPNotFound("No action for " + path_info) # Is the method exposed if not getattr(method, 'exposed', False): raise httpexceptions.HTTPNotFound("Action not exposed for " + path_info) # Is the method callable if not callable(method): raise httpexceptions.HTTPNotFound("Action not callable for " + path_info) # Setup routes rc = routes.request_config() rc.mapper = self.mapper rc.mapper_dict = raw_map rc.environ = environ rc.redirect = trans.response.send_redirect # Combine mapper args and query string / form args and call kwargs = trans.request.params.mixed() kwargs.update(map) body = method(trans, **kwargs) # Now figure out what we got back and try to get it to the browser in # a smart way if callable(body): # Assume the callable is another WSGI application to run return body(environ, start_response) else: start_response(trans.response.wsgi_status(), trans.response.wsgi_headeritems()) if isinstance(body, types.FileType): # Stream the file back to the browser return iterate_file(body) elif isinstance(body, (types.GeneratorType, list, tuple)): # Recursively stream the iterable return flatten(body) elif isinstance(body, basestring): # Wrap the string so it can be iterated return [body] elif body is None: # Returns an empty body return [] # Worst case scenario return [str(body)]