Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

Commit

Permalink
Initial commit: verbatim import from hack docs site
Browse files Browse the repository at this point in the history
License headers added.
  • Loading branch information
fredemmott committed Feb 9, 2017
1 parent 04b393d commit b7b33c8
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 0 deletions.
106 changes: 106 additions & 0 deletions src/BaseRouter.php
@@ -0,0 +1,106 @@
<?hh // strict
/*
* Copyright (c) 2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/


use HHVM\UserDocumentation\ArgAssert;
use HHVM\UserDocumentation\BuildPaths;
use HHVM\UserDocumentation\LocalConfig;

class Router {
private function getReadOnlyRoutes(
): KeyedIterable<string, classname<WebController>> {
return ImmMap {
'/' => HomePageController::class,
'/search' => SearchController::class,
'/{product:(?:hack|hhvm)}/'
=> GuidesListController::class,
'/{product:(?:hack)}/reference/'
=> APIListController::class,
'/{product:(?:hack)}/reference/{type:(?:class|function|interface|trait)}/'
=> APIListController::class,
'/{product:(?:hack)}/reference/{type:(?:class|function|interface|trait)}/{name}/'
=> APIGenericPageController::class,
'/{product:(?:hack)}/reference/{type:(?:class|interface|trait)}/{class}/{method}/'
=> APIMethodPageController::class,
'/{product:(?:hack|hhvm)}/{guide}/'
=> RedirectToGuideFirstPageController::class,
'/{product:(?:hack|hhvm)}/{guide}/{page}'
=> GuidePageController::class,
'/manual/en/{legacy_id}.php'
=> LegacyRedirectController::class,
'/robots.txt'
=> RobotsTxtController::class,
'/__content'
=> WebPageContentController::class,
'/s/{checksum}{file:/.+}'
=> StaticResourcesController::class,
'/j/{keyword}'
=> JumpController::class,
};
}

private function getWriteRoutes(
): KeyedIterable<string, classname<WebController>> {
return ImmMap {
'/__survey/go'
=> SurveyRedirectController::class,
'/__survey/nothanks'
=> SurveyNoThanksController::class,
};
}

private function getDispatcher(): \FastRoute\Dispatcher {
return \FastRoute\cachedDispatcher(
function(\FastRoute\RouteCollector $r): void {
foreach ($this->getReadOnlyRoutes() as $route => $classname) {
$r->addRoute('GET', $route, $classname);
}

foreach ($this->getWriteRoutes() as $route => $classname) {
$r->addRoute('POST', $route, $classname);
}
},
/* HH_FIXME[4110] nikic/fastroute#83*/
shape(
'cacheFile' => BuildPaths::FASTROUTE_CACHE,
'cacheDisabled' => !LocalConfig::CACHE_ROUTES,
),
);
}

public function routeRequest(
\Psr\Http\Message\ServerRequestInterface $request
): (classname<WebController>, ImmMap<string, string>) {
$path = $request->getUri()->getPath();
$route = $this->getDispatcher()->dispatch(
$request->getMethod(),
$path,
);
switch ($route[0]) {
case \FastRoute\Dispatcher::NOT_FOUND:
throw new HTTPNotFoundException($path);
case \FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
throw new HTTPMethodNotAllowedException($path);
case \FastRoute\Dispatcher::FOUND:
return tuple(
ArgAssert::isClassname($route[1], WebController::class),
(new Map($route[2]))
->map($encoded ==> urldecode($encoded))
->toImmMap(),
);
}

invariant_violation(
"Unknown fastroute result: %s",
var_export($route[0], true),
);
}
}
52 changes: 52 additions & 0 deletions src/http_exceptions.php
@@ -0,0 +1,52 @@
<?hh // strict
/*
* Copyright (c) 2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

abstract class HTTPException extends \Exception {
abstract public function getResponse(
ServerRequestInterface $request,
): Awaitable<ResponseInterface>;
}
abstract class RoutingException extends HTTPException {}

final class HTTPNotFoundException extends RoutingException {
public async function getResponse(
ServerRequestInterface $request,
): Awaitable<ResponseInterface> {
return await (new HTTP404Controller(ImmMap { }, $request))->getResponse();
}
}

final class HTTPMethodNotAllowedException extends RoutingException {
public async function getResponse(
ServerRequestInterface $_,
): Awaitable<ResponseInterface> {
return Response::newEmpty()->withStatus(405);
}
}

final class RedirectException extends HTTPException {
public function __construct(
private string $destination,
) {
parent::__construct();
}

public async function getResponse(
ServerRequestInterface $_,
): Awaitable<ResponseInterface> {
return Response::newEmpty()
->withStatus(301)
->withAddedHeader('Location', $this->destination);
}
}

0 comments on commit b7b33c8

Please sign in to comment.