# The Basis for building HTTP applications

The httpsoft/http-basis package is a simple and fast HTTP microframework implementing PHP standards recommendations:

Package dependencies:

This package requires PHP version 7.4 or later.

# Building an HTTP Application

There are two ways to build an HTTP application:

# Package installation

It's recommended that you use Composer to install.

composer require httpsoft/http-basis

# Dependency injection

You can use any container that implements the Psr\Container\ContainerInterface.

/**
 * @var Psr\Container\ContainerInterface $container
 */

$container = new Container([
    'debug' => true,
    HttpSoft\Basis\Application::class => function (ContainerInterface $container) {
        return new HttpSoft\Basis\Application(
            $container->get(HttpSoft\Router\RouteCollector::class),
            $container->get(HttpSoft\Emitter\EmitterInterface::class),
            $container->get(HttpSoft\Runner\MiddlewarePipelineInterface::class),
            $container->get(HttpSoft\Runner\MiddlewareResolverInterface::class),
            new HttpSoft\Basis\Handler\NotFoundJsonHandler($container->get('debug'))
        );
    },
    HttpSoft\Emitter\EmitterInterface::class => fn() => new HttpSoft\Emitter\SapiEmitter(),
    HttpSoft\Router\RouteCollector::class => fn() => new HttpSoft\Router\RouteCollector(),
    HttpSoft\Runner\MiddlewarePipelineInterface::class => fn() => new HttpSoft\Runner\MiddlewarePipeline(),
    HttpSoft\Runner\MiddlewareResolverInterface::class => function (ContainerInterface $container) {
        return new HttpSoft\Runner\MiddlewareResolver($container);
    },
    HttpSoft\ErrorHandler\ErrorHandlerMiddleware::class => function (ContainerInterface $container) {
        return new HttpSoft\ErrorHandler\ErrorHandlerMiddleware(
            new HttpSoft\Basis\ErrorHandler\ErrorJsonResponseGenerator($container->get('debug'))
        );
    },
    HttpSoft\Cookie\CookieManagerInterface::class => fn() => new HttpSoft\Cookie\CookieManager(),
    Psr\Http\Message\ResponseFactoryInterface::class => fn() => new HttpSoft\Message\ResponseFactory(),
]);

This example uses dependencies for HTTP responses in JSON format that are used in the REST API. To render individual templates, you need to install any template engine and implement the HttpSoft\Basis\TemplateRendererInterface.

# Setup and run the application

Creating an application object.

$app = $container->get(HttpSoft\Basis\Application::class);

Setup middleware pipeline.

$app->pipe(HttpSoft\ErrorHandler\ErrorHandlerMiddleware::class);
$app->pipe(HttpSoft\Basis\Middleware\BodyParamsMiddleware::class);
$app->pipe(HttpSoft\Basis\Middleware\ContentLengthMiddleware::class);
$app->pipe(HttpSoft\Router\Middleware\RouteMatchMiddleware::class);
$app->pipe($adminMiddleware, '/admin');
// Any custom middleware.
$app->pipe(HttpSoft\Cookie\CookieSendMiddleware::class);
$app->pipe(HttpSoft\Router\Middleware\RouteDispatchMiddleware::class);

Add routes.

$app->get('home', '/', HomeHandler::class);
$app->get('list', '/list{[page]}', ListHandler::class)->tokens(['page' => '\d+']);
$app->get('view', '/view/{slug}', ViewHandler::class)->tokens(['slug' => '[\w-]+']);
$app->delete('delete', '/delete/{id}', DeleteHandler::class)->tokens(['id' => '\d+']);
$app->add('edit', '/(create|update)/{id}', EditHandler::class, ['GET', 'POST'])
    ->tokens(['id' => '\d+'])
;

Run application.

$app->run(HttpSoft\ServerRequest\ServerRequestCreator::create());

You may quickly test this using the built-in PHP server.

php -S 0.0.0.0:8080 -t public/

# Route handling

The example of adding routes uses fictitious class names (HomeHandler, ListHandler, etc.) as handlers. This approach allows you to organize the processing of each route in a separate class. These classes implement the Psr\Http\Server\RequestHandlerInterface, read more about handlers, see in HttpSoft\Runner\MiddlewareResolver.

use HttpSoft\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

final class HomeHandler implements RequestHandlerInterface
{
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        return new JsonResponse(['name' => 'HomeAction']);
    }
}

Handler objects will be created through the container, so they can accept dependencies in the constructor.

use HttpSoft\Basis\Response\PrepareJsonDataTrait;
use HttpSoft\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

final class ListHandler implements RequestHandlerInterface
{
    use PrepareJsonDataTrait;

    private Repository $repository;

    public function __construct(Repository $repository)
    {
        $this->repository = $repository;
    }

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        return new JsonResponse($this->prepareJsonData($this->repository->getAll()));
    }
}

# Error handling

The HttpSoft\ErrorHandler\ErrorHandlerMiddleware is responsible for error handling.

This package contains two response generators and one error listener, see details in HttpSoft\Basis\ErrorHandler.

Additionally, two request handlers have been created that return a 404 response, see details in HttpSoft\Basis\Handler.

Added some HTTP exceptions for convenience, see details in HttpSoft\Basis\Exception.

If this is not enough for you, you can easily add your own solutions and any additional functionality.