1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +01:00

Allow custom Sites to have custom 404 controllers

Summary:
Currently, custom Sites must match `.*` or similar to handle 404's, since the fallback is always generic.

This locks them out of the "redirect to canonicalize to `path/` code", so they currently have a choice between a custom 404 page or automatic correction of `/`.

Instead, allow the 404 controller to be constructed explicitly. Sites can now customize 404 by implementing this method and not matching everything.

(Sites can still match everything with a catchall rule if they don't want this behavior for some reason, so this should be strictly more powerful than the old behavior.)

See next diff for CORGI.

Test Plan:
  - Visited real 404 (like "/asdfafewfq"), missing-slash-404 (like "/maniphest") and real page (like "/maniphest/") URIs on blog, main, and CORGI sites.
  - Got 404 behavior, redirects, and real pages, respectively.

Reviewers: chad

Reviewed By: chad

Differential Revision: https://secure.phabricator.com/D16966
This commit is contained in:
epriestley 2016-11-30 15:05:40 -08:00
parent 29a3cd5121
commit 9730f5a34f
5 changed files with 25 additions and 5 deletions

View file

@ -545,6 +545,13 @@ final class AphrontRequest extends Phobject {
return id(new PhutilURI($path))->setQueryParams($get);
}
public function getAbsoluteRequestURI() {
$uri = $this->getRequestURI();
$uri->setDomain($this->getHost());
$uri->setProtocol($this->isHTTPS() ? 'https' : 'http');
return $uri;
}
public function isDialogFormPost() {
return $this->isFormPost() && $this->getStr('__dialog__');
}

View file

@ -409,19 +409,25 @@ abstract class AphrontApplicationConfiguration extends Phobject {
if (!preg_match('@/$@', $path) && $request->isHTTPGet()) {
$result = $this->routePath($maps, $path.'/');
if ($result) {
$slash_uri = $request->getRequestURI()->setPath($path.'/');
$target_uri = $request->getAbsoluteRequestURI();
// We need to restore URI encoding because the webserver has
// interpreted it. For example, this allows us to redirect a path
// like `/tag/aa%20bb` to `/tag/aa%20bb/`, which may eventually be
// resolved meaningfully by an application.
$slash_uri = phutil_escape_uri($slash_uri);
$target_path = phutil_escape_uri($path.'/');
$target_uri->setPath($target_path);
$target_uri = (string)$target_uri;
$external = strlen($request->getRequestURI()->getDomain());
return $this->buildRedirectController($slash_uri, $external);
return $this->buildRedirectController($target_uri, true);
}
}
$result = $site->new404Controller($request);
if ($result) {
return array($result, array());
}
return $this->build404Controller();
}

View file

@ -9,6 +9,10 @@ abstract class AphrontSite extends Phobject {
abstract public function newSiteForRequest(AphrontRequest $request);
abstract public function getRoutingMaps();
public function new404Controller(AphrontRequest $request) {
return null;
}
protected function isHostMatch($host, array $uris) {
foreach ($uris as $uri) {
if (!strlen($uri)) {

View file

@ -92,7 +92,6 @@ final class PhabricatorPhameApplication extends PhabricatorApplication {
'/' => array(
'' => 'PhameBlogViewController',
'post/(?P<id>\d+)/(?:(?P<slug>[^/]+)/)?' => 'PhamePostViewController',
'.*' => 'PhameBlog404Controller',
),
);

View file

@ -60,6 +60,10 @@ final class PhameBlogSite extends PhameSite {
return id(new PhameBlogSite())->setBlog($blog);
}
public function new404Controller(AphrontRequest $request) {
return new PhameBlog404Controller();
}
public function getRoutingMaps() {
$app = PhabricatorApplication::getByClass('PhabricatorPhameApplication');