fiberphp / http
🌐 FiberPHP HTTP 子系统 —— 基于 Workerman 协议实现,支持请求/响应/中间件、协程管道、协程隔离。
Requires
- php: >=8.3
- ext-json: *
- fiberphp/container: dev-master
- fiberphp/framework: dev-master
- psr/log: ^3.0
- workerman/workerman: ^5.2
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
Suggests
- fiberphp/router: 注解路由支持(依赖本包)
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-07 02:44:50 UTC
README
FiberPHP 框架的 HTTP 子系统。基于 Workerman 协议层实现请求/响应/中间件,集成 Pipeline 协程管道与 Context 协程隔离,每个请求在独立 Fiber 中执行,中间件内可安全挂起做异步 I/O。
特性
- 协程隔离:每个请求
startScope开启独立 Context,endScope必清理,防跨请求泄漏 - Pipeline 管道:全局中间件按声明顺序串接,支持
Fiber::suspend()挂起/恢复 - 中间件双源:
config/http.php显式声明 +#[Package(middleware: [...])]子包声明,自动合并去重 - 异常兜底:
Handler优先App\ExceptionHandler,renderHttp()按方法约定(getHttpCode()/isMessageSafe()/getErrors())分层渲染,不依赖具体异常类 - 响应策略:keep-alive / chunked / close 自动判定,支持 If-Modified-Since 304 协商缓存
- URI 安全:拦截路径穿越(
/../、\、\0)、空路径、反斜杠 - 辅助函数:
request()/input()/response()/json()/xml()/redirect()/errcode()/route() - 统一路由表:约定式扫描与显式注册(注解/路由文件)合并为一张表,统一分发、DI 与中间件管线
环境要求
- PHP >= 8.3
ext-jsonworkerman/workerman^5.1- 依赖
fiberphp/framework(含包发现机制与#[Package]特性)、psr/log
安装
composer require fiberphp/http
安装后通过 Composer 钩子自动注册。config/http.php 作为包默认配置自动合并(装包即用,应用在自己的 config/http.php 放同名键覆盖);config/process/http.php 属进程配置,由安装钩子幂等发布到应用 config/process/。
配置
config/http.php — 中间件
return [
'middleware' => [
// 全局中间件类列表(对所有请求生效,按声明顺序串接)
'global' => [
// \App\Middleware\Cors::class,
// \App\Middleware\Auth::class,
],
// 中间件别名映射(路由/控制器中间件字符串先查别名再当类名)
'aliases' => [],
],
];
中间件类需实现 FiberPHP\Http\Contract\MiddlewareInterface 的 handle(Request, Closure): Response 方法。
config/process/http.php — Worker 进程
use FiberPHP\Http\HttpWorkerHandler;
use FiberPHP\Http\Request;
// 监听地址与 Worker 进程数支持环境变量覆盖(.env):
// SERVER_LISTEN=http://0.0.0.0:8080 SERVER_COUNT=auto(auto=按 CPU 核心数)
$listen = (string) env('SERVER_LISTEN', 'http://0.0.0.0:8787');
$count = env('SERVER_COUNT', 'auto');
return [
'http' => [
'enable' => true,
'handler' => HttpWorkerHandler::class,
'listen' => $listen,
'count' => $count === 'auto' ? max(1, cpu_count()) : (int) $count,
'constructor' => [
'requestClass' => Request::class,
],
],
];
使用
请求参数
// 获取全部参数
$params = request()->all();
// 单个参数(先 GET 后 POST,缺失返回默认值)
$id = request()->input('id', 0);
// 仅取 / 排除指定键
$data = request()->only(['name', 'email']);
$data = request()->except(['password']);
响应构造
// 纯文本
return response('hello');
// JSON
return json(['code' => 0, 'data' => $list]);
// XML
return xml($xmlElement);
// 重定向
return redirect('/login');
// 链式调用
return response('OK')
->withHeaders(['X-Trace-Id' => $traceId])
->withStatus(200);
文件响应
// 静态文件(命中 If-Modified-Since 返回 304)
return response()->file('/path/to/file.txt');
上传文件
$file = request()->file('avatar');
if ($file->isValid()) {
$tmpPath = $file->getFileName(); // 临时文件路径
$originalName = $file->getUploadName(); // 客户端原始文件名
$extension = $file->getUploadExtension(); // 扩展名
// 业务侧自行处理 move_uploaded_file / SplFileObject
}
客户端 IP
// 直连 IP
$ip = request()->getRemoteIp();
// 真实 IP(safeMode 下仅信任内网代理头)
$ip = request()->getRealIp(); // safeMode=true(默认)
$ip = request()->getRealIp(false); // 信任所有代理头
请求判定
request()->isGet();
request()->isPost();
request()->isAjax();
request()->isPjax();
request()->expectsJson(); // AJAX 非 PJAX 或 Accept: json
中间件
namespace App\Middleware;
use Closure;
use FiberPHP\Http\Contract\MiddlewareInterface;
use FiberPHP\Http\Request;
use FiberPHP\Http\Response;
class Auth implements MiddlewareInterface
{
public function handle(Request $request, Closure $next): Response
{
$token = $request->header('Authorization');
if (!$token) {
return json(['code' => 401, 'msg' => 'Unauthorized'], 401);
}
return $next($request); // 传递给下一层
}
}
注册到 config/http.php:
'middleware' => [
\App\Middleware\Auth::class,
],
路由 handler
HttpProvider 默认将 RequestHandlerInterface 绑定到内置 Router(统一路由表)。可在应用 Provider 中覆盖绑定实现自定义调度:
// App\Provider 中
$container->singleton(RequestHandlerInterface::class, MyHandler::class);
安装 fiberphp/router 后,注解与 route/*.php 路由文件注册进同一张路由表。
约定式路由
约定式路由始终启用,控制器目录固定为 app/Controller:
- 文件名映射 URI:
Index.php→/index,Admin/Role.php→/admin/role - 方法名前缀映射 HTTP 方法:
getList()→ GET/index/list,postCreate()→ POST/index/create - 无前缀方法(含
index)接受任意 HTTP 方法 Index控制器作为目录默认控制器:Index::index()同时映射/和/index- 类级
#[\FiberPHP\Http\Attribute\NoDefaultRoute]注解可关闭该类的约定路由 - 显式路由(注解/路由文件)与同 method+path 的约定条目冲突时,显式条目胜出
异常处理
业务/传输层异常统一使用 FiberPHP\Http\Exception 下两个类(继承框架异常基类,消息默认透传):
use FiberPHP\Http\Exception\HttpException;
use FiberPHP\Http\Exception\NotFoundHttpException;
// 404:URL 指向的资源不存在(路由未命中时框架内部也抛这个类)
throw new NotFoundHttpException('商品不存在');
// 任意 4xx/5xx:业务规则违反、限流、认证失败等
throw new HttpException(400, '分类编码已存在');
throw new HttpException(429, '请求过于频繁', headers: ['Retry-After' => '60']);
// 字段级校验失败由 fiberphp/validate 抛 ValidateException(422,自动携带 errors 明细)
| 异常类 | HTTP 状态码 | 说明 |
|---|---|---|
NotFoundHttpException | 404 | 资源/路由不存在,消息透传 |
HttpException($code, ...) | 传入码 | 业务拒绝、限流等,消息透传,headers 随响应下发 |
ValidateException(validate 包) | 422 | 字段校验失败,响应体自动携带 errors 明细 |
| 其他异常 | 500 | 生产环境统一收敛为 Server Error,debug 模式透出细节 |
errcode() 助手 —— 配置驱动的业务错误码
需要稳定业务码(监控聚合、前后端联调)时,用助手按 config/error.php 消息字典抛出(HTTP 恒 400):
errcode(10401); // 消息查配置,未配置回退 '业务错误'
errcode(10401, '分类【水果】已存在'); // 显式覆盖消息
// config/error.php
return [
'codes' => [
10401 => '分类编码已存在',
],
];
约定:
errcode()只表达业务拒绝(400);404 用NotFoundHttpException,422 用 validate 校验。
应用可创建 App\ExceptionHandler 继承 FiberPHP\Http\Exception\Handler,覆盖 renderHttp() 实现自定义渲染。