| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- <?php
- declare(strict_types=1);
- namespace app\miniapi\middleware;
- use Webman\Http\Request;
- use Webman\Http\Response;
- use Webman\MiddlewareInterface;
- use app\miniapi\http\ApiResponse;
- use app\miniapi\http\Input;
- use app\miniapi\exception\ApiException;
- final class ApiBoundary implements MiddlewareInterface
- {
- public function process(Request $request, callable $handler): Response
- {
- if (!ApiResponse::owns($request)) {
- return $handler($request);
- }
- $request->miniRequestId = bin2hex(random_bytes(16));
- $request->miniPrincipal = null;
- $origin = (string) $request->header('origin', '');
- $origins = (array) config('mini_api.allowed_origins', []);
- $started = microtime(true);
- // 临时停用 Origin 来源拒绝校验,联调结束后恢复。
- // if ($origin !== '' && !in_array($origin, $origins, true)) {
- // $response = ApiResponse::error($request, new ApiException(40301, '不允许的访问来源', 403));
- // }
- if ($request->method() === 'OPTIONS') {
- $response = new \support\Response(204);
- } elseif (strlen($request->rawBody()) > Input::bodyLimit($request)) {
- $response = ApiResponse::error($request, new ApiException(41301, '请求内容过大', 413));
- } else {
- $response = $handler($request);
- }
- foreach ([
- 'X-Request-Id' => ApiResponse::requestId($request),
- 'Cache-Control' => 'no-store',
- 'X-Content-Type-Options' => 'nosniff',
- ] as $name => $value) {
- $response->withHeader($name, $value);
- }
- if ($origin !== '' && in_array($origin, $origins, true)) {
- $response->withHeaders([
- 'Access-Control-Allow-Origin' => $origin,
- 'Vary' => 'Origin',
- 'Access-Control-Allow-Methods' => 'GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS',
- 'Access-Control-Allow-Headers' => 'Authorization, Content-Type',
- 'Access-Control-Expose-Headers' => 'X-Request-Id, Retry-After',
- ]);
- }
- \support\Log::info('mini_api.request', [
- 'request_id' => ApiResponse::requestId($request),
- 'method' => $request->method(),
- 'path' => $request->path(),
- 'status' => $response->getStatusCode(),
- 'duration_ms' => round((microtime(true) - $started) * 1000, 2),
- ]);
- return $response;
- }
- }
|