-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
153 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,9 +17,12 @@ Install using composer: | |
composer require utopia-php/framework | ||
``` | ||
|
||
Init your first application: | ||
Init your first application in `src/server.php`: | ||
|
||
```php | ||
require_once __DIR__ . '/../../vendor/autoload.php'; | ||
<?php | ||
|
||
require_once __DIR__.'/../vendor/autoload.php'; | ||
|
||
use Utopia\Http\Http; | ||
use Utopia\Http\Request; | ||
|
@@ -30,7 +33,7 @@ Http::get('/hello-world') // Define Route | |
->inject('request') | ||
->inject('response') | ||
->action( | ||
function($request, $response) { | ||
function(Request $request, Response $response) { | ||
$response | ||
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') | ||
->addHeader('Expires', '0') | ||
|
@@ -39,126 +42,206 @@ Http::get('/hello-world') // Define Route | |
} | ||
); | ||
|
||
Http::setMode(Http::MODE_TYPE_PRODUCTION); // Define Mode | ||
Http::setMode(Http::MODE_TYPE_PRODUCTION); | ||
|
||
$http = new Http(new Server(), 'America/New_York'); | ||
$http->start(); | ||
``` | ||
|
||
Run HTTP server: | ||
|
||
```bash | ||
php -S localhost:8000 src/server2.php | ||
``` | ||
|
||
Send HTTP request: | ||
|
||
$http = new Http(new Server(), 'America/New_York'); | ||
$http->run(); | ||
``` | ||
curl http://localhost:8000/hello-world | ||
``` | ||
|
||
### Server Adapters | ||
|
||
Library now supports server adapters and currently there are two servers implemented. You can use the PHP FPM server or the swoole server. | ||
Library supports server adapters to be able to run on any PHP setup. For instance, you could use FPM server, or the Swoole server. | ||
|
||
**Use PHP FPM server** | ||
|
||
```php | ||
require_once __DIR__ . '/../../vendor/autoload.php'; | ||
|
||
use Utopia\Http\Http; | ||
use Utopia\Http\Adapter\FPM\Request; | ||
use Utopia\Http\Adapter\FPM\Response; | ||
use Utopia\Http\Response; | ||
use Utopia\Http\Adapter\FPM\Server; | ||
|
||
Http::get('/hello-world') // Define Route | ||
->inject('request') | ||
Http::get('/') | ||
->inject('response') | ||
->action( | ||
function($request, $response) { | ||
$response | ||
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') | ||
->addHeader('Expires', '0') | ||
->addHeader('Pragma', 'no-cache') | ||
->json(['Hello' => 'World']); | ||
function(Response $response) { | ||
$response->send('Hello from PHP FPM'); | ||
} | ||
); | ||
|
||
Http::setMode(Http::MODE_TYPE_PRODUCTION); // Define Mode | ||
|
||
$http = new Http(new Server(), 'America/New_York'); | ||
$http->run(new Request(), new Response()); | ||
$http = new Http(new Server(), 'America/New_York'); | ||
$http->start(); | ||
``` | ||
|
||
**Using swoole server** | ||
**Using Swoole server** | ||
|
||
```php | ||
require_once __DIR__ . '/../../vendor/autoload.php'; | ||
|
||
use Utopia\Http\Http; | ||
use Utopia\Http\Adapter\Swoole\Request; | ||
use Utopia\Http\Adapter\Swoole\Response; | ||
use Utopia\Http\Request; | ||
use Utopia\Http\Response; | ||
use Utopia\Http\Adapter\Swoole\Server; | ||
use function Swoole\Coroutine\run; | ||
|
||
Http::get('/hello-world') // Define Route | ||
Http::get('/') | ||
->inject('request') | ||
->inject('response') | ||
->action( | ||
function($request, $response) { | ||
$response | ||
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') | ||
->addHeader('Expires', '0') | ||
->addHeader('Pragma', 'no-cache') | ||
->json(['Hello' => 'World']); | ||
function(Request $request, Response $response) { | ||
$response->send('Hello from Swoole'); | ||
} | ||
); | ||
|
||
Http::setMode(Http::MODE_TYPE_PRODUCTION); // Define Mode | ||
$http = new Http(new Server('0.0.0.0', '80'), 'America/New_York'); | ||
run(fn() => $http->start()); | ||
``` | ||
|
||
### Parameters | ||
|
||
$server = new Server('0.0.0.0', '80'); | ||
Parameters are used to recieve input into endpoint action from the HTTP request. Parameters could be defined as URL parameters, or could be defined in body with structure such as JSON. | ||
|
||
$server->onRequest(function (Request $request, Response $response) use ($server) { | ||
$http = new Http($server, 'UTC'); | ||
$http->run($request, $response); | ||
}); | ||
Every parameter must have a validator defined. Validators are simple classes that verify the input and ensure security of inputs. You can define your own validators, or use some of [built-in validators](https://github.com/utopia-php/framework/tree/master/src/Validator). | ||
|
||
Define an endpoint with params: | ||
|
||
```php | ||
Http::get('/') | ||
->param('name', 'World', new Text(256), 'Name to greet. Optional, max length 256.', true) | ||
->inject('response') | ||
->action(function(string $name, Response $response) { | ||
$response->send('Hello ' . $name); | ||
}); | ||
``` | ||
|
||
Send HTTP requests to ensure parameter works: | ||
|
||
$server->start(); | ||
```bash | ||
curl http://localhost:8000/hello-world | ||
curl http://localhost:8000/hello-world?name=Utopia | ||
curl http://localhost:8000/hello-world?name=Appwrite | ||
``` | ||
|
||
It's always recommended to use params instead of getting params or body directly from the request resource. If you do that intentionally, always ensure to run validation right after fetching such a raw input. | ||
|
||
### Hooks | ||
|
||
There are three types of hooks, init hooks, shutdown hooks and error hooks. Init hooks are executed before the route action is executed. Shutdown hook is executed after route action is executed before application shuts down. Finally error hooks are executed whenever there's an error in the application lifecycle. You can provide multiple hooks for each stage. If you do not assign groups to the hook, by default the hook will be executed for every route. | ||
There are three types of hooks: | ||
|
||
```php | ||
require_once __DIR__ . '/../../vendor/autoload.php'; | ||
- **Init hooks** are executed before the route action is executed | ||
- **Shutdown hooks** are executed after route action is finished, but before application shuts down | ||
- **Error hooks** are executed whenever there's an error in the application lifecycle. | ||
|
||
use Utopia\Http\Http; | ||
use Utopia\Http\Request; | ||
use Utopia\Http\Response; | ||
use Utopia\Http\Adapter\FPM\Server; | ||
You can provide multiple hooks for each stage. If you do not assign groups to the hook, by default the hook will be executed for every route. If a group is defined on a hook, it will only run during lifecycle of a request with the same group name on the action. | ||
|
||
```php | ||
Http::init() | ||
->inject('request') | ||
->action(function(Request $request) { | ||
\var_dump("Recieved: " . $request->getMethod() . ' ' . $request->getURI()); | ||
}); | ||
|
||
Http::shutdown() | ||
->inject('response') | ||
->action(function($response) { | ||
$response->addHeader('content-type', 'application/json'); | ||
->action(function(Response $response) { | ||
\var_dump('Responding with status code: ' . $response->getStatusCode()); | ||
}); | ||
|
||
Http::error() | ||
->inject('error') | ||
->inject('response') | ||
->action(function($error, $response) { | ||
->action(function(\Throwable $error, Response $response) { | ||
$response | ||
->setStatusCode(500) | ||
->send('Error occurred ' . $error); | ||
}); | ||
``` | ||
|
||
Http::get('/hello-world') // Define Route | ||
->inject('request') | ||
Hooks are designed to be actions ran during lifecycle of requests. Hooks should include functional logic. Hooks are not designed to prepare dependencies or context for the request. For such use case you should use resources. | ||
|
||
### Groups | ||
|
||
Groups allow you to define common behaviour for multiple endpoints. | ||
|
||
You can start by defining a group on an endpoint. Keep in mind you can also define multiple groups on a single endpoint. | ||
|
||
```php | ||
Http::get('/v1/health') | ||
->groups(['api', 'public']) | ||
->inject('response') | ||
->action( | ||
function($request, $response) { | ||
$response | ||
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') | ||
->addHeader('Expires', '0') | ||
->addHeader('Pragma', 'no-cache') | ||
->json(['Hello' => 'World']); | ||
function(Response $response) { | ||
$response->send('OK'); | ||
} | ||
); | ||
``` | ||
|
||
Now you can define hooks that would apply only to specific groups. Remember, hooks can also be assigned to multiple groups. | ||
|
||
Http::setMode(Http::MODE_TYPE_PRODUCTION); // Define Mode | ||
```php | ||
Http::init() | ||
->groups(['api']) | ||
->inject('request') | ||
->inject('response') | ||
->action(function(Request $request, Response $response) { | ||
$apiKey = $request->getHeader('x-api-key', ''); | ||
|
||
$http = new Http(new Server(), 'America/New_York'); | ||
$http->run(); | ||
if(empty($apiKey)) { | ||
$response | ||
->setStatusCode(Response::STATUS_CODE_UNAUTHORIZED) | ||
->send('API key missing.'); | ||
} | ||
}); | ||
``` | ||
|
||
Groups are designed to be actions ran during lifecycle of requests to endpoints that got some logic incommon. Groups allow you to prevent code duplication, and are designed to be defined anywhere in your source code to allow flexibility. | ||
|
||
### Resources | ||
|
||
Resources allows you to prepare dependencies for requests such as database connection or user which sent the request. A new instance of a resource is created for every request. | ||
|
||
Define a resource: | ||
|
||
```php | ||
Http::setResource('timing', function() { | ||
return \microtime(true); | ||
}); | ||
``` | ||
|
||
Inject resource into endpoint action: | ||
|
||
```php | ||
Http::get('/') | ||
->inject('timing') | ||
->inject('response') | ||
->action(function(float $timing, Response $response) { | ||
$response->send('Request Unix timestamp: ' . \strval($timing)); | ||
}); | ||
``` | ||
|
||
Inject resource into hook: | ||
|
||
```php | ||
Http::shutdown() | ||
->inject('timing') | ||
->action(function(float $timing) { | ||
$difference = \microtime(true) - $timing; | ||
\var_dump("Request took: " . $difference . " seconds"); | ||
}); | ||
``` | ||
|
||
In advanced scenarios, resources can also be injected into other resources or endpoint params. | ||
|
||
Resources are designed to prepare dependencies or context for the request. Resources are not meant to do functional logic or return callbacks. For such use case you should use hooks. | ||
|
||
## System Requirements | ||
|
||
Utopia Framework requires PHP 8.0 or later. We recommend using the latest PHP version whenever possible. | ||
|
@@ -169,23 +252,7 @@ Our ecosystem support other thin PHP projects aiming to extend the core PHP Utop | |
|
||
Each project is focused on solving a single, very simple problem and you can use composer to include any of them in your next project. | ||
|
||
Library | Description | ||
--- | --- | ||
**[Utopia AB](https://github.com/utopia-php/ab)** | Simple PHP library for managing AB testing on the server side. | ||
**[Utopia Abuse](https://github.com/utopia-php/abuse)** | Simple PHP library for rate limiting usage of different features in your app or API. | ||
**[Utopia Analytics](https://github.com/utopia-php/analytics)** | Simple PHP library to send information about events or pageviews to Google Analytics. | ||
**[Utopia Audit](https://github.com/utopia-php/audit)** | Simple PHP library for audit logging users actions and system events | ||
**[Utopia Cache](https://github.com/utopia-php/cache)** | Simple PHP library for managing cache with different storage adapters. | ||
**[Utopia CLI](https://github.com/utopia-php/cli)** | Simple PHP library for for building simple command line tools. | ||
**[Utopia Config](https://github.com/utopia-php/config)** | Simple PHP library for managing your app configuration. | ||
**[Utopia Database](https://github.com/utopia-php/database)** | Simple PHP library for managing application persistency. It supports multiple database adapters. | ||
**[Utopia Domains](https://github.com/utopia-php/domains)** | Simple PHP library for parsing domain names. | ||
**[Utopia Image](https://github.com/utopia-php/image)** | Simple PHP library for creating common image manipulations that is easy to use. | ||
**[Utopia Locale](https://github.com/utopia-php/locale)** | Simple PHP library for adding support to multiple locales in your app or API. | ||
**[Utopia Preloader](https://github.com/utopia-php/preloader)** | Simple PHP library for managing PHP preloading configuration. | ||
**[Utopia Registry](https://github.com/utopia-php/registry)** | Simple PHP library for dependency injection and lazy loading of objects or resources. | ||
**[Utopia System](https://github.com/utopia-php/system)** | Simple PHP library for obtaining information about the host's system. | ||
**[Utopia Storage](https://github.com/utopia-php/storage)** | Simple and lite PHP library for managing application storage. It supports multiple storage adapters. | ||
You can find all libraries in [GitHub Utopia organization](https://github.com/utopia-php). | ||
|
||
## Contributing | ||
|
||
|
@@ -197,12 +264,6 @@ You can refer to the [Contributing Guide](https://github.com/utopia-php/framewor | |
|
||
For security issues, please email [email protected] instead of posting a public issue in GitHub. | ||
|
||
### Testing | ||
|
||
- `docker-compose up -d` | ||
- `docker-compose exec web vendor/bin/phpunit --configuration phpunit.xml` | ||
- `docker-compose exec web vendor/bin/psalm --show-info=true` | ||
|
||
## Copyright and license | ||
|
||
The MIT License (MIT) [http://www.opensource.org/licenses/mit-license.php](http://www.opensource.org/licenses/mit-license.php) |