Changeset View
Changeset View
Standalone View
Standalone View
src/aphront/configuration/AphrontApplicationConfiguration.php
| Show First 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | public function processRequest( | ||||
| $controller_class = get_class($controller); | $controller_class = get_class($controller); | ||||
| $access_log->setData( | $access_log->setData( | ||||
| array( | array( | ||||
| 'C' => $controller_class, | 'C' => $controller_class, | ||||
| )); | )); | ||||
| $multimeter->setEventContext('web.'.$controller_class); | $multimeter->setEventContext('web.'.$controller_class); | ||||
| $request->setController($controller); | |||||
| $request->setURIMap($uri_data); | $request->setURIMap($uri_data); | ||||
| $controller->setRequest($request); | $controller->setRequest($request); | ||||
| // If execution throws an exception and then trying to render that | // If execution throws an exception and then trying to render that | ||||
| // exception throws another exception, we want to show the original | // exception throws another exception, we want to show the original | ||||
| // exception, as it is likely the root cause of the rendering exception. | // exception, as it is likely the root cause of the rendering exception. | ||||
| $original_exception = null; | $original_exception = null; | ||||
| try { | try { | ||||
| $response = $controller->willBeginExecution(); | $response = $controller->willBeginExecution(); | ||||
| ▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | public function processRequest( | ||||
| return $response; | return $response; | ||||
| } | } | ||||
| /* -( URI Routing )-------------------------------------------------------- */ | /* -( URI Routing )-------------------------------------------------------- */ | ||||
| /** | /** | ||||
| * Using builtin and application routes, build the appropriate | * Build a controller to respond to the request. | ||||
| * @{class:AphrontController} class for the request. To route a request, we | |||||
| * first test if the HTTP_HOST is configured as a valid Phabricator URI. If | |||||
| * it isn't, we do a special check to see if it's a custom domain for a blog | |||||
| * in the Phame application and if that fails we error. Otherwise, we test | |||||
| * against all application routes from installed | |||||
| * @{class:PhabricatorApplication}s. | |||||
| * | |||||
| * If we match a route, we construct the controller it points at, build it, | |||||
| * and return it. | |||||
| * | |||||
| * If we fail to match a route, but the current path is missing a trailing | |||||
| * "/", we try routing the same path with a trailing "/" and do a redirect | |||||
| * if that has a valid route. The idea is to canoncalize URIs for consistency, | |||||
| * but avoid breaking noncanonical URIs that we can easily salvage. | |||||
| * | |||||
| * NOTE: We only redirect on GET. On POST, we'd drop parameters and most | |||||
| * likely mutate the request implicitly, and a bad POST usually indicates a | |||||
| * programming error rather than a sloppy typist. | |||||
| * | |||||
| * If the failing path already has a trailing "/", or we can't route the | |||||
| * version with a "/", we call @{method:build404Controller}, which build a | |||||
| * fallback @{class:AphrontController}. | |||||
epriestley: This had been mostly reduced to lies by the introduction of Sites. | |||||
| * | * | ||||
| * @return pair<AphrontController,dict> Controller and dictionary of request | * @return pair<AphrontController,dict> Controller and dictionary of request | ||||
| * parameters. | * parameters. | ||||
| * @task routing | * @task routing | ||||
| */ | */ | ||||
| final public function buildController() { | final private function buildController() { | ||||
| $request = $this->getRequest(); | $request = $this->getRequest(); | ||||
| // If we're configured to operate in cluster mode, reject requests which | // If we're configured to operate in cluster mode, reject requests which | ||||
| // were not received on a cluster interface. | // were not received on a cluster interface. | ||||
| // | // | ||||
| // For example, a host may have an internal address like "170.0.0.1", and | // For example, a host may have an internal address like "170.0.0.1", and | ||||
| // also have a public address like "51.23.95.16". Assuming the cluster | // also have a public address like "51.23.95.16". Assuming the cluster | ||||
| // is configured on a range like "170.0.0.0/16", we want to reject the | // is configured on a range like "170.0.0.0/16", we want to reject the | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | if ($site->shouldRequireHTTPS()) { | ||||
| $https_uri->setProtocol('https'); | $https_uri->setProtocol('https'); | ||||
| // In this scenario, we'll be redirecting to HTTPS using an absolute | // In this scenario, we'll be redirecting to HTTPS using an absolute | ||||
| // URI, so we need to permit an external redirect. | // URI, so we need to permit an external redirect. | ||||
| return $this->buildRedirectController($https_uri, true); | return $this->buildRedirectController($https_uri, true); | ||||
| } | } | ||||
| } | } | ||||
| // TODO: Really, the Site should get more control here and be able to | $maps = $site->getRoutingMaps(); | ||||
| // do its own routing logic if it wants, but we don't need that for now. | $path = $request->getPath(); | ||||
| $path = $site->getPathForRouting($request); | |||||
| $result = $this->routePath($maps, $path); | |||||
| list($controller, $uri_data) = $this->buildControllerForPath($path); | if ($result) { | ||||
| if (!$controller) { | return $result; | ||||
| if (!preg_match('@/$@', $path)) { | } | ||||
| // If we failed to match anything but don't have a trailing slash, try | // If we failed to match anything but don't have a trailing slash, try | ||||
| // to add a trailing slash and issue a redirect if that resolves. | // to add a trailing slash and issue a redirect if that resolves. | ||||
| list($controller, $uri_data) = $this->buildControllerForPath($path.'/'); | |||||
| // NOTE: For POST, just 404 instead of redirecting, since the redirect | |||||
| // will be a GET without parameters. | |||||
| if ($controller && !$request->isHTTPPost()) { | // NOTE: We only do this for GET, since redirects switch to GET and drop | ||||
| // data like POST parameters. | |||||
| if (!preg_match('@/$@', $path) && $request->isHTTPGet()) { | |||||
| $result = $this->routePath($maps, $path.'/'); | |||||
| if ($result) { | |||||
| $slash_uri = $request->getRequestURI()->setPath($path.'/'); | $slash_uri = $request->getRequestURI()->setPath($path.'/'); | ||||
| $external = strlen($request->getRequestURI()->getDomain()); | $external = strlen($request->getRequestURI()->getDomain()); | ||||
| return $this->buildRedirectController($slash_uri, $external); | return $this->buildRedirectController($slash_uri, $external); | ||||
| } | } | ||||
| } | } | ||||
| return $this->build404Controller(); | |||||
| } | |||||
| return array($controller, $uri_data); | return $this->build404Controller(); | ||||
| } | } | ||||
| /** | /** | ||||
| * Map a specific path to the corresponding controller. For a description | * Map a specific path to the corresponding controller. For a description | ||||
| * of routing, see @{method:buildController}. | * of routing, see @{method:buildController}. | ||||
| * | * | ||||
| * @param list<AphrontRoutingMap> List of routing maps. | |||||
| * @param string Path to route. | |||||
| * @return pair<AphrontController,dict> Controller and dictionary of request | * @return pair<AphrontController,dict> Controller and dictionary of request | ||||
| * parameters. | * parameters. | ||||
| * @task routing | * @task routing | ||||
| */ | */ | ||||
| final public function buildControllerForPath($path) { | private function routePath(array $maps, $path) { | ||||
| $maps = array(); | foreach ($maps as $map) { | ||||
| $result = $map->routePath($path); | |||||
| $applications = PhabricatorApplication::getAllInstalledApplications(); | if ($result) { | ||||
| foreach ($applications as $application) { | return array($result->getController(), $result->getURIData()); | ||||
| $maps[] = array($application, $application->getRoutes()); | |||||
| } | |||||
| $current_application = null; | |||||
| $controller_class = null; | |||||
| foreach ($maps as $map_info) { | |||||
| list($application, $map) = $map_info; | |||||
| $mapper = new AphrontURIMapper($map); | |||||
| list($controller_class, $uri_data) = $mapper->mapPath($path); | |||||
| if ($controller_class) { | |||||
| if ($application) { | |||||
| $current_application = $application; | |||||
| } | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| if (!$controller_class) { | |||||
| return array(null, null); | |||||
| } | |||||
| $request = $this->getRequest(); | |||||
| $controller = newv($controller_class, array()); | |||||
| if ($current_application) { | |||||
| $controller->setCurrentApplication($current_application); | |||||
| } | |||||
| return array($controller, $uri_data); | |||||
| } | } | ||||
| private function buildSiteForRequest(AphrontRequest $request) { | private function buildSiteForRequest(AphrontRequest $request) { | ||||
| $sites = PhabricatorSite::getAllSites(); | $sites = PhabricatorSite::getAllSites(); | ||||
| $site = null; | $site = null; | ||||
| foreach ($sites as $candidate) { | foreach ($sites as $candidate) { | ||||
| $site = $candidate->newSiteForRequest($request); | $site = $candidate->newSiteForRequest($request); | ||||
| if ($site) { | if ($site) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (!$site) { | if (!$site) { | ||||
| $path = $request->getPath(); | $path = $request->getPath(); | ||||
| $host = $request->getHost(); | $host = $request->getHost(); | ||||
| throw new Exception( | throw new Exception( | ||||
| pht( | pht( | ||||
| 'This request asked for "%s" on host "%s", but no site is '. | 'This request asked for "%s" on host "%s", but no site is '. | ||||
| 'configured which can serve this request.', | 'configured which can serve this request.', | ||||
| $path, | $path, | ||||
| $host)); | $host)); | ||||
| } | } | ||||
| $request->setSite($site); | |||||
| return $site; | return $site; | ||||
| } | } | ||||
| } | } | ||||
This had been mostly reduced to lies by the introduction of Sites.