簡體   English   中英

PHP Fastroute - 處理 404s

[英]PHP Fastroute - Handle 404s

在我的應用程序中,我使用的是FastRoute ,我希望有不同類型的 404 響應:

  • 當調用以/api開頭的不存在的端點時,應用程序應返回JSON 404 響應。
  • 當調用一個不存在的端點時,應用程序應該返回一個通用的 404。

為了獲得通用的 404 響應,我按照文檔做了:

$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
switch ($routeInfo[0]) {
    case FastRoute\Dispatcher::NOT_FOUND:
        // ... 404 Not Found
        break;

但是在不存在/api端點的情況下,我無法找到獲得 404 JSON 響應的方法。
我取得的成就是這樣的:

$router->addGroup('/api', function (RouteCollector $r) {
    $r->post('/login', 'ApiController@login');
    $r->addRoute('*', '[/{str}]', 'ApiController@notFound');
});

例如:

  • 調用/api/not-existing-endpoint時,它返回 JSON 404 響應(所以沒關系)。
  • 當調用/api/not-existing-endpoint/aaa/bbb/ccc時,它沒有捕獲到它並返回一個通用的 404。

如何修復路由的模式$r->addRoute('*', '[/{str}]', 'ApiController@notFound'); 為了也捕捉像/api/aaa/bbb/ccc/ddd這樣的嵌套 URI?

使用帶有正則表達式的路由路徑。

$r->addRoute('*', '[/{any:.*}]', 'ApiController@notFound');
我的完整代碼。
require 'vendor/autoload.php';


$dispatcher = \FastRoute\simpleDispatcher(function(\FastRoute\RouteCollector $r) {
    $r->addRoute('GET', '/hello[/]', function() {
        echo 'hello';
    });
    $r->addRoute('GET', '/hello/{name}', function($attribute) {
        echo 'hello ' . $attribute['name'];
    });
    $r->addGroup('/api', function (\FastRoute\RouteCollector $r) {
        $r->addRoute('GET', '/hello[/]', function() {
            header('Content-type: application/json');
            echo json_encode(['msg' => 'hello API']);
        });
        $r->addRoute('*', '[/{any:.*}]', function() {
            header('Content-type: application/json');
            echo json_encode(['msg' => 'not found']);
        });
    });
});

// Fetch method and URI from somewhere
// for dynamic subfolder. https://github.com/nikic/FastRoute/issues/110
$base  = dirname($_SERVER['PHP_SELF']);
ltrim($base, '/') ? $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], strlen($base)) : '';
// end dynamic subfolder.
$httpMethod = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];

// Strip query string (?foo=bar) and decode URI
if (false !== $pos = strpos($uri, '?')) {
    $uri = substr($uri, 0, $pos);
}
$uri = rawurldecode($uri);

$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
switch ($routeInfo[0]) {
    case FastRoute\Dispatcher::NOT_FOUND:
        // ... 404 Not Found
        http_response_code(404);
        echo 'not found';
        break;
    case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
        $allowedMethods = $routeInfo[1];
        // ... 405 Method Not Allowed
        http_response_code(405);
        echo 'method not allowed';
        break;
    case FastRoute\Dispatcher::FOUND:
        $handler = $routeInfo[1];
        $vars = $routeInfo[2];
        // ... call $handler with $vars
        $handler($vars);
        break;
}

測試:

  • https://localhost/api => JSON '未找到'
  • https://localhost/api/hello => JSON '你好 API'
  • https://localhost/api/notfound => JSON '未找到'
  • https://localhost/api/notfound/notfound => JSON '未找到'
  • https://localhost/notfound => HTML '未找到'

選擇

我建議您改用 404 路由來處理這個問題。 以后管理你的代碼會更好更容易,因為它不會和正常的路由混在一起。

switch ($routeInfo[0]) {
    case FastRoute\Dispatcher::NOT_FOUND:
        // ... 404 Not Found
        http_response_code(404);
        $expUri = explode('/', $uri);
        if ($expUri[1] === 'api') {
            // if first url segment is api. please check this again in your application that it is [1] or [0] and correct it.
            header('Content-type: application/json');
            echo json_encode(['msg' => 'not found']);
        } else {
            echo 'not found';
        }
        break;
    // ...
}
我的完整代碼。
<?php
require 'vendor/autoload.php';


$dispatcher = \FastRoute\simpleDispatcher(function(\FastRoute\RouteCollector $r) {
    $r->addRoute('GET', '/hello[/]', function() {
        echo 'hello';
    });
    $r->addRoute('GET', '/hello/{name}', function($attribute) {
        echo 'hello ' . $attribute['name'];
    });
    $r->addGroup('/api', function (\FastRoute\RouteCollector $r) {
        $r->addRoute('GET', '/hello[/]', function() {
            header('Content-type: application/json');
            echo json_encode(['msg' => 'hello API']);
        });
    });
});

// Fetch method and URI from somewhere
// for dynamic subfolder. https://github.com/nikic/FastRoute/issues/110
$base  = dirname($_SERVER['PHP_SELF']);
ltrim($base, '/') ? $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], strlen($base)) : '';
// end dynamic subfolder.
$httpMethod = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];

// Strip query string (?foo=bar) and decode URI
if (false !== $pos = strpos($uri, '?')) {
    $uri = substr($uri, 0, $pos);
}
$uri = rawurldecode($uri);

$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
switch ($routeInfo[0]) {
    case FastRoute\Dispatcher::NOT_FOUND:
        // ... 404 Not Found
        http_response_code(404);
        $expUri = explode('/', $uri);
        if ($expUri[1] === 'api') {
            // if first url segment is api. please check this again in your application that it is [1] or [0] and correct it.
            header('Content-type: application/json');
            echo json_encode(['msg' => 'not found']);
        } else {
            echo 'not found';
        }
        break;
    case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
        $allowedMethods = $routeInfo[1];
        // ... 405 Method Not Allowed
        http_response_code(405);
        echo 'method not allowed';
        break;
    case FastRoute\Dispatcher::FOUND:
        $handler = $routeInfo[1];
        $vars = $routeInfo[2];
        // ... call $handler with $vars
        $handler($vars);
        break;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM