ingenerator / microframework
超轻量级的用于 Cloud Run / Lambda 等的服务器框架
Requires
- php: ~8.2.0
- guzzlehttp/psr7: ^2.7
- ingenerator/php-utils: ^2.0
Requires (Dev)
- fig/log-test: ^1.1
- guzzlehttp/guzzle: ^7.9.1
- phpunit/phpunit: ^10.5.28
- symfony/filesystem: ^7.1.2
README
microframework 提供了一个极其轻量级、具有偏见的框架,用于简单的 HTTP 请求处理器(例如 Cloud Run / Lambda / Cloud Functions 风格的端点)。
它提供
- 基本引导,包括设置时区和区域设置。
- 错误/异常处理,包括记录和渲染通用错误响应。
- 检测执行过程中/早期发送头部的意外输出。
- 请求记录(包括高精度延迟)。
- 将 PSR
ResponseInterface
对象渲染回客户端(包括状态码、头和主体)。
它设计并测试过,可以在 apache v2.4 下使用 mod_php、mod_prefork 和 mod_rewrite 运行。其他运行时配置可能也可以工作,但不是官方支持。
它不提供,也不会提供路由、运行时配置管理、依赖注入、HTML 模板、中间件、事件调度或更多功能齐全框架的类似功能。
入门
composer require ingenerator/microframework
处理请求
提供一个 PHP 文件作为您的入口点。这可以是 {Apache DocumentRoot}/index.php
或其他任何位置(例如,您可以将它放在一个更大的/更复杂的项目子目录中,其中包含使用不同框架的代码)。
<?php // index.php require_once(__DIR__.'/../vendor/autoload.php'); // *NO CODE HERE* // You should ideally not have any code that runs outside the functions passed into execute() below. This makes sure // that all code is wrapped in the output detection, error handling, and logging provided by microframework. (new Ingenerator\MicroFramework\MicroFramework)->execute( /* * --- REQUIRED CODE --- */ // You must provide a callable that returns a `LoggerProvider` // // The DefaultStackdriverLoggerProvider returns a logger that will log requests and custom entries to STDOUT in a // format suitable for ingestion into Google Stackdriver (including tagging exceptions for Google Error Reporting). // // You can alternatively provide a custom LoggerProvider that returns any PSR\Log\LoggerInterface along with a thin // RequestLogger class that will be called automatically to log the request itself. logger_provider_factory: fn () => new \Ingenerator\MicroFramework\DefaultStackdriverLoggerProvider( service_name: 'my-function', // For the DefaultStackdriverLoggerProvider, you need to give a path to a file that will return the current // version of your service - e.g. `<?php return 'ab9237723'` which you would usually write during docker build. // This will be included in the metadata for all log entries. version_file_path: __DIR__.'/../version.php' ), // Your actual implementation sits within a RequestHandler class. // - For the simplest functions, you can define this inline as an anonymous class - as in the example below. // - For more complex functions, you will probably want to define a normal PHP class in a separate file (e.g. // autoloadable by composer) and potentially a factory function to create it with any services / config it // requires. // // The only service / dependency that microframework provides to your code is the Logger - this is passed to // your factory function for you to use as required. handler_factory: fn(\Psr\Log\LoggerInterface $logger) => new class implements Ingenerator\MicroFramework\RequestHandler { // If you wish to write log entries from your own code, capture the logger as a constructor argument. public function __construct(private readonly $logger) {} public function handle(\Psr\Http\Message\ServerRequestInterface $request): \Psr\Http\Message\ResponseInterface { // Do whatever you want with the request here. // Microframework does not provide any routing - if you need to handle different requests with different // code, it is up to you to dispatch them appropriately. // When you are finished, return a PSR ResponseInterface. $this->logger->info('Got a request'); return new Response(200, headers: ['Content-Type'=> 'application/json'], body: '{"ok": true}'); } }, /* * * --- OPTIONAL CODE --- * */ // For ultra-precise latency measurement, you could capture start_hr_time as the very first line of PHP in the file // e.g. before requiring the composer autoloader. If not provided, it will default to when ->execute() is called. start_hr_time: hrtime(as_number: true), // Set a custom locale, if required (defaults to en_UK.utf-8) locale: 'en_US.utf-8', // Set a custom timezone (defaults to Europe/London) default_timezone: 'Europe/Paris', // Customise how the incoming request is parsed - e.g. if your runtime environment does not provide the request // in a structure that the default GuzzleHttp\Psr7\ServerRequest::fromGlobals() can understand. Provide a factory // function that returns a ServerRequestInterface request_factory: fn() => new \GuzzleHttp\Psr7\ServerRequest(/*request values from somewhere*/) ); // *NO CODE HERE* // Again, you should not have code that runs outside the `execute` call above. // If absolutely required and you e.g. need to run cleanup after the response has been sent / streamed to the client, // you could do that here - but be aware that it will not be covered by error handling or logging & will not be able to // modify response headers or output.
版本政策
该软件包遵循 semver。为了便于维护,任何给定的软件包版本将只支持单个 PHP 版本以及(数量很少的)composer 依赖项的每个小版本。
预计您可能需要更新您的函数代码到最新的支持的 PHP / composer 依赖项版本,才能升级到该软件包的较新小版本。
我们可能会偶尔针对旧版本的软件包发布错误修复版本,以解决安全问题或严重错误,但大部分更改将只应用于当前的小版本。
运行测试
该软件包有一些单元测试和集成测试,可以像往常一样使用 phpunit 运行。
我们还提供了一套黑盒测试,通过在支持的运行时环境中对软件包的发行版本进行 HTTP 请求,以验证软件包的整体行为。该测试环境相当具体,并使用 docker compose
和一些自定义脚本来确保测试的系统具有(仅)生产代码的确切副本。有关详细信息,请参阅 test/blackbox/README.md。
贡献
欢迎贡献,但在开始任何工作之前请与我们联系:这是一个具有偏见的软件包,我们可能有特定的要求/意见与您不同。
贡献者
此软件包由 inGenerator Ltd 赞助。
许可证
许可协议为 BSD-3-Clause-Licence。