You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Codeigniter 4 REST API客户端请求出现301永久重定向错误求助

问题:Codeigniter 4 REST API 客户端请求返回301 Moved Permanently,Postman可正常访问

环境:Laragon 5.0.0210523(Apache-2.4.47、PHP-8.1.7、MongoDB-4.0.28),搭建了集成firebase/php-jwt的Codeigniter 4 REST API应用。此前服务端与客户端均运行正常,停止Laragon服务次日重启后,客户端请求返回301错误,但Postman可正常访问API。已尝试重启Apache、MongoDB服务及Windows系统,排查URL错误无效,需解决方案。


REST API服务端配置

composer.json

***
"require": {
        "php": "^7.4 || ^8.0",
        "codeigniter4/framework": "^4.0",
        "mongodb/mongodb": "^1.12",
        "firebase/php-jwt": "^6.3"
    },
***

.env文件

***
JWT_SECRET_KEY = SomeThing$089
JWT_TIME_TO_LIVE = 3600

app.baseURL = 'http://ci4-api.localhost'
***

Route.php

***
$routes->get('/', 'Home::index');

$routes->resource('api/users');

$routes->post('api/auth', [\App\Controllers\Api\Auth::class, 'index']);
***

JWT_Helper.php

use App\Models\ModelUsers;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

/**
* @throws Exception
*/
function getJWT($authHeader)
{
    if (is_null($authHeader)){
        throw new Exception("Authentication JWT failed");
    }
    return explode(" ", $authHeader)[1];
}

function validateJWT($encodedToken)
{
    $key = getenv('JWT_SECRET_KEY');
    $decodedToken = JWT::decode($encodedToken, new Key($key, 'HS256'));
    $modelUsers = new ModelUsers();
    $modelUsers->get_email($decodedToken->email);
}

function createJWT($email): string
{
    $timeRequest = time();
    $timeToken = getenv('JWT_TIME_TO_LIVE');
    $timeExpired = $timeRequest + $timeToken;
    $payload = [
        'email' => $email,
        'iat' => $timeRequest,
        'exp' => $timeExpired,
    ];
    return JWT::encode($payload, getenv('JWT_SECRET_KEY'), 'HS256');
}

FilterJWT.php

namespace App\Filters;

use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use Exception;

class FilterJWT implements FilterInterface
{
    use ResponseTrait;

    public function before(RequestInterface $request, $arguments = null)
    {
        $header = $request->getServer('HTTP_AUTHORIZATION');
        try {
            helper('jwt');
            $encodedToken = getJWT($header);
            validateJWT($encodedToken);
            return $request;
        } catch (Exception $ex) {
            return Services::response()->setJSON(
                [
                    'error' => $ex->getMessage(),
                ]
            )->setStatusCode(ResponseInterface::HTTP_UNAUTHORIZED);
        }
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // TODO: Implement after() method.
    }
}

Filters.php

***
public $aliases = [
        'csrf'          => CSRF::class,
        'toolbar'      => DebugToolbar::class,
        'honeypot'      => Honeypot::class,
        'invalidchars'  => InvalidChars::class,
        'secureheaders' => SecureHeaders::class,
        'auth' => FilterJWT::class,
    ];
public $filters = [
        'auth' => [
            'before' => [
                'api/users/*',
                'api/users'
            ]
        ]
    ];
***

ModelUsers.php

namespace App\Models;

use App\Libraries\MongoDb;

class ModelUsers
{
    private $database = 'ci4_api';
    private $collection = 'user';
    private $conn;

    function __construct()
    {
        $mongodb = new MongoDb();
        $this->conn = $mongodb->getConn();
    }

    function get_user_list() {
        try {

            $filter = [];
            $query = new \MongoDB\Driver\Query($filter);

            $result = $this->conn->executeQuery($this->database. '.' . $this->collection, $query);

            return $result->toArray();

        } catch (\MongoDB\Driver\Exception\RuntimeException $ex) {
            show_error('Error while fetching users: ' . $ex->getMessage(), 500);
        }
    }
***

Auth.php

namespace App\Controllers\Api;

use App\Controllers\BaseController;
use App\Models\ModelUsers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Validation\Validation;
use Config\Services;

class Auth extends BaseController
{
    use ResponseTrait;

    private ModelUsers $model;
    private Validation $validation;

    function __construct()
    {
        $this->model = new ModelUsers();
        $this->validation = Services::validation();
    }

    public function index()
    {
        $email = $this->request->getVar('email');
        $password = $this->request->getVar('password');
        $password_hash = password_hash($password, PASSWORD_DEFAULT);

        $data1 = [
            'email' => $email,
            'password' => $password
        ];

        if (!$this->validation->run($data1, 'login')) {

            $errors = $this->validation->getErrors();

            $response = [
                'status' => 201,
                'error' => null,
                'messages' => [
                    'errors' => [
                        $errors
                    ]
                ],
            ];

            return $this->respond($response);
        }

        $data1 = $this->model->get_email($email);
        //return $this->respond($data1, 200);

        if (!$data1) {
            $response = [
                'status' => 201,
                'error' => null,
                'messages' => [
                    'error' => 'Data user atau password tidak ada1'
                ],
            ];

            return $this->respond($response, 200);
        }

        $password_user = $data1->password;

        if (password_verify($password_hash, $password_user) != 0){
            $response = [
                'status' => 201,
                'error' => null,
                'messages' => [
                    'error' => 'Data user atau password tidak ada2'
                ],
            ];

            return $this->respond($response, 200);
        }

        helper('jwt');
        $response = [
            'message' => 'Auth berhasil dilakukan',
            'data' => $data1,
            'access_token' => createJWT($email)
        ];

        return $this->respond($response, 200);
    }
***

Users.php

namespace App\Controllers\Api;

use App\Controllers\BaseController;
use App\Models\ModelUsers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\HTTP\Response;
use CodeIgniter\Validation\Validation;
use Config\Services;

class Users extends BaseController
{
    use ResponseTrait;

    private ModelUsers $model;
    private Validation $validation;

    function __construct()
    {
        $this->model = new ModelUsers();
        $this->validation = Services::validation();
    }

    public function index(): Response
    {
        $data = $this->model->get_user_list();
        $count = count($data);

        if ($count <= 0) {
            $data = [
                'status' => 201,
                'error' => null,
                'message' => [
                    'success' => 'Tidak ada data daftar pegawai'
                ],
            ];

        }
        return $this->respond($data, 200);

    }
***

REST客户端配置

.env文件

***
app.baseURL = 'http://ci4-test.localhost'
***

Routes.php

***
$routes->get('/rest', [\App\Controllers\Rest\RestClient::class, 'index']);
***

RestClient.php

namespace App\Controllers\Rest;

use App\Controllers\BaseController;
use Config\Services;

class RestClient extends BaseController
{
    public function index()
    {
        $client = Services::curlrequest();
        $token = "someToken";
        $url = "http://ci4-api.localhost/api/users/";
        $headers = [
            'Authorization' => 'Bearer ' . $token,
        ];

        $response = $client->request('GET', $url, ['headers' => $headers, 'http_errors' => false]);

        return $response->getBody();
    }
}

Postman测试情况

  • API认证请求正常
  • 获取用户列表请求正常

解决方案

1. 修正客户端请求URL的末尾斜杠

Codeigniter 4路由默认会对带末尾斜杠的URL返回301重定向(如/api/users/ → /api/users),Postman会自动跟随重定向,但CURL请求默认不处理。
修改客户端RestClient.php中的URL为:

$url = "http://ci4-api.localhost/api/users"; // 去掉末尾斜杠

2. 开启CURL跟随重定向

如果需要保留斜杠,可在CURL请求中添加重定向配置:

$response = $client->request('GET', $url, [
    'headers' => $headers,
    'http_errors' => false,
    'allow_redirects' => [
        'max' => 5, // 最大重定向次数
        'strict' => true,
        'referer' => true
    ]
]);

3. 检查服务端.htaccess配置

确认服务端项目根目录的.htaccess文件存在且配置正确,避免Apache重写规则异常:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]

4. 清除Codeigniter缓存

重启Laragon后可能存在缓存问题,删除服务端项目writable/cache目录下的所有文件,强制刷新路由配置。

5. 验证Apache虚拟主机配置

确认Laragon的虚拟主机配置中,ci4-api.localhost的根目录正确指向API项目,避免请求被路由到错误位置。


内容的提问来源于stack exchange,提问作者santo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:09:45