@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Replace AphrontUsageException with AphrontMalformedRequestException

Summary:
Ref T1806. Ref T7173. Context here is that I want to fix "you can not log in to this instance" being a confusing mess with an opaque error. To do this without hacks, I want to:

- clean up some exception handling behavior (this diff);
- modularize exception handling (next diff);
- replace confusing, over-general exceptions with tailored ones in the Phacility cluster, using the new modular stuff.

This cleans up an awkward "AphrontUsageException" which does some weird stuff right now. In particular, it is extensible and extended in one place in Diffusion, but that extension is meaningless.

Realign this as "AphrontMalformedRequestException", which is a better description of what it is and does: raises errors before we can get as far as normal routing and site handling.

Test Plan: Hit some of these exceptions, saw the expected "abandon all hope" error page.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T1806, T7173

Differential Revision: https://secure.phabricator.com/D14047

+60 -53
+3 -3
src/__phutil_library_map__.php
··· 143 143 'AphrontJavelinView' => 'view/AphrontJavelinView.php', 144 144 'AphrontKeyboardShortcutsAvailableView' => 'view/widget/AphrontKeyboardShortcutsAvailableView.php', 145 145 'AphrontListFilterView' => 'view/layout/AphrontListFilterView.php', 146 + 'AphrontMalformedRequestException' => 'aphront/exception/AphrontMalformedRequestException.php', 146 147 'AphrontMoreView' => 'view/layout/AphrontMoreView.php', 147 148 'AphrontMultiColumnView' => 'view/layout/AphrontMultiColumnView.php', 148 149 'AphrontMySQLDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontMySQLDatabaseConnectionTestCase.php', ··· 170 171 'AphrontTokenizerTemplateView' => 'view/control/AphrontTokenizerTemplateView.php', 171 172 'AphrontTypeaheadTemplateView' => 'view/control/AphrontTypeaheadTemplateView.php', 172 173 'AphrontUnhandledExceptionResponse' => 'aphront/response/AphrontUnhandledExceptionResponse.php', 173 - 'AphrontUsageException' => 'aphront/exception/AphrontUsageException.php', 174 174 'AphrontView' => 'view/AphrontView.php', 175 175 'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php', 176 176 'ArcanistConduitAPIMethod' => 'applications/arcanist/conduit/ArcanistConduitAPIMethod.php', ··· 3771 3771 'AphrontJavelinView' => 'AphrontView', 3772 3772 'AphrontKeyboardShortcutsAvailableView' => 'AphrontView', 3773 3773 'AphrontListFilterView' => 'AphrontView', 3774 + 'AphrontMalformedRequestException' => 'AphrontException', 3774 3775 'AphrontMoreView' => 'AphrontView', 3775 3776 'AphrontMultiColumnView' => 'AphrontView', 3776 3777 'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase', ··· 3800 3801 'AphrontTokenizerTemplateView' => 'AphrontView', 3801 3802 'AphrontTypeaheadTemplateView' => 'AphrontView', 3802 3803 'AphrontUnhandledExceptionResponse' => 'AphrontStandaloneHTMLResponse', 3803 - 'AphrontUsageException' => 'AphrontException', 3804 3804 'AphrontView' => array( 3805 3805 'Phobject', 3806 3806 'PhutilSafeHTMLProducerInterface', ··· 4383 4383 'DiffusionSearchQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 4384 4384 'DiffusionServeController' => 'DiffusionController', 4385 4385 'DiffusionSetPasswordSettingsPanel' => 'PhabricatorSettingsPanel', 4386 - 'DiffusionSetupException' => 'AphrontUsageException', 4386 + 'DiffusionSetupException' => 'Exception', 4387 4387 'DiffusionSubversionSSHWorkflow' => 'DiffusionSSHWorkflow', 4388 4388 'DiffusionSubversionServeSSHWorkflow' => 'DiffusionSubversionSSHWorkflow', 4389 4389 'DiffusionSubversionWireProtocol' => 'Phobject',
+6 -4
src/aphront/configuration/AphrontApplicationConfiguration.php
··· 318 318 // This is a command line script (probably something like a unit 319 319 // test) so it's fine that we don't have SERVER_ADDR defined. 320 320 } else { 321 - throw new AphrontUsageException( 321 + throw new AphrontMalformedRequestException( 322 322 pht('No %s', 'SERVER_ADDR'), 323 323 pht( 324 324 'Phabricator is configured to operate in cluster mode, but '. ··· 330 330 } 331 331 } else { 332 332 if (!PhabricatorEnv::isClusterAddress($server_addr)) { 333 - throw new AphrontUsageException( 333 + throw new AphrontMalformedRequestException( 334 334 pht('External Interface'), 335 335 pht( 336 336 'Phabricator is configured in cluster mode and the address '. ··· 413 413 if (!$site) { 414 414 $path = $request->getPath(); 415 415 $host = $request->getHost(); 416 - throw new Exception( 416 + throw new AphrontMalformedRequestException( 417 + pht('Site Not Found'), 417 418 pht( 418 419 'This request asked for "%s" on host "%s", but no site is '. 419 420 'configured which can serve this request.', 420 421 $path, 421 - $host)); 422 + $host), 423 + true); 422 424 } 423 425 424 426 $request->setSite($site);
-16
src/aphront/configuration/AphrontDefaultApplicationConfiguration.php
··· 210 210 return $response; 211 211 } 212 212 213 - if ($ex instanceof AphrontUsageException) { 214 - $error = new PHUIInfoView(); 215 - $error->setTitle($ex->getTitle()); 216 - $error->appendChild($ex->getMessage()); 217 - 218 - $view = new PhabricatorStandardPageView(); 219 - $view->setRequest($this->getRequest()); 220 - $view->appendChild($error); 221 - 222 - $response = new AphrontWebpageResponse(); 223 - $response->setContent($view->render()); 224 - $response->setHTTPResponseCode(500); 225 - 226 - return $response; 227 - } 228 - 229 213 // Always log the unhandled exception. 230 214 phlog($ex); 231 215
+34
src/aphront/exception/AphrontMalformedRequestException.php
··· 1 + <?php 2 + 3 + /** 4 + * These exceptions are raised when a client submits a malformed request. 5 + * 6 + * These errors are caught by Aphront itself and occur too early or too 7 + * fundamentally in request handling to allow the request to route to a 8 + * controller or survive to normal processing. 9 + * 10 + * These exceptions can be made "unlogged", which will prevent them from being 11 + * logged. The intent is that errors which are purely the result of client 12 + * failure and of no interest to the server can be raised silently to avoid 13 + * cluttering the logs with client errors that are not actionable. 14 + */ 15 + final class AphrontMalformedRequestException extends AphrontException { 16 + 17 + private $title; 18 + private $isUnlogged; 19 + 20 + public function __construct($title, $message, $unlogged = false) { 21 + $this->title = $title; 22 + $this->isUnlogged = $unlogged; 23 + parent::__construct($message); 24 + } 25 + 26 + public function getTitle() { 27 + return $this->title; 28 + } 29 + 30 + public function getIsUnlogged() { 31 + return $this->isUnlogged; 32 + } 33 + 34 + }
-21
src/aphront/exception/AphrontUsageException.php
··· 1 - <?php 2 - 3 - /** 4 - * These exceptions represent user error, and are not logged. 5 - * 6 - * @concrete-extensible 7 - */ 8 - class AphrontUsageException extends AphrontException { 9 - 10 - private $title; 11 - 12 - public function __construct($title, $message) { 13 - $this->title = $title; 14 - parent::__construct($message); 15 - } 16 - 17 - public function getTitle() { 18 - return $this->title; 19 - } 20 - 21 - }
+16 -2
src/aphront/response/AphrontUnhandledExceptionResponse.php
··· 6 6 private $exception; 7 7 8 8 public function setException(Exception $exception) { 9 + // Log the exception unless it's specifically a silent malformed request 10 + // exception. 11 + 12 + $should_log = true; 13 + if ($exception instanceof AphrontMalformedRequestException) { 14 + if ($exception->getIsUnlogged()) { 15 + $should_log = false; 16 + } 17 + } 18 + 19 + if ($should_log) { 20 + phlog($exception); 21 + } 22 + 9 23 $this->exception = $exception; 10 24 return $this; 11 25 } ··· 24 38 protected function getResponseTitle() { 25 39 $ex = $this->exception; 26 40 27 - if ($ex instanceof AphrontUsageException) { 41 + if ($ex instanceof AphrontMalformedRequestException) { 28 42 return $ex->getTitle(); 29 43 } else { 30 44 return pht('Unhandled Exception'); ··· 38 52 protected function getResponseBody() { 39 53 $ex = $this->exception; 40 54 41 - if ($ex instanceof AphrontUsageException) { 55 + if ($ex instanceof AphrontMalformedRequestException) { 42 56 $title = $ex->getTitle(); 43 57 } else { 44 58 $title = get_class($ex);
+1 -7
src/applications/diffusion/exception/DiffusionSetupException.php
··· 1 1 <?php 2 2 3 - final class DiffusionSetupException extends AphrontUsageException { 4 - 5 - public function __construct($message) { 6 - parent::__construct(pht('Diffusion Setup Exception'), $message); 7 - } 8 - 9 - } 3 + final class DiffusionSetupException extends Exception {}