# Class HttpSoft\Basis\Application

This class manages the fundamental processes of an HTTP application, using several independent components.

To use this class, you can simply create an instance with all the necessary dependencies, but it is better to use a dependency injection container that implements PSR-11. Using a container allows you to access the created dependencies and their data in other places in the application.

Source code on GitHub.

/**
 * @var Psr\Container\ContainerInterface $container
 * @var Psr\Http\Server\MiddlewareInterface $adminMiddleware
 */

$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());

# Public methods

public function __construct(
    HttpSoft\Router\RouteCollector $router,
    HttpSoft\Emitter\EmitterInterface $emitter,
    HttpSoft\Runner\MiddlewarePipelineInterface $pipeline,
    HttpSoft\Runner\MiddlewareResolverInterface $resolver,
    Psr\Http\Server\RequestHandlerInterface $default = null
);

# run

Runs the Psr\Http\Message\ServerRequestInterface implementation and emits the client an instance of Psr\Http\Message\ResponseInterface.

public function run(
    Psr\Http\Message\ServerRequestInterface $request, 
    Psr\Http\Server\RequestHandlerInterface $defaultHandler = null
): void;

If $defaultHandler was specified, it will be used as the default handler, otherwise $default passed to the constructor will be used.

If the default handler was set, the HttpSoft\Runner\MiddlewarePipelineInterface::process() method will be called, otherwise the HttpSoft\Runner\MiddlewarePipelineInterface::handle() method will be called.

# pipe

Adds a middleware to the pipeline.

public function pipe($middleware, string $pathPrefix = null): void;

$middleware is any valid value that can be converted to an instance of the Psr\Http\Server\MiddlewareInterface, see HttpSoft\Runner\MiddlewareResolver.

By specifying the path prefix, the middleware is attached to the specific path and will only be processed if the request URI path starts with the given prefix.

// Available: `https://example.com` and `https://example.com/any`:
$pipeline->pipe($commonMiddleware);
// Or
$pipeline->pipe($commonMiddleware, '');
// Or
$pipeline->pipe($commonMiddleware, '/');

// Available: `https://example.com/api` and `https://example.com/api/any`:
$pipeline->pipe($apiMiddleware, '/api');

// Available: `https://example.com/api/admin` and `https://example.com/api/admin/any`:
$pipeline->pipe($apiAdminMiddleware, '/api/admin');
// but not available: `https://example.com/api` and `https://example.com/api/any`.

The path prefix MUST start at the root, and the leading and trailing slashes are optional (/path or path or path/).

// One middleware can be attached to different paths:
$pipeline->pipe($authMiddleware, 'blog');
$pipeline->pipe($authMiddleware, '/forum');

// Multiple intermediate programs can be connected to the same path:
$pipeline->pipe($authMiddleware, 'admin/');
$pipeline->pipe($adminMiddleware, '/admin/');

# group

Creates a route group with a common path prefix.

/**
 * @param string $prefix common path prefix for the route group.
 * @param callable $callback callback that will add routes with a common path prefix.
 */
public function group(string $prefix, callable $callback): void;

The callback can take a HttpSoft\Router\RouteCollector instance as a parameter.

$app->group('/post', static function (RouteCollector $router) use ($handler): void {
    // '/post/post-slug'
    $router->get('post.view', '/{slug}', $handler)->tokens(['slug' => '[\w-]+']);
    // '/post' or '/post/2'
    $router->get('post.list', '/list{[page]}', $handler)->tokens(['page' => '\d+']);
    // '/post/delete/13'
    $router->delete('post.delete', '/delete/{id}', DeleteHandler::class)->tokens(['id' => '\d+']);
    // '/post/create/11' or '/post/update/12'
    $router->add('post.edit', '/(create|update)/{id}', EditHandler::class, ['GET', 'POST'])
        ->tokens(['id' => '\d+'])
    ;
});

# add

Adds a route and returns it.

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @param array $methods allowed request methods of the route.
 * @return HttpSoft\Router\Route
 */
public function add(string $name, string $pattern, $handler, array $methods): Route;

# any

Adds a generic route for any request methods and returns it.

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @return HttpSoft\Router\Route
 */
public function any(string $name, string $pattern, $handler): Route;

# get

Adds a route only for the GET method and returns it.

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @return HttpSoft\Router\Route
 */
public function get(string $name, string $pattern, $handler): Route;

# post

Adds a route only for the POST method and returns it.

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @return HttpSoft\Router\Route
 */
public function post(string $name, string $pattern, $handler): Route;

# put

Adds a route only for the PUT method and returns it.

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @return HttpSoft\Router\Route
 */
public function put(string $name, string $pattern, $handler): Route;

# patch

Adds a route only for the PATCH method and returns it.

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @return HttpSoft\Router\Route
 */
public function patch(string $name, string $pattern, $handler): Route;

# delete

Adds a route only for the DELETE method and returns it.

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @return HttpSoft\Router\Route
 */
public function delete(string $name, string $pattern, $handler): Route;

Adds a route only for the HEAD method and returns it.

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @return HttpSoft\Router\Route
 */
public function head(string $name, string $pattern, $handler): Route;

# options

Adds a route only for the OPTIONS method and returns it.

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @return HttpSoft\Router\Route
 */
public function options(string $name, string $pattern, $handler): Route;