2011-01-16 13:51:39 -08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
/**
|
2012-08-06 12:46:51 -07:00
|
|
|
* @task routing URI Routing
|
2011-01-16 13:51:39 -08:00
|
|
|
*/
|
2015-06-15 18:02:26 +10:00
|
|
|
abstract class AphrontApplicationConfiguration extends Phobject {
|
2011-01-16 13:51:39 -08:00
|
|
|
|
|
|
|
|
private $request;
|
|
|
|
|
private $host;
|
|
|
|
|
private $path;
|
2011-02-02 13:48:52 -08:00
|
|
|
private $console;
|
2011-01-16 13:51:39 -08:00
|
|
|
|
|
|
|
|
abstract public function getApplicationName();
|
|
|
|
|
abstract public function buildRequest();
|
2011-01-29 16:16:09 -08:00
|
|
|
abstract public function build404Controller();
|
2014-08-21 21:35:29 +10:00
|
|
|
abstract public function buildRedirectController($uri, $external);
|
2011-01-16 13:51:39 -08:00
|
|
|
|
|
|
|
|
final public function setRequest(AphrontRequest $request) {
|
|
|
|
|
$this->request = $request;
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final public function getRequest() {
|
|
|
|
|
return $this->request;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-02 13:48:52 -08:00
|
|
|
final public function getConsole() {
|
|
|
|
|
return $this->console;
|
|
|
|
|
}
|
2011-02-05 12:20:18 -08:00
|
|
|
|
2011-02-05 11:45:13 -08:00
|
|
|
final public function setConsole($console) {
|
|
|
|
|
$this->console = $console;
|
2012-04-02 18:35:09 -07:00
|
|
|
return $this;
|
2011-02-05 11:45:13 -08:00
|
|
|
}
|
2011-02-02 13:48:52 -08:00
|
|
|
|
2012-08-06 12:46:51 -07:00
|
|
|
final public function setHost($host) {
|
|
|
|
|
$this->host = $host;
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final public function getHost() {
|
|
|
|
|
return $this->host;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final public function setPath($path) {
|
|
|
|
|
$this->path = $path;
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final public function getPath() {
|
|
|
|
|
return $this->path;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-10 06:49:56 +10:00
|
|
|
public function willBuildRequest() {}
|
2012-08-06 12:46:51 -07:00
|
|
|
|
|
|
|
|
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
/**
|
|
|
|
|
* @phutil-external-symbol class PhabricatorStartup
|
|
|
|
|
*/
|
|
|
|
|
public static function runHTTPRequest(AphrontHTTPSink $sink) {
|
Skeleton for "Multimeter", a performance sampling application
Summary:
Ref T6930. This application collects and displays performance samples -- roughly, things Phabricator spent some kind of resource on. It will collect samples on different types of resources and events:
- Wall time (queries, service calls, pages)
- Bytes In / Bytes Out (requests)
- Implicit requests to CSS/JS (static resources)
I've started with the simplest case (static resources), since this can be used in an immediate, straghtforward way to improve packaging (look at which individual files have the most requests recently).
There's no aggregation yet and a lot of the data isn't collected properly. Future diffs will add more dimension data (controllers, users), more event and resource types (queries, service calls, wall time), and more display options (aggregation, sorting).
Test Plan: {F389344}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T6930
Differential Revision: https://secure.phabricator.com/D12623
2015-05-01 13:19:43 -07:00
|
|
|
$multimeter = MultimeterControl::newInstance();
|
|
|
|
|
$multimeter->setEventContext('<http-init>');
|
|
|
|
|
$multimeter->setEventViewer('<none>');
|
|
|
|
|
|
Allow setup checks to perform writes
Summary:
Fixes T8198. Currently, if the `policy.locked` configuration setting includes a value which is a user PHID, we may perform a cache fill during setup as a side effect of validating it.
Right now, there is no WriteGuard active during setup, because we don't have a Request object yet so we can't actually perform CSRF validation.
Two possible approaches are:
# Prevent the write from occuring.
# Change the code to allow the write.
In the past, I think we've hit similar cases and done (1). However, IIRC those writes were sketchier, more isolated, and easy to remove (I think there was one with PKCS8 keys). This one is pretty legit and not very easy to remove without making a bit of a mess.
There's no techncial reason we can't do (2), we just have to create a no-op WriteGuard for the setup phase.
Test Plan:
- To reproduce this issue: set some value in `policy.locked` to a user PHID, then wipe out profile caches in the database, then restart the webserver.
- Reproduced the issue.
- Added the new dummy write guard, fixed a minor issue with disposal semantics (see D12841).
- Verified this fixed the issue.
- Added a `throw` to the real CSRF validator and performed a real write. Verified I got CSRF-blocked.
- Removed a CSRF token from a form and double-checked that CSRF protection still works.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T8198
Differential Revision: https://secure.phabricator.com/D12842
2015-05-14 10:39:28 -07:00
|
|
|
// Build a no-op write guard for the setup phase. We'll replace this with a
|
|
|
|
|
// real write guard later on, but we need to survive setup and build a
|
|
|
|
|
// request object first.
|
|
|
|
|
$write_guard = new AphrontWriteGuard('id');
|
|
|
|
|
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
PhabricatorEnv::initializeWebEnvironment();
|
|
|
|
|
|
Skeleton for "Multimeter", a performance sampling application
Summary:
Ref T6930. This application collects and displays performance samples -- roughly, things Phabricator spent some kind of resource on. It will collect samples on different types of resources and events:
- Wall time (queries, service calls, pages)
- Bytes In / Bytes Out (requests)
- Implicit requests to CSS/JS (static resources)
I've started with the simplest case (static resources), since this can be used in an immediate, straghtforward way to improve packaging (look at which individual files have the most requests recently).
There's no aggregation yet and a lot of the data isn't collected properly. Future diffs will add more dimension data (controllers, users), more event and resource types (queries, service calls, wall time), and more display options (aggregation, sorting).
Test Plan: {F389344}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T6930
Differential Revision: https://secure.phabricator.com/D12623
2015-05-01 13:19:43 -07:00
|
|
|
$multimeter->setSampleRate(
|
|
|
|
|
PhabricatorEnv::getEnvConfig('debug.sample-rate'));
|
|
|
|
|
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
$debug_time_limit = PhabricatorEnv::getEnvConfig('debug.time-limit');
|
|
|
|
|
if ($debug_time_limit) {
|
|
|
|
|
PhabricatorStartup::setDebugTimeLimit($debug_time_limit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is the earliest we can get away with this, we need env config first.
|
|
|
|
|
PhabricatorAccessLog::init();
|
|
|
|
|
$access_log = PhabricatorAccessLog::getLog();
|
2015-06-04 17:26:52 -07:00
|
|
|
PhabricatorStartup::setAccessLog($access_log);
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
$access_log->setData(
|
|
|
|
|
array(
|
|
|
|
|
'R' => AphrontRequest::getHTTPHeader('Referer', '-'),
|
|
|
|
|
'r' => idx($_SERVER, 'REMOTE_ADDR', '-'),
|
|
|
|
|
'M' => idx($_SERVER, 'REQUEST_METHOD', '-'),
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
DarkConsoleXHProfPluginAPI::hookProfiler();
|
|
|
|
|
DarkConsoleErrorLogPluginAPI::registerErrorHandler();
|
|
|
|
|
|
|
|
|
|
$response = PhabricatorSetupCheck::willProcessRequest();
|
|
|
|
|
if ($response) {
|
|
|
|
|
PhabricatorStartup::endOutputCapture();
|
|
|
|
|
$sink->writeResponse($response);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$host = AphrontRequest::getHTTPHeader('Host');
|
|
|
|
|
$path = $_REQUEST['__path__'];
|
|
|
|
|
|
|
|
|
|
switch ($host) {
|
|
|
|
|
default:
|
|
|
|
|
$config_key = 'aphront.default-application-configuration-class';
|
|
|
|
|
$application = PhabricatorEnv::newObjectFromConfig($config_key);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$application->setHost($host);
|
|
|
|
|
$application->setPath($path);
|
|
|
|
|
$application->willBuildRequest();
|
|
|
|
|
$request = $application->buildRequest();
|
|
|
|
|
|
Allow setup checks to perform writes
Summary:
Fixes T8198. Currently, if the `policy.locked` configuration setting includes a value which is a user PHID, we may perform a cache fill during setup as a side effect of validating it.
Right now, there is no WriteGuard active during setup, because we don't have a Request object yet so we can't actually perform CSRF validation.
Two possible approaches are:
# Prevent the write from occuring.
# Change the code to allow the write.
In the past, I think we've hit similar cases and done (1). However, IIRC those writes were sketchier, more isolated, and easy to remove (I think there was one with PKCS8 keys). This one is pretty legit and not very easy to remove without making a bit of a mess.
There's no techncial reason we can't do (2), we just have to create a no-op WriteGuard for the setup phase.
Test Plan:
- To reproduce this issue: set some value in `policy.locked` to a user PHID, then wipe out profile caches in the database, then restart the webserver.
- Reproduced the issue.
- Added the new dummy write guard, fixed a minor issue with disposal semantics (see D12841).
- Verified this fixed the issue.
- Added a `throw` to the real CSRF validator and performed a real write. Verified I got CSRF-blocked.
- Removed a CSRF token from a form and double-checked that CSRF protection still works.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T8198
Differential Revision: https://secure.phabricator.com/D12842
2015-05-14 10:39:28 -07:00
|
|
|
// Now that we have a request, convert the write guard into one which
|
|
|
|
|
// actually checks CSRF tokens.
|
|
|
|
|
$write_guard->dispose();
|
|
|
|
|
$write_guard = new AphrontWriteGuard(array($request, 'validateCSRF'));
|
|
|
|
|
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
// Build the server URI implied by the request headers. If an administrator
|
|
|
|
|
// has not configured "phabricator.base-uri" yet, we'll use this to generate
|
|
|
|
|
// links.
|
|
|
|
|
|
|
|
|
|
$request_protocol = ($request->isHTTPS() ? 'https' : 'http');
|
|
|
|
|
$request_base_uri = "{$request_protocol}://{$host}/";
|
|
|
|
|
PhabricatorEnv::setRequestBaseURI($request_base_uri);
|
|
|
|
|
|
|
|
|
|
$access_log->setData(
|
|
|
|
|
array(
|
|
|
|
|
'U' => (string)$request->getRequestURI()->getPath(),
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
$processing_exception = null;
|
|
|
|
|
try {
|
2015-05-01 13:20:30 -07:00
|
|
|
$response = $application->processRequest(
|
|
|
|
|
$request,
|
|
|
|
|
$access_log,
|
|
|
|
|
$sink,
|
|
|
|
|
$multimeter);
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
$response_code = $response->getHTTPResponseCode();
|
|
|
|
|
} catch (Exception $ex) {
|
|
|
|
|
$processing_exception = $ex;
|
|
|
|
|
$response_code = 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$write_guard->dispose();
|
|
|
|
|
|
|
|
|
|
$access_log->setData(
|
|
|
|
|
array(
|
|
|
|
|
'c' => $response_code,
|
|
|
|
|
'T' => PhabricatorStartup::getMicrosecondsSinceStart(),
|
|
|
|
|
));
|
|
|
|
|
|
2015-05-01 13:20:30 -07:00
|
|
|
$multimeter->newEvent(
|
|
|
|
|
MultimeterEvent::TYPE_REQUEST_TIME,
|
|
|
|
|
$multimeter->getEventContext(),
|
|
|
|
|
PhabricatorStartup::getMicrosecondsSinceStart());
|
|
|
|
|
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
$access_log->write();
|
|
|
|
|
|
Skeleton for "Multimeter", a performance sampling application
Summary:
Ref T6930. This application collects and displays performance samples -- roughly, things Phabricator spent some kind of resource on. It will collect samples on different types of resources and events:
- Wall time (queries, service calls, pages)
- Bytes In / Bytes Out (requests)
- Implicit requests to CSS/JS (static resources)
I've started with the simplest case (static resources), since this can be used in an immediate, straghtforward way to improve packaging (look at which individual files have the most requests recently).
There's no aggregation yet and a lot of the data isn't collected properly. Future diffs will add more dimension data (controllers, users), more event and resource types (queries, service calls, wall time), and more display options (aggregation, sorting).
Test Plan: {F389344}
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T6930
Differential Revision: https://secure.phabricator.com/D12623
2015-05-01 13:19:43 -07:00
|
|
|
$multimeter->saveEvents();
|
|
|
|
|
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
DarkConsoleXHProfPluginAPI::saveProfilerSample($access_log);
|
|
|
|
|
|
|
|
|
|
// Add points to the rate limits for this request.
|
|
|
|
|
if (isset($_SERVER['REMOTE_ADDR'])) {
|
|
|
|
|
$user_ip = $_SERVER['REMOTE_ADDR'];
|
|
|
|
|
|
|
|
|
|
// The base score for a request allows users to make 30 requests per
|
|
|
|
|
// minute.
|
|
|
|
|
$score = (1000 / 30);
|
|
|
|
|
|
|
|
|
|
// If the user was logged in, let them make more requests.
|
|
|
|
|
if ($request->getUser() && $request->getUser()->getPHID()) {
|
|
|
|
|
$score = $score / 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PhabricatorStartup::addRateLimitScore($user_ip, $score);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($processing_exception) {
|
|
|
|
|
throw $processing_exception;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function processRequest(
|
|
|
|
|
AphrontRequest $request,
|
|
|
|
|
PhutilDeferredLog $access_log,
|
2015-05-01 13:20:30 -07:00
|
|
|
AphrontHTTPSink $sink,
|
|
|
|
|
MultimeterControl $multimeter) {
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
|
|
|
|
|
$this->setRequest($request);
|
|
|
|
|
|
|
|
|
|
list($controller, $uri_data) = $this->buildController();
|
|
|
|
|
|
2015-05-01 13:20:30 -07:00
|
|
|
$controller_class = get_class($controller);
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
$access_log->setData(
|
|
|
|
|
array(
|
2015-05-01 13:20:30 -07:00
|
|
|
'C' => $controller_class,
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
));
|
2015-05-01 13:20:30 -07:00
|
|
|
$multimeter->setEventContext('web.'.$controller_class);
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
|
|
|
|
|
$request->setURIMap($uri_data);
|
|
|
|
|
$controller->setRequest($request);
|
|
|
|
|
|
|
|
|
|
// If execution throws an exception and then trying to render that
|
|
|
|
|
// exception throws another exception, we want to show the original
|
|
|
|
|
// exception, as it is likely the root cause of the rendering exception.
|
|
|
|
|
$original_exception = null;
|
|
|
|
|
try {
|
|
|
|
|
$response = $controller->willBeginExecution();
|
|
|
|
|
|
|
|
|
|
if ($request->getUser() && $request->getUser()->getPHID()) {
|
|
|
|
|
$access_log->setData(
|
|
|
|
|
array(
|
|
|
|
|
'u' => $request->getUser()->getUserName(),
|
|
|
|
|
'P' => $request->getUser()->getPHID(),
|
|
|
|
|
));
|
2015-05-01 13:20:30 -07:00
|
|
|
$multimeter->setEventViewer('user.'.$request->getUser()->getPHID());
|
Improve top-level exception handling
Summary:
Fixes T6692. Addresses two main issues:
- The write guard would sometimes not get disposed of on exception pathways, generating an unnecessary secondary error which was just a symptom of the original root error.
- This was generally confusing and reduced the quality of reports we received because users would report the symptomatic error sometimes instead of the real error.
- Instead, reflow the handling so that we always dispose of the write guard if we create one.
- If we missed the Controller-level error page generation (normally, a nice page with full CSS, etc), we'd jump straight to Startup-level error page generation (very basic plain text).
- A large class of errors occur too early or too late to be handled by Controller-level pages, but many of these errors are not fundamental, and the plain text page is excessively severe.
- Provide a mid-level simple HTML error page for errors which can't get full CSS, but also aren't so fundamental that we have no recourse but plain text.
Test Plan:
Mid-level errors now produce an intentional-looking error page:
{F259885}
Verified that setup errors still render properly.
@chad, feel free to tweak the exception page -- I just did a rough pass on it. Like the setup error stuff, it doesn't have Celerity, so we can't use `{$colors}` and no other CSS will be loaded.
Reviewers: chad, btrahan
Reviewed By: btrahan
Subscribers: epriestley, chad
Maniphest Tasks: T6692
Differential Revision: https://secure.phabricator.com/D11126
2015-01-02 10:49:27 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$response) {
|
|
|
|
|
$controller->willProcessRequest($uri_data);
|
|
|
|
|
$response = $controller->handleRequest($request);
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception $ex) {
|
|
|
|
|
$original_exception = $ex;
|
|
|
|
|
$response = $this->handleException($ex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$response = $controller->didProcessRequest($response);
|
|
|
|
|
$response = $this->willSendResponse($response, $controller);
|
|
|
|
|
$response->setRequest($request);
|
|
|
|
|
|
|
|
|
|
$unexpected_output = PhabricatorStartup::endOutputCapture();
|
|
|
|
|
if ($unexpected_output) {
|
|
|
|
|
$unexpected_output = pht(
|
|
|
|
|
"Unexpected output:\n\n%s",
|
|
|
|
|
$unexpected_output);
|
|
|
|
|
|
|
|
|
|
phlog($unexpected_output);
|
|
|
|
|
|
|
|
|
|
if ($response instanceof AphrontWebpageResponse) {
|
|
|
|
|
echo phutil_tag(
|
|
|
|
|
'div',
|
|
|
|
|
array('style' =>
|
|
|
|
|
'background: #eeddff;'.
|
|
|
|
|
'white-space: pre-wrap;'.
|
|
|
|
|
'z-index: 200000;'.
|
|
|
|
|
'position: relative;'.
|
|
|
|
|
'padding: 8px;'.
|
|
|
|
|
'font-family: monospace',
|
|
|
|
|
),
|
|
|
|
|
$unexpected_output);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$sink->writeResponse($response);
|
|
|
|
|
} catch (Exception $ex) {
|
|
|
|
|
if ($original_exception) {
|
|
|
|
|
throw $original_exception;
|
|
|
|
|
}
|
|
|
|
|
throw $ex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-06 12:46:51 -07:00
|
|
|
/* -( URI Routing )-------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Using builtin and application routes, build the appropriate
|
|
|
|
|
* @{class:AphrontController} class for the request. To route a request, we
|
2012-09-30 17:10:27 -07:00
|
|
|
* 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
|
2014-10-13 11:17:23 -07:00
|
|
|
* against all application routes from installed
|
|
|
|
|
* @{class:PhabricatorApplication}s.
|
2012-08-06 12:46:51 -07:00
|
|
|
*
|
|
|
|
|
* 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}.
|
|
|
|
|
*
|
|
|
|
|
* @return pair<AphrontController,dict> Controller and dictionary of request
|
|
|
|
|
* parameters.
|
|
|
|
|
* @task routing
|
|
|
|
|
*/
|
2011-01-16 13:51:39 -08:00
|
|
|
final public function buildController() {
|
|
|
|
|
$request = $this->getRequest();
|
2012-08-05 14:03:39 -07:00
|
|
|
|
Add `cluster.addresses` and require membership before accepting cluster authentication tokens
Summary:
Ref T2783. Ref T6706.
- Add `cluster.addresses`. This is a whitelist of CIDR blocks which define cluster hosts.
- When we recieve a request that has a cluster-based authentication token, require the cluster to be configured and require the remote address to be a cluster member before we accept it.
- This provides a general layer of security for these mechanisms.
- In particular, it means they do not work by default on unconfigured hosts.
- When cluster addresses are configured, and we receive a request //to// an address not on the list, reject it.
- This provides a general layer of security for getting the Ops side of cluster configuration correct.
- If cluster nodes have public IPs and are listening on them, we'll reject requests.
- Basically, this means that any requests which bypass the LB get rejected.
Test Plan:
- With addresses not configured, tried to make requests; rejected for using a cluster auth mechanism.
- With addresses configred wrong, tried to make requests; rejected for sending from (or to) an address outside of the cluster.
- With addresses configured correctly, made valid requests.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T6706, T2783
Differential Revision: https://secure.phabricator.com/D11159
2015-01-02 15:13:41 -08:00
|
|
|
// If we're configured to operate in cluster mode, reject requests which
|
|
|
|
|
// were not received on a cluster interface.
|
|
|
|
|
//
|
|
|
|
|
// 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
|
|
|
|
|
// is configured on a range like "170.0.0.0/16", we want to reject the
|
|
|
|
|
// requests received on the public interface.
|
|
|
|
|
//
|
|
|
|
|
// Ideally, nodes in a cluster should only be listening on internal
|
|
|
|
|
// interfaces, but they may be configured in such a way that they also
|
|
|
|
|
// listen on external interfaces, since this is easy to forget about or
|
|
|
|
|
// get wrong. As a broad security measure, reject requests received on any
|
|
|
|
|
// interfaces which aren't on the whitelist.
|
|
|
|
|
|
|
|
|
|
$cluster_addresses = PhabricatorEnv::getEnvConfig('cluster.addresses');
|
|
|
|
|
if ($cluster_addresses) {
|
|
|
|
|
$server_addr = idx($_SERVER, 'SERVER_ADDR');
|
|
|
|
|
if (!$server_addr) {
|
|
|
|
|
if (php_sapi_name() == 'cli') {
|
|
|
|
|
// This is a command line script (probably something like a unit
|
|
|
|
|
// test) so it's fine that we don't have SERVER_ADDR defined.
|
|
|
|
|
} else {
|
|
|
|
|
throw new AphrontUsageException(
|
2015-05-22 17:27:56 +10:00
|
|
|
pht('No %s', 'SERVER_ADDR'),
|
Add `cluster.addresses` and require membership before accepting cluster authentication tokens
Summary:
Ref T2783. Ref T6706.
- Add `cluster.addresses`. This is a whitelist of CIDR blocks which define cluster hosts.
- When we recieve a request that has a cluster-based authentication token, require the cluster to be configured and require the remote address to be a cluster member before we accept it.
- This provides a general layer of security for these mechanisms.
- In particular, it means they do not work by default on unconfigured hosts.
- When cluster addresses are configured, and we receive a request //to// an address not on the list, reject it.
- This provides a general layer of security for getting the Ops side of cluster configuration correct.
- If cluster nodes have public IPs and are listening on them, we'll reject requests.
- Basically, this means that any requests which bypass the LB get rejected.
Test Plan:
- With addresses not configured, tried to make requests; rejected for using a cluster auth mechanism.
- With addresses configred wrong, tried to make requests; rejected for sending from (or to) an address outside of the cluster.
- With addresses configured correctly, made valid requests.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T6706, T2783
Differential Revision: https://secure.phabricator.com/D11159
2015-01-02 15:13:41 -08:00
|
|
|
pht(
|
|
|
|
|
'Phabricator is configured to operate in cluster mode, but '.
|
2015-05-22 17:27:56 +10:00
|
|
|
'%s is not defined in the request context. Your webserver '.
|
|
|
|
|
'configuration needs to forward %s to PHP so Phabricator can '.
|
|
|
|
|
'reject requests received on external interfaces.',
|
|
|
|
|
'SERVER_ADDR',
|
|
|
|
|
'SERVER_ADDR'));
|
Add `cluster.addresses` and require membership before accepting cluster authentication tokens
Summary:
Ref T2783. Ref T6706.
- Add `cluster.addresses`. This is a whitelist of CIDR blocks which define cluster hosts.
- When we recieve a request that has a cluster-based authentication token, require the cluster to be configured and require the remote address to be a cluster member before we accept it.
- This provides a general layer of security for these mechanisms.
- In particular, it means they do not work by default on unconfigured hosts.
- When cluster addresses are configured, and we receive a request //to// an address not on the list, reject it.
- This provides a general layer of security for getting the Ops side of cluster configuration correct.
- If cluster nodes have public IPs and are listening on them, we'll reject requests.
- Basically, this means that any requests which bypass the LB get rejected.
Test Plan:
- With addresses not configured, tried to make requests; rejected for using a cluster auth mechanism.
- With addresses configred wrong, tried to make requests; rejected for sending from (or to) an address outside of the cluster.
- With addresses configured correctly, made valid requests.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T6706, T2783
Differential Revision: https://secure.phabricator.com/D11159
2015-01-02 15:13:41 -08:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!PhabricatorEnv::isClusterAddress($server_addr)) {
|
|
|
|
|
throw new AphrontUsageException(
|
|
|
|
|
pht('External Interface'),
|
|
|
|
|
pht(
|
|
|
|
|
'Phabricator is configured in cluster mode and the address '.
|
|
|
|
|
'this request was received on ("%s") is not whitelisted as '.
|
|
|
|
|
'a cluster address.',
|
|
|
|
|
$server_addr));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-04 09:56:30 -07:00
|
|
|
if (PhabricatorEnv::getEnvConfig('security.require-https')) {
|
|
|
|
|
if (!$request->isHTTPS()) {
|
2013-06-19 01:33:27 -07:00
|
|
|
$https_uri = $request->getRequestURI();
|
|
|
|
|
$https_uri->setDomain($request->getHost());
|
|
|
|
|
$https_uri->setProtocol('https');
|
2014-08-21 21:35:29 +10:00
|
|
|
|
|
|
|
|
// In this scenario, we'll be redirecting to HTTPS using an absolute
|
|
|
|
|
// URI, so we need to permit an external redirect.
|
|
|
|
|
return $this->buildRedirectController($https_uri, true);
|
2012-09-04 09:56:30 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-19 04:16:09 -07:00
|
|
|
$path = $request->getPath();
|
|
|
|
|
$host = $request->getHost();
|
|
|
|
|
$base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
|
|
|
|
|
$prod_uri = PhabricatorEnv::getEnvConfig('phabricator.production-uri');
|
|
|
|
|
$file_uri = PhabricatorEnv::getEnvConfig(
|
|
|
|
|
'security.alternate-file-domain');
|
2013-05-26 10:57:29 -07:00
|
|
|
$allowed_uris = PhabricatorEnv::getEnvConfig('phabricator.allowed-uris');
|
2013-05-19 04:16:09 -07:00
|
|
|
|
|
|
|
|
$uris = array_merge(
|
|
|
|
|
array(
|
|
|
|
|
$base_uri,
|
|
|
|
|
$prod_uri,
|
|
|
|
|
),
|
2013-05-26 10:57:29 -07:00
|
|
|
$allowed_uris);
|
2013-05-19 04:16:09 -07:00
|
|
|
|
2014-07-25 06:40:05 -07:00
|
|
|
$cdn_routes = array(
|
|
|
|
|
'/res/',
|
|
|
|
|
'/file/data/',
|
|
|
|
|
'/file/xform/',
|
|
|
|
|
'/phame/r/',
|
|
|
|
|
);
|
|
|
|
|
|
2013-05-19 04:16:09 -07:00
|
|
|
$host_match = false;
|
|
|
|
|
foreach ($uris as $uri) {
|
|
|
|
|
if ($host === id(new PhutilURI($uri))->getDomain()) {
|
|
|
|
|
$host_match = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-01-22 13:57:02 -08:00
|
|
|
|
2014-07-25 06:40:05 -07:00
|
|
|
if (!$host_match) {
|
|
|
|
|
if ($host === id(new PhutilURI($file_uri))->getDomain()) {
|
|
|
|
|
foreach ($cdn_routes as $route) {
|
|
|
|
|
if (strncmp($path, $route, strlen($route)) == 0) {
|
|
|
|
|
$host_match = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-22 13:57:02 -08:00
|
|
|
// NOTE: If the base URI isn't defined yet, don't activate alternate
|
|
|
|
|
// domains.
|
2013-05-19 04:16:09 -07:00
|
|
|
if ($base_uri && !$host_match) {
|
2012-10-15 14:49:52 -07:00
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$blog = id(new PhameBlogQuery())
|
2012-10-15 14:50:12 -07:00
|
|
|
->setViewer(new PhabricatorUser())
|
2012-10-15 14:49:52 -07:00
|
|
|
->withDomain($host)
|
|
|
|
|
->executeOne();
|
|
|
|
|
} catch (PhabricatorPolicyException $ex) {
|
|
|
|
|
throw new Exception(
|
2015-05-22 17:27:56 +10:00
|
|
|
pht(
|
|
|
|
|
'This blog is not visible to logged out users, so it can not be '.
|
|
|
|
|
'visited from a custom domain.'));
|
2012-10-15 14:49:52 -07:00
|
|
|
}
|
|
|
|
|
|
2012-09-30 17:10:27 -07:00
|
|
|
if (!$blog) {
|
2012-10-03 19:45:24 -07:00
|
|
|
if ($prod_uri && $prod_uri != $base_uri) {
|
2015-05-22 17:27:56 +10:00
|
|
|
$prod_str = pht('%s or %s', $base_uri, $prod_uri);
|
2012-09-30 17:10:27 -07:00
|
|
|
} else {
|
2015-05-22 17:27:56 +10:00
|
|
|
$prod_str = $base_uri;
|
2012-09-30 17:10:27 -07:00
|
|
|
}
|
|
|
|
|
throw new Exception(
|
2015-05-22 17:27:56 +10:00
|
|
|
pht(
|
|
|
|
|
'Specified domain %s is not configured for Phabricator '.
|
|
|
|
|
'requests. Please use %s to visit this instance.',
|
|
|
|
|
$host,
|
|
|
|
|
$prod_str));
|
2012-09-30 17:10:27 -07:00
|
|
|
}
|
|
|
|
|
|
2012-10-15 14:50:12 -07:00
|
|
|
// TODO: Make this more flexible and modular so any application can
|
|
|
|
|
// do crazy stuff here if it wants.
|
2012-09-30 17:10:27 -07:00
|
|
|
|
2012-10-15 14:51:30 -07:00
|
|
|
$path = '/phame/live/'.$blog->getID().'/'.$path;
|
2012-09-30 17:10:27 -07:00
|
|
|
}
|
|
|
|
|
|
2012-08-06 12:46:51 -07:00
|
|
|
list($controller, $uri_data) = $this->buildControllerForPath($path);
|
|
|
|
|
if (!$controller) {
|
|
|
|
|
if (!preg_match('@/$@', $path)) {
|
|
|
|
|
// 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.
|
|
|
|
|
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()) {
|
2013-06-19 01:33:27 -07:00
|
|
|
$slash_uri = $request->getRequestURI()->setPath($path.'/');
|
2014-08-21 21:35:29 +10:00
|
|
|
|
|
|
|
|
$external = strlen($request->getRequestURI()->getDomain());
|
|
|
|
|
return $this->buildRedirectController($slash_uri, $external);
|
2012-08-06 12:46:51 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $this->build404Controller();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return array($controller, $uri_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Map a specific path to the corresponding controller. For a description
|
|
|
|
|
* of routing, see @{method:buildController}.
|
|
|
|
|
*
|
|
|
|
|
* @return pair<AphrontController,dict> Controller and dictionary of request
|
|
|
|
|
* parameters.
|
|
|
|
|
* @task routing
|
|
|
|
|
*/
|
2012-08-09 22:11:50 -07:00
|
|
|
final public function buildControllerForPath($path) {
|
2012-08-05 14:03:39 -07:00
|
|
|
$maps = array();
|
|
|
|
|
|
|
|
|
|
$applications = PhabricatorApplication::getAllInstalledApplications();
|
|
|
|
|
foreach ($applications as $application) {
|
|
|
|
|
$maps[] = array($application, $application->getRoutes());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$current_application = null;
|
2012-08-06 12:46:51 -07:00
|
|
|
$controller_class = null;
|
2012-08-05 14:03:39 -07:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-01-16 13:51:39 -08:00
|
|
|
|
2011-01-29 16:16:09 -08:00
|
|
|
if (!$controller_class) {
|
2012-08-06 12:46:51 -07:00
|
|
|
return array(null, null);
|
2011-01-29 16:16:09 -08:00
|
|
|
}
|
|
|
|
|
|
2012-08-06 12:46:51 -07:00
|
|
|
$request = $this->getRequest();
|
|
|
|
|
|
Decouple some aspects of request routing and construction
Summary:
Ref T5702. This is a forward-looking change which provides some very broad API improvements but does not implement them. In particular:
- Controllers no longer require `$request` to construct. This is mostly for T5702, directly, but simplifies things in general. Instead, we call `setRequest()` before using a controller. Only a small number of sites activate controllers, so this is less code overall, and more consistent with most constructors not having any parameters or effects.
- `$request` now offers `getURIData($key, ...)`. This is an alternate way of accessing `$data` which is currently only available on `willProcessRequest(array $data)`. Almost all controllers which implement this method do so in order to read one or two things out of the URI data. Instead, let them just read this data directly when processing the request.
- Introduce `handleRequest(AphrontRequest $request)` and deprecate (very softly) `processRequest()`. The majority of `processRequest()` calls begin `$request = $this->getRequest()`, which is avoided with the more practical signature.
- Provide `getViewer()` on `$request`, and a convenience `getViewer()` on `$controller`. This fixes `$viewer = $request->getUser();` into `$viewer = $request->getViewer();`, and converts the `$request + $viewer` two-liner into a single `$this->getViewer()`.
Test Plan:
- Browsed around in general.
- Hit special controllers (redirect, 404).
- Hit AuditList controller (uses new style).
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T5702
Differential Revision: https://secure.phabricator.com/D10698
2014-10-17 05:01:40 -07:00
|
|
|
$controller = newv($controller_class, array());
|
2012-08-05 14:03:39 -07:00
|
|
|
if ($current_application) {
|
|
|
|
|
$controller->setCurrentApplication($current_application);
|
|
|
|
|
}
|
2011-01-16 13:51:39 -08:00
|
|
|
|
|
|
|
|
return array($controller, $uri_data);
|
|
|
|
|
}
|
2014-07-10 08:12:48 +10:00
|
|
|
|
2011-01-16 13:51:39 -08:00
|
|
|
}
|