def test_bugs_host_has_api(self): # Requests to /api on the bugs domain are treated as web service # requests. request, publication = get_request_and_publication( host=config.vhost.bugs.hostname, extra_environment={'PATH_INFO': '/api/1.0'}) # XXX MichaelHudson, 2010-07-20, bug=607664: WebServiceLayer only # actually provides WebServiceLayer in the sense of verifyObject after # traversal has started. self.assertTrue(WebServiceLayer.providedBy(request))
def test_blueprints_host_has_api(self): # Requests to /api on the blueprints domain are treated as web service # requests. request, publication = get_request_and_publication( host=config.vhost.blueprints.hostname, extra_environment={'PATH_INFO': '/api/1.0'}) # XXX MichaelHudson, 2010-07-20, bug=607664: WebServiceLayer only # actually provides WebServiceLayer in the sense of verifyObject after # traversal has started. self.assertTrue(WebServiceLayer.providedBy(request))
def http_url(self): """Return the webapp URL for the context `LibraryFileAlias`. Preserve the `LibraryFileAlias.http_url` behavior for deleted files, returning None. Mask webservice requests if it's the case, so the returned URL will be always relative to the parent webapp URL. """ if self.context.deleted: return None request = get_current_browser_request() if WebServiceLayer.providedBy(request): request = IWebBrowserOriginatingRequest(request) parent_url = canonical_url(self.parent, request=request) traversal_url = urlappend(parent_url, '+files') url = urlappend( traversal_url, url_path_quote(self.context.filename.encode('utf-8'))) return url
def _getBetaRedirectionView(self): # If the inhibit_beta_redirect cookie is set, don't redirect. if self.request.cookies.get('inhibit_beta_redirect', '0') == '1': return None # If we are looking at the front page, don't redirect. if self.request['PATH_INFO'] == '/': return None # If this is a HTTP POST, we don't want to issue a redirect. # Doing so would go against the HTTP standard. if self.request.method == 'POST': return None # If this is a web service request, don't redirect. if WebServiceLayer.providedBy(self.request): return None # If the request is for a bug then redirect straight to that bug. bug_match = re.match("/bugs/(\d+)$", self.request['PATH_INFO']) if bug_match: bug_number = bug_match.group(1) bug_set = getUtility(IBugSet) try: bug = bug_set.get(bug_number) except NotFoundError: raise NotFound(self.context, bug_number) if not check_permission("launchpad.View", bug): return None # Empty the traversal stack, since we're redirecting. self.request.setTraversalStack([]) # And perform a temporary redirect. return RedirectionView(canonical_url(bug.default_bugtask), self.request, status=303) # Explicit catchall - do not redirect. return None
def _getBetaRedirectionView(self): # If the inhibit_beta_redirect cookie is set, don't redirect. if self.request.cookies.get('inhibit_beta_redirect', '0') == '1': return None # If we are looking at the front page, don't redirect. if self.request['PATH_INFO'] == '/': return None # If this is a HTTP POST, we don't want to issue a redirect. # Doing so would go against the HTTP standard. if self.request.method == 'POST': return None # If this is a web service request, don't redirect. if WebServiceLayer.providedBy(self.request): return None # If the request is for a bug then redirect straight to that bug. bug_match = re.match("/bugs/(\d+)$", self.request['PATH_INFO']) if bug_match: bug_number = bug_match.group(1) bug_set = getUtility(IBugSet) try: bug = bug_set.get(bug_number) except NotFoundError: raise NotFound(self.context, bug_number) if not check_permission("launchpad.View", bug): return None # Empty the traversal stack, since we're redirecting. self.request.setTraversalStack([]) # And perform a temporary redirect. return RedirectionView(canonical_url(bug.default_bugtask), self.request, status=303) # Explicit catchall - do not redirect. return None
def attach_http_request(report, context): """Add request metadata into the error report. This reads the exc_info and http_request keys from the context and will write to: * url * ignore * username * topic * req_vars """ info = context.get('exc_info') request = context.get('http_request') if request is None: return # XXX jamesh 2005-11-22: Temporary fix, which Steve should # undo. URL is just too HTTPRequest-specific. if safe_hasattr(request, 'URL'): # URL's are byte strings, but possibly str() will fail - safe_unicode # handles all those cases, and then we can safely encode it to utf8. # This is strictly double handling as a URL should never have unicode # characters in it anyway (though it may have them % encoded, which is # fine). Better safe than sorry, and the safe_unicode handling won't # cause double-encoding, so it is safe. url = oops.createhooks.safe_unicode(request.URL).encode('utf8') report['url'] = url if WebServiceLayer.providedBy(request) and info is not None: webservice_error = getattr( info[1], '__lazr_webservice_error__', 500) if webservice_error / 100 != 5: request.oopsid = None # Tell the oops machinery to ignore this error report['ignore'] = True missing = object() principal = getattr(request, 'principal', missing) if safe_hasattr(principal, 'getLogin'): login = principal.getLogin() elif principal is missing or principal is None: # Request has no principal (e.g. scriptrequest) login = None else: # Request has an UnauthenticatedPrincipal. login = '******' if _get_type(report) in ( _ignored_exceptions_for_unauthenticated_users): report['ignore'] = True if principal is not None and principal is not missing: username = '******'.join([ unicode(login), unicode(request.principal.id), unicode(request.principal.title), unicode(request.principal.description)]) report['username'] = username if getattr(request, '_orig_env', None): report['topic'] = request._orig_env.get('launchpad.pageid', '') for key, value in request.items(): if _is_sensitive(request, key): value = '<hidden>' if not isinstance(value, basestring): value = oops.createhooks.safe_unicode(value) # keys need to be unicode objects. The form items (a subset of # request.items) are generally just the url query_string url decoded, # which means the keys may be invalid in bson docs (bson requires that # they be unicode). key = oops.createhooks.safe_unicode(key) report['req_vars'][key] = value if IXMLRPCRequest.providedBy(request): args = request.getPositionalArguments() # Request variables are strings: this could move to its own key and be # raw. report['req_vars']['xmlrpc args'] = unicode(args)
def canonical_url( obj, request=None, rootsite=None, path_only_if_possible=False, view_name=None, force_local_path=False): """Return the canonical URL string for the object. If the canonical url configuration for the given object binds it to a particular root site, then we use that root URL. (There is an assumption here that traversal works the same way on different sites. When that isn't so, we need to specify the url in full in the canonical url configuration. We may want to register canonical url configuration *for* particular sites in the future, to allow more flexibility for traversal. I foresee a refactoring where we'll combine the concepts of sites, layers, URLs and so on.) Otherwise, we attempt to take the protocol, host and port from the request. If a request is not provided, but a web-request is in progress, the protocol, host and port are taken from the current request. :param request: The web request; if not provided, canonical_url attempts to guess at the current request, using the protocol, host, and port taken from the root_url given in launchpad.conf. :param path_only_if_possible: If the protocol and hostname can be omitted for the current request, return a url containing only the path. :param view_name: Provide the canonical url for the specified view, rather than the default view. :param force_local_path: Strip off the site no matter what. :raises: NoCanonicalUrl if a canonical url is not available. """ urlparts = [urldata.path for urldata in canonical_urldata_iterator(obj) if urldata.path] if rootsite is None: obj_urldata = ICanonicalUrlData(obj, None) if obj_urldata is None: raise NoCanonicalUrl(obj, obj) rootsite = obj_urldata.rootsite # The request is needed when there's no rootsite specified. if request is None: # Look for a request from the interaction. current_request = get_current_browser_request() if current_request is not None: if WebServiceLayer.providedBy(current_request): from lp.services.webapp.publication import ( LaunchpadBrowserPublication) from lp.services.webapp.servers import ( LaunchpadBrowserRequest) current_request = LaunchpadBrowserRequest( current_request.bodyStream.getCacheStream(), dict(current_request.environment)) current_request.setPublication( LaunchpadBrowserPublication(None)) current_request.setVirtualHostRoot(names=[]) main_root_url = current_request.getRootURL( 'mainsite') current_request._app_server = main_root_url.rstrip('/') request = current_request if view_name is not None: # Make sure that the view is registered for the site requested. fake_request = FakeRequest() directlyProvides(fake_request, layer_for_rootsite(rootsite)) # Look first for a view. if queryMultiAdapter((obj, fake_request), name=view_name) is None: # Look if this is a special name defined by Navigation. navigation = queryMultiAdapter( (obj, fake_request), IBrowserPublisher) if isinstance(navigation, Navigation): all_names = navigation.all_traversal_and_redirection_names else: all_names = [] if view_name not in all_names: raise AssertionError( 'Name "%s" is not registered as a view or navigation ' 'step for "%s" on "%s".' % ( view_name, obj.__class__.__name__, rootsite)) urlparts.insert(0, view_name) if request is None: # Yes this really does need to be here, as rootsite can be None, and # we don't want to make the getRootURL from the request break. if rootsite is None: rootsite = 'mainsite' root_url = allvhosts.configs[rootsite].rooturl else: root_url = request.getRootURL(rootsite) path = u'/'.join(reversed(urlparts)) if ((path_only_if_possible and request is not None and root_url.startswith(request.getApplicationURL())) or force_local_path): return unicode('/' + path) return unicode(root_url + path)
def attach_http_request(report, context): """Add request metadata into the error report. This reads the exc_info and http_request keys from the context and will write to: * url * ignore * username * topic * req_vars """ info = context.get('exc_info') request = context.get('http_request') if request is None: return # XXX jamesh 2005-11-22: Temporary fix, which Steve should # undo. URL is just too HTTPRequest-specific. if safe_hasattr(request, 'URL'): # URL's are byte strings, but possibly str() will fail - safe_unicode # handles all those cases, and then we can safely encode it to utf8. # This is strictly double handling as a URL should never have unicode # characters in it anyway (though it may have them % encoded, which is # fine). Better safe than sorry, and the safe_unicode handling won't # cause double-encoding, so it is safe. url = oops.createhooks.safe_unicode(request.URL).encode('utf8') report['url'] = url if WebServiceLayer.providedBy(request) and info is not None: webservice_error = getattr( info[1], '__lazr_webservice_error__', 500) if webservice_error / 100 != 5: request.oopsid = None # Tell the oops machinery to ignore this error report['ignore'] = True missing = object() principal = getattr(request, 'principal', missing) if safe_hasattr(principal, 'getLogin'): login = principal.getLogin() elif principal is missing or principal is None: # Request has no principal (e.g. scriptrequest) login = None else: # Request has an UnauthenticatedPrincipal. login = '******' if _get_type(report) in ( _ignored_exceptions_for_unauthenticated_users): report['ignore'] = True if principal is not None and principal is not missing: username = '******'.join([ unicode(login), unicode(request.principal.id), unicode(request.principal.title), unicode(request.principal.description)]) report['username'] = username if getattr(request, '_orig_env', None): report['topic'] = request._orig_env.get('launchpad.pageid', '') for key, value in request.items(): if _is_sensitive(request, key): value = '<hidden>' if not isinstance(value, basestring): value = oops.createhooks.safe_unicode(value) # keys need to be unicode objects. The form items (a subset of # request.items) are generally just the url query_string url decoded, # which means the keys may be invalid in bson docs (bson requires that # they be unicode). key = oops.createhooks.safe_unicode(key) report['req_vars'][key] = value if IXMLRPCRequest.providedBy(request): args = request.getPositionalArguments() # Request variables are strings: this could move to its own key and be # raw. report['req_vars']['xmlrpc args'] = unicode(args)
def request(self): request = get_current_browser_request() if WebServiceLayer.providedBy(request): request = IWebBrowserOriginatingRequest(request) return request