├── src ├── Exception │ ├── RuntimeException.php │ ├── BadMethodCallException.php │ ├── ExceptionInterface.php │ ├── InvalidArgumentException.php │ ├── DuplicateRouteException.php │ ├── ContainerNotRegisteredException.php │ ├── MissingDependencyException.php │ └── InvalidMiddlewareException.php ├── Container │ ├── Exception │ │ ├── ExceptionInterface.php │ │ └── InvalidServiceException.php │ ├── MiddlewareContainerFactory.php │ ├── ApplicationPipelineFactory.php │ ├── MiddlewareFactoryFactory.php │ ├── WhoopsErrorResponseGeneratorFactory.php │ ├── EmitterFactory.php │ ├── ErrorHandlerFactory.php │ ├── ErrorResponseGeneratorFactory.php │ ├── NotFoundHandlerFactory.php │ ├── ServerRequestErrorResponseGeneratorFactory.php │ ├── ApplicationFactory.php │ ├── ResponseFactoryFactory.php │ ├── StreamFactoryFactory.php │ ├── RequestHandlerRunnerFactory.php │ ├── ServerRequestFactoryFactory.php │ ├── WhoopsPageHandlerFactory.php │ ├── WhoopsFactory.php │ └── ApplicationConfigInjectionDelegator.php ├── Middleware │ ├── LazyLoadingMiddleware.php │ ├── ErrorResponseGenerator.php │ └── WhoopsErrorResponseGenerator.php ├── Response │ ├── ServerRequestErrorResponseGenerator.php │ └── ErrorResponseGeneratorTrait.php ├── MiddlewareContainer.php ├── constants.php ├── ConfigProvider.php ├── Handler │ └── NotFoundHandler.php ├── MiddlewareFactory.php └── Application.php ├── LICENSE.md ├── bin └── expressive-tooling ├── composer.json ├── README.md └── CHANGELOG.md /src/Exception/RuntimeException.php: -------------------------------------------------------------------------------- 1 | get(MiddlewareContainer::class) 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Container/WhoopsErrorResponseGeneratorFactory.php: -------------------------------------------------------------------------------- 1 | get('Zend\Expressive\Whoops') 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Container/EmitterFactory.php: -------------------------------------------------------------------------------- 1 | push(new SapiEmitter()); 23 | return $stack; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Exception/ContainerNotRegisteredException.php: -------------------------------------------------------------------------------- 1 | has(ErrorResponseGenerator::class) 22 | ? $container->get(ErrorResponseGenerator::class) 23 | : null; 24 | 25 | return new ErrorHandler($container->get(ResponseInterface::class), $generator); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Exception/MissingDependencyException.php: -------------------------------------------------------------------------------- 1 | has('config') ? $container->get('config') : []; 21 | 22 | $debug = $config['debug'] ?? false; 23 | 24 | $template = $config['zend-expressive']['error_handler']['template_error'] 25 | ?? ErrorResponseGenerator::TEMPLATE_DEFAULT; 26 | 27 | $layout = $config['zend-expressive']['error_handler']['layout'] 28 | ?? ErrorResponseGenerator::LAYOUT_DEFAULT; 29 | 30 | $renderer = $container->has(TemplateRendererInterface::class) 31 | ? $container->get(TemplateRendererInterface::class) 32 | : null; 33 | 34 | return new ErrorResponseGenerator($debug, $renderer, $template, $layout); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Container/NotFoundHandlerFactory.php: -------------------------------------------------------------------------------- 1 | has('config') ? $container->get('config') : []; 22 | $renderer = $container->has(TemplateRendererInterface::class) 23 | ? $container->get(TemplateRendererInterface::class) 24 | : null; 25 | $template = $config['zend-expressive']['error_handler']['template_404'] 26 | ?? NotFoundHandler::TEMPLATE_DEFAULT; 27 | $layout = $config['zend-expressive']['error_handler']['layout'] 28 | ?? NotFoundHandler::LAYOUT_DEFAULT; 29 | 30 | return new NotFoundHandler( 31 | $container->get(ResponseInterface::class), 32 | $renderer, 33 | $template, 34 | $layout 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Container/ServerRequestErrorResponseGeneratorFactory.php: -------------------------------------------------------------------------------- 1 | has('config') ? $container->get('config') : []; 22 | $debug = $config['debug'] ?? false; 23 | 24 | $renderer = $container->has(TemplateRendererInterface::class) 25 | ? $container->get(TemplateRendererInterface::class) 26 | : null; 27 | 28 | $template = $config['zend-expressive']['error_handler']['template_error'] 29 | ?? ServerRequestErrorResponseGenerator::TEMPLATE_DEFAULT; 30 | 31 | return new ServerRequestErrorResponseGenerator( 32 | $container->get(ResponseInterface::class), 33 | $debug, 34 | $renderer, 35 | $template 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2018, Zend Technologies USA, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | - Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | - Neither the name of Zend Technologies USA, Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from this 16 | software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/Container/ApplicationFactory.php: -------------------------------------------------------------------------------- 1 | get(MiddlewareFactory::class), 37 | $container->get(ApplicationPipeline::class), 38 | $container->get(RouteCollector::class), 39 | $container->get(RequestHandlerRunner::class) 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Middleware/LazyLoadingMiddleware.php: -------------------------------------------------------------------------------- 1 | container = $container; 36 | $this->middlewareName = $middlewareName; 37 | } 38 | 39 | /** 40 | * @throws InvalidMiddlewareException for invalid middleware types pulled 41 | * from the container. 42 | */ 43 | public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface 44 | { 45 | $middleware = $this->container->get($this->middlewareName); 46 | return $middleware->process($request, $handler); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Container/ResponseFactoryFactory.php: -------------------------------------------------------------------------------- 1 | get(ApplicationPipeline::class), 42 | $container->get(EmitterInterface::class), 43 | $container->get(ServerRequestInterface::class), 44 | $container->get(ServerRequestErrorResponseGenerator::class) 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Container/ServerRequestFactoryFactory.php: -------------------------------------------------------------------------------- 1 | debug = $isDevelopmentMode; 33 | $this->renderer = $renderer; 34 | $this->template = $template; 35 | $this->layout = $layout; 36 | } 37 | 38 | public function __invoke( 39 | Throwable $e, 40 | ServerRequestInterface $request, 41 | ResponseInterface $response 42 | ) : ResponseInterface { 43 | $response = $response->withStatus(Utils::getStatusCode($e, $response)); 44 | 45 | if ($this->renderer) { 46 | return $this->prepareTemplatedResponse( 47 | $e, 48 | $this->renderer, 49 | [ 50 | 'response' => $response, 51 | 'request' => $request, 52 | 'uri' => (string) $request->getUri(), 53 | 'status' => $response->getStatusCode(), 54 | 'reason' => $response->getReasonPhrase(), 55 | 'layout' => $this->layout, 56 | ], 57 | $this->debug, 58 | $response 59 | ); 60 | } 61 | 62 | return $this->prepareDefaultResponse($e, $this->debug, $response); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Response/ServerRequestErrorResponseGenerator.php: -------------------------------------------------------------------------------- 1 | responseFactory = function () use ($responseFactory) : ResponseInterface { 40 | return $responseFactory(); 41 | }; 42 | 43 | $this->debug = $isDevelopmentMode; 44 | $this->renderer = $renderer; 45 | $this->template = $template; 46 | } 47 | 48 | public function __invoke(Throwable $e) : ResponseInterface 49 | { 50 | $response = ($this->responseFactory)(); 51 | $response = $response->withStatus(Utils::getStatusCode($e, $response)); 52 | 53 | if ($this->renderer) { 54 | return $this->prepareTemplatedResponse( 55 | $e, 56 | $this->renderer, 57 | [ 58 | 'response' => $response, 59 | 'status' => $response->getStatusCode(), 60 | 'reason' => $response->getReasonPhrase(), 61 | ], 62 | $this->debug, 63 | $response 64 | ); 65 | } 66 | 67 | return $this->prepareDefaultResponse($e, $this->debug, $response); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/MiddlewareContainer.php: -------------------------------------------------------------------------------- 1 | container = $container; 29 | } 30 | 31 | /** 32 | * Returns true if the service is in the container, or resolves to an 33 | * autoloadable class name. 34 | * 35 | * @param string $service 36 | */ 37 | public function has($service) : bool 38 | { 39 | if ($this->container->has($service)) { 40 | return true; 41 | } 42 | 43 | return class_exists($service); 44 | } 45 | 46 | /** 47 | * Returns middleware pulled from container, or directly instantiated if 48 | * not managed by the container. 49 | * 50 | * @param string $service 51 | * @throws Exception\MissingDependencyException if the service does not 52 | * exist, or is not a valid class name. 53 | * @throws Exception\InvalidMiddlewareException if the service is not 54 | * an instance of MiddlewareInterface. 55 | */ 56 | public function get($service) : MiddlewareInterface 57 | { 58 | if (! $this->has($service)) { 59 | throw Exception\MissingDependencyException::forMiddlewareService($service); 60 | } 61 | 62 | $middleware = $this->container->has($service) 63 | ? $this->container->get($service) 64 | : new $service(); 65 | 66 | if ($middleware instanceof RequestHandlerInterface 67 | && ! $middleware instanceof MiddlewareInterface 68 | ) { 69 | $middleware = new RequestHandlerMiddleware($middleware); 70 | } 71 | 72 | if (! $middleware instanceof MiddlewareInterface) { 73 | throw Exception\InvalidMiddlewareException::forMiddlewareService($service, $middleware); 74 | } 75 | 76 | return $middleware; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/constants.php: -------------------------------------------------------------------------------- 1 | getBody() 70 | ->write($renderer->render($this->template, $templateData)); 71 | 72 | return $response; 73 | } 74 | 75 | private function prepareDefaultResponse( 76 | Throwable $e, 77 | bool $debug, 78 | ResponseInterface $response 79 | ) : ResponseInterface { 80 | $message = 'An unexpected error occurred'; 81 | 82 | if ($debug) { 83 | $message .= "; stack trace:\n\n" . $this->prepareStackTrace($e); 84 | } 85 | 86 | $response->getBody()->write($message); 87 | 88 | return $response; 89 | } 90 | 91 | /** 92 | * Prepares a stack trace to display. 93 | */ 94 | private function prepareStackTrace(Throwable $e) : string 95 | { 96 | $message = ''; 97 | do { 98 | $message .= sprintf( 99 | $this->stackTraceTemplate, 100 | get_class($e), 101 | $e->getFile(), 102 | $e->getLine(), 103 | $e->getMessage(), 104 | $e->getTraceAsString() 105 | ); 106 | } while ($e = $e->getPrevious()); 107 | 108 | return $message; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Container/WhoopsPageHandlerFactory.php: -------------------------------------------------------------------------------- 1 | 33 | * 'whoops' => [ 34 | * 'editor' => 'editor name, editor service name, or callable', 35 | * ] 36 | * 37 | * 38 | * If an editor is provided, it checks to see if it maps to a known service in 39 | * the container, and will use that; otherwise, it uses the value verbatim. 40 | */ 41 | class WhoopsPageHandlerFactory 42 | { 43 | public function __invoke(ContainerInterface $container) : PrettyPageHandler 44 | { 45 | $config = $container->has('config') ? $container->get('config') : []; 46 | $config = $config['whoops'] ?? []; 47 | 48 | $pageHandler = new PrettyPageHandler(); 49 | 50 | $this->injectEditor($pageHandler, $config, $container); 51 | 52 | return $pageHandler; 53 | } 54 | 55 | /** 56 | * Inject an editor into the whoops configuration. 57 | * 58 | * @see https://github.com/filp/whoops/blob/master/docs/Open%20Files%20In%20An%20Editor.md 59 | * @param array|\ArrayAccess $config 60 | * @throws Exception\InvalidServiceException for an invalid editor definition. 61 | */ 62 | private function injectEditor(PrettyPageHandler $handler, $config, ContainerInterface $container) : void 63 | { 64 | if (! isset($config['editor'])) { 65 | return; 66 | } 67 | 68 | $editor = $config['editor']; 69 | 70 | if (is_callable($editor)) { 71 | $handler->setEditor($editor); 72 | return; 73 | } 74 | 75 | if (! is_string($editor)) { 76 | throw new Exception\InvalidServiceException(sprintf( 77 | 'Whoops editor must be a string editor name, string service name, or callable; received "%s"', 78 | is_object($editor) ? get_class($editor) : gettype($editor) 79 | )); 80 | } 81 | 82 | if ($container->has($editor)) { 83 | $editor = $container->get($editor); 84 | } 85 | 86 | $handler->setEditor($editor); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/ConfigProvider.php: -------------------------------------------------------------------------------- 1 | $this->getDependencies(), 30 | ]; 31 | } 32 | 33 | public function getDependencies() : array 34 | { 35 | // @codingStandardsIgnoreStart 36 | return [ 37 | 'aliases' => [ 38 | DEFAULT_DELEGATE => Handler\NotFoundHandler::class, 39 | DISPATCH_MIDDLEWARE => Router\Middleware\DispatchMiddleware::class, 40 | IMPLICIT_HEAD_MIDDLEWARE => Router\Middleware\ImplicitHeadMiddleware::class, 41 | IMPLICIT_OPTIONS_MIDDLEWARE => Router\Middleware\ImplicitOptionsMiddleware::class, 42 | NOT_FOUND_MIDDLEWARE => Handler\NotFoundHandler::class, 43 | ROUTE_MIDDLEWARE => Router\Middleware\RouteMiddleware::class, 44 | ], 45 | 'factories' => [ 46 | Application::class => Container\ApplicationFactory::class, 47 | ApplicationPipeline::class => Container\ApplicationPipelineFactory::class, 48 | EmitterInterface::class => Container\EmitterFactory::class, 49 | ErrorHandler::class => Container\ErrorHandlerFactory::class, 50 | Handler\NotFoundHandler::class => Container\NotFoundHandlerFactory::class, 51 | MiddlewareContainer::class => Container\MiddlewareContainerFactory::class, 52 | MiddlewareFactory::class => Container\MiddlewareFactoryFactory::class, 53 | // Change the following in development to the WhoopsErrorResponseGeneratorFactory: 54 | Middleware\ErrorResponseGenerator::class => Container\ErrorResponseGeneratorFactory::class, 55 | RequestHandlerRunner::class => Container\RequestHandlerRunnerFactory::class, 56 | ResponseInterface::class => Container\ResponseFactoryFactory::class, 57 | Response\ServerRequestErrorResponseGenerator::class => Container\ServerRequestErrorResponseGeneratorFactory::class, 58 | ServerRequestInterface::class => Container\ServerRequestFactoryFactory::class, 59 | StreamInterface::class => Container\StreamFactoryFactory::class, 60 | ], 61 | ]; 62 | // @codingStandardsIgnoreEnd 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Container/WhoopsFactory.php: -------------------------------------------------------------------------------- 1 | 34 | * 'whoops' => [ 35 | * 'json_exceptions' => [ 36 | * 'display' => true, 37 | * 'show_trace' => true, 38 | * 'ajax_only' => true, 39 | * ] 40 | * ] 41 | * 42 | * 43 | * All values are booleans; omission of any implies boolean false. 44 | */ 45 | class WhoopsFactory 46 | { 47 | /** 48 | * Create and return an instance of the Whoops runner. 49 | */ 50 | public function __invoke(ContainerInterface $container) : Whoops 51 | { 52 | $config = $container->has('config') ? $container->get('config') : []; 53 | $config = $config['whoops'] ?? []; 54 | 55 | $whoops = new Whoops(); 56 | $whoops->allowQuit(false); 57 | $whoops->pushHandler($container->get('Zend\Expressive\WhoopsPageHandler')); 58 | $this->registerJsonHandler($whoops, $config); 59 | $whoops->register(); 60 | return $whoops; 61 | } 62 | 63 | /** 64 | * If configuration indicates a JsonResponseHandler, configure and register it. 65 | * 66 | * @param Whoops $whoops 67 | * @param array|\ArrayAccess $config 68 | * @return void 69 | */ 70 | private function registerJsonHandler(Whoops $whoops, $config) : void 71 | { 72 | if (empty($config['json_exceptions']['display'])) { 73 | return; 74 | } 75 | 76 | $handler = new JsonResponseHandler(); 77 | 78 | if (! empty($config['json_exceptions']['show_trace'])) { 79 | $handler->addTraceToOutput(true); 80 | } 81 | 82 | if (! empty($config['json_exceptions']['ajax_only'])) { 83 | if (method_exists(WhoopsUtil::class, 'isAjaxRequest')) { 84 | // Whoops 2.x; don't push handler on stack unless we are in 85 | // an XHR request. 86 | if (! WhoopsUtil::isAjaxRequest()) { 87 | return; 88 | } 89 | } elseif (method_exists($handler, 'onlyForAjaxRequests')) { 90 | // Whoops 1.x 91 | $handler->onlyForAjaxRequests(true); 92 | } 93 | } 94 | 95 | $whoops->pushHandler($handler); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /bin/expressive-tooling: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 1 ? $argv[1] : ''; 45 | $remove = false; 46 | 47 | switch (strtolower($command)) { 48 | case 'remove': 49 | echo "Removing zend-expressive-tooling\n"; 50 | $remove = true; 51 | $command = sprintf('%s remove --dev zendframework/zend-expressive-tooling', $composer); 52 | break; 53 | default: 54 | echo "Installing zend-expressive-tooling\n"; 55 | $command = sprintf('%s require --dev zendframework/zend-expressive-tooling', $composer); 56 | break; 57 | } 58 | 59 | system($command, $return); 60 | 61 | if ($return !== 0) { 62 | fwrite(STDERR, "\n\nRequested installation/removal failed; please check the logs above.\n"); 63 | exit($return); 64 | } 65 | 66 | if ($remove) { 67 | exit(0); 68 | } 69 | 70 | $toolingPackage = sprintf('%s/vendor/zendframework/zend-expressive-tooling/composer.json', getcwd()); 71 | 72 | if (! file_exists($toolingPackage)) { 73 | fwrite(STDERR, "\n\nInstalled tooling package, but unable to locate script information.\n"); 74 | fwrite(STDERR, "Check your installation, and follow the migration documentation to use the tooling.\n"); 75 | exit(1); 76 | } 77 | 78 | $composer = json_decode(file_get_contents($toolingPackage), true); 79 | if (! isset($composer['bin'])) { 80 | fwrite(STDERR, "\n\nInstalled tooling package, but package does not contain script information?\n"); 81 | fwrite(STDERR, "Check your installation, and follow the migration documentation to use the tooling.\n"); 82 | exit(1); 83 | } 84 | 85 | echo "\n\nTooling installed!\n"; 86 | echo "The following migration and development tools are now available:\n"; 87 | 88 | array_walk($composer['bin'], function ($script) { 89 | printf("- ./vendor/%s\n", $script); 90 | }); 91 | 92 | exit(0); 93 | -------------------------------------------------------------------------------- /src/Handler/NotFoundHandler.php: -------------------------------------------------------------------------------- 1 | responseFactory = function () use ($responseFactory) : ResponseInterface { 53 | return $responseFactory(); 54 | }; 55 | $this->renderer = $renderer; 56 | $this->template = $template; 57 | $this->layout = $layout; 58 | } 59 | 60 | /** 61 | * Creates and returns a 404 response. 62 | * 63 | * @param ServerRequestInterface $request Passed to internal handler 64 | */ 65 | public function handle(ServerRequestInterface $request) : ResponseInterface 66 | { 67 | if ($this->renderer === null) { 68 | return $this->generatePlainTextResponse($request); 69 | } 70 | 71 | return $this->generateTemplatedResponse($this->renderer, $request); 72 | } 73 | 74 | /** 75 | * Generates a plain text response indicating the request method and URI. 76 | */ 77 | private function generatePlainTextResponse(ServerRequestInterface $request) : ResponseInterface 78 | { 79 | $response = ($this->responseFactory)()->withStatus(StatusCodeInterface::STATUS_NOT_FOUND); 80 | $response->getBody() 81 | ->write(sprintf( 82 | 'Cannot %s %s', 83 | $request->getMethod(), 84 | (string) $request->getUri() 85 | )); 86 | 87 | return $response; 88 | } 89 | 90 | /** 91 | * Generates a response using a template. 92 | * 93 | * Template will receive the current request via the "request" variable. 94 | */ 95 | private function generateTemplatedResponse( 96 | TemplateRendererInterface $renderer, 97 | ServerRequestInterface $request 98 | ) : ResponseInterface { 99 | 100 | $response = ($this->responseFactory)()->withStatus(StatusCodeInterface::STATUS_NOT_FOUND); 101 | $response->getBody()->write( 102 | $renderer->render($this->template, ['request' => $request, 'layout' => $this->layout]) 103 | ); 104 | 105 | return $response; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zendframework/zend-expressive", 3 | "description": "PSR-15 Middleware Microframework", 4 | "license": "BSD-3-Clause", 5 | "keywords": [ 6 | "http", 7 | "middleware", 8 | "psr", 9 | "psr-7", 10 | "psr-11", 11 | "psr-15", 12 | "expressive", 13 | "zf", 14 | "zendframework", 15 | "zend-expressive" 16 | ], 17 | "support": { 18 | "docs": "https://docs.zendframework.com/zend-expressive/", 19 | "issues": "https://github.com/zendframework/zend-expressive/issues", 20 | "source": "https://github.com/zendframework/zend-expressive", 21 | "rss": "https://github.com/zendframework/zend-expressive/releases.atom", 22 | "slack": "https://zendframework-slack.herokuapp.com", 23 | "forum": "https://discourse.zendframework.com/c/questions/expressive" 24 | }, 25 | "require": { 26 | "php": "^7.1", 27 | "fig/http-message-util": "^1.1.2", 28 | "psr/container": "^1.0", 29 | "psr/http-message": "^1.0.1", 30 | "psr/http-server-middleware": "^1.0", 31 | "zendframework/zend-expressive-router": "^3.0", 32 | "zendframework/zend-expressive-template": "^2.0", 33 | "zendframework/zend-httphandlerrunner": "^1.0.1", 34 | "zendframework/zend-stratigility": "^3.0" 35 | }, 36 | "require-dev": { 37 | "filp/whoops": "^1.1.10 || ^2.1.13", 38 | "malukenho/docheader": "^0.1.6", 39 | "mockery/mockery": "^1.0", 40 | "phpstan/phpstan": "^0.9.2", 41 | "phpstan/phpstan-strict-rules": "^0.9", 42 | "phpunit/phpunit": "^7.0.1", 43 | "zendframework/zend-coding-standard": "~1.0.0", 44 | "zendframework/zend-diactoros": "^1.7.1 || ^2.0", 45 | "zendframework/zend-expressive-aurarouter": "^3.0", 46 | "zendframework/zend-expressive-fastroute": "^3.0", 47 | "zendframework/zend-expressive-zendrouter": "^3.0", 48 | "zendframework/zend-servicemanager": "^2.7.8 || ^3.3" 49 | }, 50 | "conflict": { 51 | "container-interop/container-interop": "<1.2.0", 52 | "zendframework/zend-diactoros": "<1.7.1" 53 | }, 54 | "suggest": { 55 | "filp/whoops": "^2.1 to use the Whoops error handler", 56 | "psr/http-message-implementation": "Please install a psr/http-message-implementation to consume Expressive; e.g., zendframework/zend-diactoros", 57 | "zendframework/zend-auradi-config": "^1.0 to use Aura.Di dependency injection container", 58 | "zendframework/zend-expressive-helpers": "^3.0 for its UrlHelper, ServerUrlHelper, and BodyParseMiddleware", 59 | "zendframework/zend-expressive-tooling": "^1.0 for migration and development tools; require it with the --dev flag", 60 | "zendframework/zend-pimple-config": "^1.0 to use Pimple for dependency injection container", 61 | "zendframework/zend-servicemanager": "^3.3 to use zend-servicemanager for dependency injection" 62 | }, 63 | "autoload": { 64 | "files": [ 65 | "src/constants.php" 66 | ], 67 | "psr-4": { 68 | "Zend\\Expressive\\": "src/" 69 | } 70 | }, 71 | "autoload-dev": { 72 | "psr-4": { 73 | "ZendTest\\Expressive\\": "test/" 74 | } 75 | }, 76 | "config": { 77 | "sort-packages": true 78 | }, 79 | "extra": { 80 | "branch-alias": { 81 | "dev-master": "3.2.x-dev", 82 | "dev-develop": "3.3.x-dev" 83 | }, 84 | "zf": { 85 | "config-provider": "Zend\\Expressive\\ConfigProvider" 86 | } 87 | }, 88 | "bin": [ 89 | "bin/expressive-tooling" 90 | ], 91 | "scripts": { 92 | "check": [ 93 | "@license-check", 94 | "@cs-check", 95 | "@test" 96 | ], 97 | "cs-check": "phpcs", 98 | "cs-fix": "phpcbf", 99 | "phpstan": "phpstan analyze -l max -c phpstan.neon ./src", 100 | "test": "phpunit --colors=always", 101 | "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", 102 | "license-check": "docheader check src/ test/" 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zend-expressive 2 | 3 | > ## Repository abandoned 2019-12-31 4 | > 5 | > This repository has moved to [mezzio/mezzio](https://github.com/mezzio/mezzio). 6 | 7 | [![Build Status](https://secure.travis-ci.org/zendframework/zend-expressive.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-expressive) 8 | [![Coverage Status](https://coveralls.io/repos/github/zendframework/zend-expressive/badge.svg?branch=master)](https://coveralls.io/github/zendframework/zend-expressive?branch=master) 9 | 10 | *Develop PSR-7 middleware applications in minutes!* 11 | 12 | zend-expressive builds on [zend-stratigility](https://github.com/zendframework/zend-stratigility) 13 | to provide a minimalist PSR-7 middleware framework for PHP, with the following 14 | features: 15 | 16 | - Routing. Choose your own router; we support: 17 | - [Aura.Router](https://github.com/auraphp/Aura.Router) 18 | - [FastRoute](https://github.com/nikic/FastRoute) 19 | - [zend-router](https://github.com/zendframework/zend-expressive-router) 20 | - DI Containers, via [PSR-11 Container](https://github.com/php-fig/container). 21 | Middleware matched via routing is retrieved from the composed container. 22 | - Optionally, templating. We support: 23 | - [Plates](http://platesphp.com/) 24 | - [Twig](http://twig.sensiolabs.org/) 25 | - [ZF2's PhpRenderer](https://github.com/zendframework/zend-view) 26 | 27 | ## Installation 28 | 29 | We provide two ways to install Expressive, both using 30 | [Composer](https://getcomposer.org): via our 31 | [skeleton project and installer](https://github.com/zendframework/zend-expressive-skeleton), 32 | or manually. 33 | 34 | ### Using the skeleton + installer 35 | 36 | The simplest way to install and get started is using the skeleton project, which 37 | includes installer scripts for choosing a router, dependency injection 38 | container, and optionally a template renderer and/or error handler. The skeleton 39 | also provides configuration for officially supported dependencies. 40 | 41 | To use the skeleton, use Composer's `create-project` command: 42 | 43 | ```bash 44 | $ composer create-project zendframework/zend-expressive-skeleton 45 | ``` 46 | 47 | This will prompt you through choosing your dependencies, and then create and 48 | install the project in the `` (omitting the `` will 49 | create and install in a `zend-expressive-skeleton/` directory). 50 | 51 | ### Manual Composer installation 52 | 53 | You can install Expressive standalone using Composer: 54 | 55 | ```bash 56 | $ composer require zendframework/zend-expressive 57 | ``` 58 | 59 | However, at this point, Expressive is not usable, as you need to supply 60 | minimally: 61 | 62 | - a router. 63 | - a dependency injection container. 64 | 65 | We currently support and provide the following routing integrations: 66 | 67 | - [Aura.Router](https://github.com/auraphp/Aura.Router): 68 | `composer require zendframework/zend-expressive-aurarouter` 69 | - [FastRoute](https://github.com/nikic/FastRoute): 70 | `composer require zendframework/zend-expressive-fastroute` 71 | - [zend-router](https://github.com/zendframework/zend-expressive-router): 72 | `composer require zendframework/zend-expressive-zendrouter` 73 | 74 | We recommend using a dependency injection container, and typehint against 75 | [PSR-11 Container](https://github.com/php-fig/container). We 76 | can recommend the following implementations: 77 | 78 | - [zend-servicemanager](https://github.com/zendframework/zend-servicemanager): 79 | `composer require zendframework/zend-servicemanager` 80 | - [Pimple](https://github.com/silexphp/Pimple) (see [docs](docs/book/features/container/pimple.md) for more details): 81 | `composer require zendframework/zend-pimple-config` 82 | - [Aura.Di](https://github.com/auraphp/Aura.Di) (see [docs](docs/book/features/container/aura-di.md) for more details): 83 | `composer require zendframework/zend-auradi-config` 84 | 85 | Additionally, you may optionally want to install a template renderer 86 | implementation, and/or an error handling integration. These are covered in the 87 | documentation. 88 | 89 | ## Documentation 90 | 91 | Documentation is [in the doc tree](docs/book/), and can be compiled using [mkdocs](http://www.mkdocs.org): 92 | 93 | ```bash 94 | $ mkdocs build 95 | ``` 96 | 97 | Additionally, public-facing, browseable documentation is available at 98 | https://docs.zendframework.com/zend-expressive/ 99 | -------------------------------------------------------------------------------- /src/Middleware/WhoopsErrorResponseGenerator.php: -------------------------------------------------------------------------------- 1 | whoops = $whoops; 53 | } 54 | 55 | public function __invoke( 56 | Throwable $e, 57 | ServerRequestInterface $request, 58 | ResponseInterface $response 59 | ) : ResponseInterface { 60 | // Walk through all handlers 61 | foreach ($this->whoops->getHandlers() as $handler) { 62 | // Add fancy data for the PrettyPageHandler 63 | if ($handler instanceof PrettyPageHandler) { 64 | $this->prepareWhoopsHandler($request, $handler); 65 | } 66 | 67 | // Set Json content type header 68 | if ($handler instanceof JsonResponseHandler) { 69 | $contentType = 'application/json'; 70 | 71 | // Whoops < 2.1.5 does not provide contentType method 72 | if (method_exists($handler, 'contentType')) { 73 | $contentType = $handler->contentType(); 74 | } 75 | 76 | $response = $response->withHeader('Content-Type', $contentType); 77 | } 78 | } 79 | 80 | $response = $response->withStatus(Utils::getStatusCode($e, $response)); 81 | 82 | $sendOutputFlag = $this->whoops->writeToOutput(); 83 | $this->whoops->writeToOutput(false); 84 | $response 85 | ->getBody() 86 | ->write($this->whoops->handleException($e)); 87 | $this->whoops->writeToOutput($sendOutputFlag); 88 | 89 | return $response; 90 | } 91 | 92 | /** 93 | * Prepare the Whoops page handler with a table displaying request information 94 | */ 95 | private function prepareWhoopsHandler(ServerRequestInterface $request, PrettyPageHandler $handler) : void 96 | { 97 | $uri = $request->getAttribute('originalUri', false) ?: $request->getUri(); 98 | $request = $request->getAttribute('originalRequest', false) ?: $request; 99 | 100 | $serverParams = $request->getServerParams(); 101 | $scriptName = $serverParams['SCRIPT_NAME'] ?? ''; 102 | 103 | $handler->addDataTable('Expressive Application Request', [ 104 | 'HTTP Method' => $request->getMethod(), 105 | 'URI' => (string) $uri, 106 | 'Script' => $scriptName, 107 | 'Headers' => $request->getHeaders(), 108 | 'Cookies' => $request->getCookieParams(), 109 | 'Attributes' => $request->getAttributes(), 110 | 'Query String Arguments' => $request->getQueryParams(), 111 | 'Body Params' => $request->getParsedBody(), 112 | ]); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/MiddlewareFactory.php: -------------------------------------------------------------------------------- 1 | container = $container; 60 | } 61 | 62 | /** 63 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface $middleware 64 | * @throws Exception\InvalidMiddlewareException if argument is not one of 65 | * the specified types. 66 | */ 67 | public function prepare($middleware) : MiddlewareInterface 68 | { 69 | if ($middleware instanceof MiddlewareInterface) { 70 | return $middleware; 71 | } 72 | 73 | if ($middleware instanceof RequestHandlerInterface) { 74 | return $this->handler($middleware); 75 | } 76 | 77 | if (is_callable($middleware)) { 78 | return $this->callable($middleware); 79 | } 80 | 81 | if (is_array($middleware)) { 82 | return $this->pipeline(...$middleware); 83 | } 84 | 85 | if (! is_string($middleware) || $middleware === '') { 86 | throw Exception\InvalidMiddlewareException::forMiddleware($middleware); 87 | } 88 | 89 | return $this->lazy($middleware); 90 | } 91 | 92 | /** 93 | * Decorate callable standards-signature middleware via a CallableMiddlewareDecorator. 94 | */ 95 | public function callable(callable $middleware) : CallableMiddlewareDecorator 96 | { 97 | return new CallableMiddlewareDecorator($middleware); 98 | } 99 | 100 | /** 101 | * Decorate a RequestHandlerInterface as middleware via RequestHandlerMiddleware. 102 | */ 103 | public function handler(RequestHandlerInterface $handler) : RequestHandlerMiddleware 104 | { 105 | return new RequestHandlerMiddleware($handler); 106 | } 107 | 108 | /** 109 | * Create lazy loading middleware based on a service name. 110 | */ 111 | public function lazy(string $middleware) : Middleware\LazyLoadingMiddleware 112 | { 113 | return new Middleware\LazyLoadingMiddleware($this->container, $middleware); 114 | } 115 | 116 | /** 117 | * Create a middleware pipeline from an array of middleware. 118 | * 119 | * This method allows passing an array of middleware as either: 120 | * 121 | * - discrete arguments 122 | * - an array of middleware, using the splat operator: pipeline(...$array) 123 | * - an array of middleware as the sole argument: pipeline($array) 124 | * 125 | * Each item is passed to prepare() before being passed to the 126 | * MiddlewarePipe instance the method returns. 127 | * 128 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface ...$middleware 129 | */ 130 | public function pipeline(...$middleware) : MiddlewarePipe 131 | { 132 | // Allow passing arrays of middleware or individual lists of middleware 133 | if (is_array($middleware[0]) 134 | && count($middleware) === 1 135 | ) { 136 | $middleware = array_shift($middleware); 137 | } 138 | 139 | $pipeline = new MiddlewarePipe(); 140 | foreach ($middleware as $m) { 141 | $pipeline->pipe($this->prepare($m)); 142 | } 143 | return $pipeline; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/Application.php: -------------------------------------------------------------------------------- 1 | factory = $factory; 51 | $this->pipeline = $pipeline; 52 | $this->routes = $routes; 53 | $this->runner = $runner; 54 | } 55 | 56 | /** 57 | * Proxies to composed pipeline to handle. 58 | * {@inheritDocs} 59 | */ 60 | public function handle(ServerRequestInterface $request) : ResponseInterface 61 | { 62 | return $this->pipeline->handle($request); 63 | } 64 | 65 | /** 66 | * Proxies to composed pipeline to process. 67 | * {@inheritDocs} 68 | */ 69 | public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface 70 | { 71 | return $this->pipeline->process($request, $handler); 72 | } 73 | 74 | /** 75 | * Run the application. 76 | * 77 | * Proxies to the RequestHandlerRunner::run() method. 78 | */ 79 | public function run() : void 80 | { 81 | $this->runner->run(); 82 | } 83 | 84 | /** 85 | * Pipe middleware to the pipeline. 86 | * 87 | * If two arguments are present, they are passed to pipe(), after first 88 | * passing the second argument to the factory's prepare() method. 89 | * 90 | * If only one argument is presented, it is passed to the factory prepare() 91 | * method. 92 | * 93 | * The resulting middleware, in both cases, is piped to the pipeline. 94 | * 95 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface $middlewareOrPath 96 | * Either the middleware to pipe, or the path to segregate the $middleware 97 | * by, via a PathMiddlewareDecorator. 98 | * @param null|string|array|callable|MiddlewareInterface|RequestHandlerInterface $middleware 99 | * If present, middleware or request handler to segregate by the path 100 | * specified in $middlewareOrPath. 101 | */ 102 | public function pipe($middlewareOrPath, $middleware = null) : void 103 | { 104 | $middleware = $middleware ?: $middlewareOrPath; 105 | $path = $middleware === $middlewareOrPath ? '/' : $middlewareOrPath; 106 | 107 | $middleware = $path !== '/' 108 | ? path($path, $this->factory->prepare($middleware)) 109 | : $this->factory->prepare($middleware); 110 | 111 | $this->pipeline->pipe($middleware); 112 | } 113 | 114 | /** 115 | * Add a route for the route middleware to match. 116 | * 117 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface $middleware 118 | * Middleware or request handler (or service name resolving to one of 119 | * those types) to associate with route. 120 | * @param null|array $methods HTTP method to accept; null indicates any. 121 | * @param null|string $name The name of the route. 122 | */ 123 | public function route(string $path, $middleware, array $methods = null, string $name = null) : Router\Route 124 | { 125 | return $this->routes->route( 126 | $path, 127 | $this->factory->prepare($middleware), 128 | $methods, 129 | $name 130 | ); 131 | } 132 | 133 | /** 134 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface $middleware 135 | * Middleware or request handler (or service name resolving to one of 136 | * those types) to associate with route. 137 | * @param null|string $name The name of the route. 138 | */ 139 | public function get(string $path, $middleware, string $name = null) : Router\Route 140 | { 141 | return $this->route($path, $middleware, ['GET'], $name); 142 | } 143 | 144 | /** 145 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface $middleware 146 | * Middleware or request handler (or service name resolving to one of 147 | * those types) to associate with route. 148 | * @param null|string $name The name of the route. 149 | */ 150 | public function post(string $path, $middleware, $name = null) : Router\Route 151 | { 152 | return $this->route($path, $middleware, ['POST'], $name); 153 | } 154 | 155 | /** 156 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface $middleware 157 | * Middleware or request handler (or service name resolving to one of 158 | * those types) to associate with route. 159 | * @param null|string $name The name of the route. 160 | */ 161 | public function put(string $path, $middleware, string $name = null) : Router\Route 162 | { 163 | return $this->route($path, $middleware, ['PUT'], $name); 164 | } 165 | 166 | /** 167 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface $middleware 168 | * Middleware or request handler (or service name resolving to one of 169 | * those types) to associate with route. 170 | * @param null|string $name The name of the route. 171 | */ 172 | public function patch(string $path, $middleware, string $name = null) : Router\Route 173 | { 174 | return $this->route($path, $middleware, ['PATCH'], $name); 175 | } 176 | 177 | /** 178 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface $middleware 179 | * Middleware or request handler (or service name resolving to one of 180 | * those types) to associate with route. 181 | * @param null|string $name The name of the route. 182 | */ 183 | public function delete(string $path, $middleware, string $name = null) : Router\Route 184 | { 185 | return $this->route($path, $middleware, ['DELETE'], $name); 186 | } 187 | 188 | /** 189 | * @param string|array|callable|MiddlewareInterface|RequestHandlerInterface $middleware 190 | * Middleware or request handler (or service name resolving to one of 191 | * those types) to associate with route. 192 | * @param null|string $name The name of the route. 193 | */ 194 | public function any(string $path, $middleware, string $name = null) : Router\Route 195 | { 196 | return $this->route($path, $middleware, null, $name); 197 | } 198 | 199 | /** 200 | * Retrieve all directly registered routes with the application. 201 | * 202 | * @return Router\Route[] 203 | */ 204 | public function getRoutes() : array 205 | { 206 | return $this->routes->getRoutes(); 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/Container/ApplicationConfigInjectionDelegator.php: -------------------------------------------------------------------------------- 1 | has('config')) { 53 | return $application; 54 | } 55 | 56 | $config = $container->get('config'); 57 | 58 | if (! empty($config['middleware_pipeline'])) { 59 | self::injectPipelineFromConfig($application, (array) $config); 60 | } 61 | if (! empty($config['routes'])) { 62 | self::injectRoutesFromConfig($application, (array) $config); 63 | } 64 | 65 | return $application; 66 | } 67 | 68 | /** 69 | * Inject a middleware pipeline from the middleware_pipeline configuration. 70 | * 71 | * Inspects the configuration provided to determine if a middleware pipeline 72 | * exists to inject in the application. 73 | * 74 | * Use the following configuration format: 75 | * 76 | * 77 | * return [ 78 | * 'middleware_pipeline' => [ 79 | * // An array of middleware to register with the pipeline. 80 | * // entries to register prior to routing/dispatching... 81 | * // - entry for \Zend\Expressive\Router\Middleware\PathBasedRoutingMiddleware::class 82 | * // - entry for \Zend\Expressive\Router\Middleware\MethodNotAllowedMiddleware::class 83 | * // - entry for \Zend\Expressive\Router\Middleware\DispatchMiddleware::class 84 | * // entries to register after routing/dispatching... 85 | * ], 86 | * ]; 87 | * 88 | * 89 | * Each item in the middleware_pipeline array must be of the following 90 | * specification: 91 | * 92 | * 93 | * [ 94 | * // required: 95 | * 'middleware' => 'Name of middleware service, or a callable', 96 | * // optional: 97 | * 'path' => '/path/to/match', 98 | * 'priority' => 1, // integer 99 | * ] 100 | * 101 | * 102 | * Note that the `path` element can only be a literal. 103 | * 104 | * `priority` is used to shape the order in which middleware is piped to the 105 | * application. Values are integers, with high values having higher priority 106 | * (piped earlier), and low/negative values having lower priority (piped last). 107 | * Default priority if none is specified is 1. Middleware with the same 108 | * priority are piped in the order in which they appear. 109 | * 110 | * Middleware piped may be either callables or service names. 111 | * 112 | * Additionally, you can specify an array of callables or service names as 113 | * the `middleware` value of a specification. Internally, this will create 114 | * a `Zend\Stratigility\MiddlewarePipe` instance, with the middleware 115 | * specified piped in the order provided. 116 | */ 117 | public static function injectPipelineFromConfig(Application $application, array $config) : void 118 | { 119 | if (empty($config['middleware_pipeline'])) { 120 | return; 121 | } 122 | 123 | // Create a priority queue from the specifications 124 | $queue = array_reduce( 125 | array_map(self::createCollectionMapper(), $config['middleware_pipeline']), 126 | self::createPriorityQueueReducer(), 127 | new SplPriorityQueue() 128 | ); 129 | 130 | foreach ($queue as $spec) { 131 | $path = $spec['path'] ?? '/'; 132 | $application->pipe($path, $spec['middleware']); 133 | } 134 | } 135 | 136 | /** 137 | * Inject routes from configuration. 138 | * 139 | * Introspects the provided configuration for routes to inject in the 140 | * application instance. 141 | * 142 | * The following configuration structure can be used to define routes: 143 | * 144 | * 145 | * return [ 146 | * 'routes' => [ 147 | * [ 148 | * 'path' => '/path/to/match', 149 | * 'middleware' => 'Middleware Service Name or Callable', 150 | * 'allowed_methods' => ['GET', 'POST', 'PATCH'], 151 | * 'options' => [ 152 | * 'stuff' => 'to', 153 | * 'pass' => 'to', 154 | * 'the' => 'underlying router', 155 | * ], 156 | * ], 157 | * // etc. 158 | * ], 159 | * ]; 160 | * 161 | * 162 | * Each route MUST have a path and middleware key at the minimum. 163 | * 164 | * The "allowed_methods" key may be omitted, can be either an array or the 165 | * value of the Zend\Expressive\Router\Route::HTTP_METHOD_ANY constant; any 166 | * valid HTTP method token is allowed, which means you can specify custom HTTP 167 | * methods as well. 168 | * 169 | * The "options" key may also be omitted, and its interpretation will be 170 | * dependent on the underlying router used. 171 | * 172 | * @throws InvalidArgumentException 173 | */ 174 | public static function injectRoutesFromConfig(Application $application, array $config) : void 175 | { 176 | if (empty($config['routes']) || ! is_array($config['routes'])) { 177 | return; 178 | } 179 | 180 | foreach ($config['routes'] as $key => $spec) { 181 | if (! isset($spec['path']) || ! isset($spec['middleware'])) { 182 | continue; 183 | } 184 | 185 | $methods = Route::HTTP_METHOD_ANY; 186 | if (isset($spec['allowed_methods'])) { 187 | $methods = $spec['allowed_methods']; 188 | if (! is_array($methods)) { 189 | throw new InvalidArgumentException(sprintf( 190 | 'Allowed HTTP methods for a route must be in form of an array; received "%s"', 191 | gettype($methods) 192 | )); 193 | } 194 | } 195 | 196 | $name = $spec['name'] ?? (is_string($key) ? $key : null); 197 | $route = $application->route( 198 | $spec['path'], 199 | $spec['middleware'], 200 | $methods, 201 | $name 202 | ); 203 | 204 | if (isset($spec['options'])) { 205 | $options = $spec['options']; 206 | if (! is_array($options)) { 207 | throw new InvalidArgumentException(sprintf( 208 | 'Route options must be an array; received "%s"', 209 | gettype($options) 210 | )); 211 | } 212 | 213 | $route->setOptions($options); 214 | } 215 | } 216 | } 217 | 218 | /** 219 | * Create the collection mapping function. 220 | * 221 | * Returns a callable with the following signature: 222 | * 223 | * 224 | * function (array|string $item) : array 225 | * 226 | * 227 | * If the 'middleware' value is missing, or not viable as middleware, it 228 | * raises an exception, to ensure the pipeline is built correctly. 229 | * 230 | * @throws InvalidArgumentException 231 | */ 232 | private static function createCollectionMapper() : callable 233 | { 234 | return function ($item) { 235 | if (! is_array($item) || ! array_key_exists('middleware', $item)) { 236 | throw new InvalidArgumentException(sprintf( 237 | 'Invalid pipeline specification received; must be an array' 238 | . ' containing a middleware key; received %s', 239 | is_object($item) ? get_class($item) : gettype($item) 240 | )); 241 | } 242 | 243 | return $item; 244 | }; 245 | } 246 | 247 | /** 248 | * Create reducer function that will reduce an array to a priority queue. 249 | * 250 | * Creates and returns a function with the signature: 251 | * 252 | * 253 | * function (SplQueue $queue, array $item) : SplQueue 254 | * 255 | * 256 | * The function is useful to reduce an array of pipeline middleware to a 257 | * priority queue. 258 | */ 259 | private static function createPriorityQueueReducer() : callable 260 | { 261 | // $serial is used to ensure that items of the same priority are enqueued 262 | // in the order in which they are inserted. 263 | $serial = PHP_INT_MAX; 264 | return function ($queue, $item) use (&$serial) { 265 | $priority = isset($item['priority']) && is_int($item['priority']) 266 | ? $item['priority'] 267 | : 1; 268 | $queue->insert($item, [$priority, $serial]); 269 | $serial -= 1; 270 | return $queue; 271 | }; 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file, in reverse chronological order by release. 4 | 5 | ## 3.2.2 - TBD 6 | 7 | ### Added 8 | 9 | - Nothing. 10 | 11 | ### Changed 12 | 13 | - Nothing. 14 | 15 | ### Deprecated 16 | 17 | - Nothing. 18 | 19 | ### Removed 20 | 21 | - Nothing. 22 | 23 | ### Fixed 24 | 25 | - [#663](https://github.com/zendframework/zend-expressive/pull/663) fixes parameter 26 | types in docblock for `Zend\Expressive\MiddlewareFactory::pipeline()` 27 | 28 | ## 3.2.1 - 2018-11-08 29 | 30 | ### Added 31 | 32 | - Nothing. 33 | 34 | ### Changed 35 | 36 | - Nothing. 37 | 38 | ### Deprecated 39 | 40 | - Nothing. 41 | 42 | ### Removed 43 | 44 | - Nothing. 45 | 46 | ### Fixed 47 | 48 | - [#646](https://github.com/zendframework/zend-expressive/pull/646) fixes behavior in the `MiddlewareContainer` when retrieving 49 | services that implement both `RequestHandlerInterface` and 50 | `MiddlewareInterface`. Previously, it incorrectly cast these values to 51 | `RequestHandlerMiddleware`, which could cause middleware pipelines to fail if 52 | they attempted to delegate back to the application middleware pipeline. These 53 | values are now correctly returned verbatim. 54 | 55 | ## 3.2.0 - 2018-09-27 56 | 57 | ### Added 58 | 59 | - [#637](https://github.com/zendframework/zend-expressive/pull/637) adds support for zendframework/zend-diactoros 2.0.0. You may use either 60 | a 1.Y or 2.Y version of that library with Expressive applications. 61 | 62 | ### Changed 63 | 64 | - Nothing. 65 | 66 | ### Deprecated 67 | 68 | - Nothing. 69 | 70 | ### Removed 71 | 72 | - Nothing. 73 | 74 | ### Fixed 75 | 76 | - [#634](https://github.com/zendframework/zend-expressive/pull/634) provides several minor performance and maintenance improvements. 77 | 78 | ## 3.1.0 - 2018-07-30 79 | 80 | ### Added 81 | 82 | - Nothing. 83 | 84 | ### Changed 85 | 86 | - [#629](https://github.com/zendframework/zend-expressive/pull/629) changes the constructor of `Zend\Expressive\Middleware\ErrorResponseGenerator` 87 | to accept an additional, optional argument, `$layout`, which defaults to a new 88 | constant value, `ErrorResponseGenerator::LAYOUT_DEFAULT`, or `layout::default`. 89 | `Zend\Expressive\Container\ErrorResponseGeneratorFactory` now also looks for 90 | the configuration value `zend-expressive.error_handler.layout`, and will use 91 | that value to seed the constructor argument. This change makes the 92 | `ErrorResponseGenerator` mirror the `NotFoundHandler`, allowing for a 93 | consistent layout between the two error pages. 94 | 95 | ### Deprecated 96 | 97 | - Nothing. 98 | 99 | ### Removed 100 | 101 | - Nothing. 102 | 103 | ### Fixed 104 | 105 | - Nothing. 106 | 107 | ## 3.0.3 - 2018-07-25 108 | 109 | ### Added 110 | 111 | - [#615](https://github.com/zendframework/zend-expressive/pull/615) adds a cookbook entry for accessing common data in templates. 112 | 113 | ### Changed 114 | 115 | - Nothing. 116 | 117 | ### Deprecated 118 | 119 | - Nothing. 120 | 121 | ### Removed 122 | 123 | - Nothing. 124 | 125 | ### Fixed 126 | 127 | - [#627](https://github.com/zendframework/zend-expressive/pull/627) fixes an issue in the Whoops response generator; previously, if an error or 128 | exception occurred in an `ErrorHandler` listener or prior to handling the pipeline, 129 | Whoops would fail to intercept, resulting in an empty response with status 200. With 130 | the patch, it properly intercepts and displays the errors. 131 | 132 | ## 3.0.2 - 2018-04-10 133 | 134 | ### Added 135 | 136 | - Nothing. 137 | 138 | ### Changed 139 | 140 | - Nothing. 141 | 142 | ### Deprecated 143 | 144 | - Nothing. 145 | 146 | ### Removed 147 | 148 | - Nothing. 149 | 150 | ### Fixed 151 | 152 | - [#612](https://github.com/zendframework/zend-expressive/pull/612) updates the 153 | `ApplicationConfigInjectionDelegator` delegator factory logic to cast the 154 | `$config` value to an array before passing it to its 155 | `injectPipelineFromConfig()` and `injectRoutesFromConfig()` methods, ensuring 156 | it will work correctly with containers that store the `config` service as an 157 | `ArrayObject` instead of an `array`. 158 | 159 | ## 3.0.1 - 2018-03-19 160 | 161 | ### Added 162 | 163 | - Nothing. 164 | 165 | ### Changed 166 | 167 | - [#596](https://github.com/zendframework/zend-expressive/pull/596) updates the 168 | `ApplicationConfigInjectionDelegator::injectRoutesFromConfig()` method to use 169 | the key name associated with a route specification if no `name` member is 170 | provided when creating a `Route` instance. This can help enforce name 171 | uniqueness when defining routes via configuration. 172 | 173 | ### Deprecated 174 | 175 | - Nothing. 176 | 177 | ### Removed 178 | 179 | - Nothing. 180 | 181 | ### Fixed 182 | 183 | - Nothing. 184 | 185 | ## 3.0.0 - 2018-03-15 186 | 187 | ### Added 188 | 189 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) adds support 190 | for the final PSR-15 interfaces, and explicitly depends on 191 | psr/http-server-middleware. 192 | 193 | - [#538](https://github.com/zendframework/zend-expressive/pull/538) adds scalar 194 | and return type hints to methods wherever possible. 195 | 196 | - [#562](https://github.com/zendframework/zend-expressive/pull/562) adds the 197 | class `Zend\Expressive\Response\ServerRequestErrorResponseGenerator`, and maps 198 | it to the `Zend\Expressive\Container\ServerRequestErrorResponseGeneratorFactory`. 199 | The class generates an error response when an exeption occurs producing a 200 | server request instance, and can be optionally templated. 201 | 202 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) adds a new 203 | class, `Zend\Expressive\MiddlewareContainer`. The class decorates a PSR-11 204 | `ContainerInterface`, and adds the following behavior: 205 | 206 | - If a class is not in the container, but exists, `has()` will return `true`. 207 | - If a class is not in the container, but exists, `get()` will attempt to 208 | instantiate it, caching the instance locally if it is valid. 209 | - Any instance pulled from the container or directly instantiated is tested. 210 | If it is a PSR-15 `RequestHandlerInterface`, it will decorate it in a 211 | zend-stratigility `RequestHandlerMiddleware` instance. If the instance is 212 | not a PSR-15 `MiddlewareInterface`, the container will raise a 213 | `Zend\Expressive\Exception\InvalidMiddlewareException`. 214 | 215 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) adds a new 216 | class, `Zend\Expressive\MiddlewareFactory`. The class composes a 217 | `MiddlewareContainer`, and exposes the following methods: 218 | 219 | - `callable(callable $middleware) : CallableMiddlewareDecorator` 220 | - `handler(RequestHandlerInterface $handler) : RequestHandlerMiddleware` 221 | - `lazy(string $service) : LazyLoadingMiddleware` 222 | - `prepare($middleware) : MiddlewareInterface`: accepts a string service name, 223 | callable, `RequestHandlerInterface`, `MiddlewareInterface`, or array of such 224 | values, and returns a `MiddlewareInterface`, raising an exception if it 225 | cannot determine what to do. 226 | - `pipeline(...$middleware) : MiddlewarePipe`: passes each argument to 227 | `prepare()`, and the result to `MiddlewarePipe::pipe()`, returning the 228 | pipeline when complete. 229 | 230 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) adds 231 | the following factory classes, each within the `Zend\Expressive\Container` 232 | namespace: 233 | 234 | - `ApplicationPipelineFactory`: creates and returns a 235 | `Zend\Stratigility\MiddlewarePipe` to use as the application middleware 236 | pipeline. 237 | - `DispatchMiddlewareFactory`: creates and returns a `Zend\Expressive\Router\DispatchMiddleware` instance. 238 | - `EmitterFactory`: creates and returns a 239 | `Zend\HttpHandlerRunner\Emitter\EmitterStack` instance composing an 240 | `SapiEmitter` from that same namespace as the only emitter on the stack. 241 | This is used as a dependency for the `Zend\HttpHandlerRunner\RequestHandlerRunner` 242 | service. 243 | - `MiddlewareContainerFactory`: creates and returns a `Zend\Expressive\MiddlewareContainer` 244 | instance decorating the PSR-11 container passed to the factory. 245 | - `MiddlewareFactoryFactory`: creates and returns a `Zend\Expressive\MiddlewareFactory` 246 | instance decorating a `MiddlewareContainer` instance as pulled from the 247 | container. 248 | - `RequestHandlerRunnerFactory`: creates and returns a 249 | `Zend\HttpHandlerRunner\RequestHandlerRunner` instance, using the services 250 | `Zend\Expressive\Application`, `Zend\HttpHandlerRunner\Emitter\EmitterInterface`, 251 | `Zend\Expressive\ServerRequestFactory`, and `Zend\Expressive\ServerRequestErrorResponseGenerator`. 252 | - `ServerRequestFactoryFactory`: creates and returns a `callable` factory for 253 | generating a PSR-7 `ServerRequestInterface` instance; this returned factory is a 254 | dependency for the `Zend\HttpHandlerRunner\RequestHandlerRunner` service. 255 | - `ServerRequestErrorResponseGeneratorFactory`: creates and returns a 256 | `callable` that accepts a PHP `Throwable` in order to generate a PSR-7 257 | `ResponseInterface` instance; this returned factory is a dependency for the 258 | `Zend\HttpHandlerRunner\RequestHandlerRunner` service, which uses it to 259 | generate a response in the scenario that the `ServerRequestFactory` is 260 | unable to create a request instance. 261 | 262 | - [#551](https://github.com/zendframework/zend-expressive/pull/551) and 263 | [#554](https://github.com/zendframework/zend-expressive/pull/554) add 264 | the following constants under the `Zend\Expressive` namespace: 265 | 266 | - `DEFAULT_DELEGATE` can be used to refer to the former `DefaultDelegate` FQCN 267 | service, and maps to the `Zend\Expressive\Handler\NotFoundHandler` service. 268 | - `IMPLICIT_HEAD_MIDDLEWARE` can be used to refer to the former 269 | `Zend\Expressive\Middleware\ImplicitHeadMiddleware` service, and maps to the 270 | `Zend\Expressive\Router\Middleware\ImplicitHeadMiddleware` service. 271 | - `IMPLICIT_OPTIONS_MIDDLEWARE` can be used to refer to the former 272 | `Zend\Expressive\Middleware\ImplicitOptionsMiddleware` service, and maps to the 273 | `Zend\Expressive\Router\Middleware\ImplicitOptionsMiddleware` service. 274 | - `NOT_FOUND_MIDDLEWARE` can be used to refer to the former 275 | `Zend\Expressive\Middleware\NotFoundMiddleware` service, and maps to the 276 | `Zend\Expressive\Handler\NotFoundHandler` service. 277 | 278 | ### Changed 279 | 280 | - [#579](https://github.com/zendframework/zend-expressive/pull/579) updates the 281 | version constraint for zend-expressive-router to use 3.0.0rc4 or later. 282 | 283 | - [#579](https://github.com/zendframework/zend-expressive/pull/579) updates the 284 | version constraint for zend-stratigility to use 3.0.0rc1 or later. 285 | 286 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) adds 287 | a dependency on zendframework/zend-httphandlerrunner 1.0.0 288 | 289 | - [#542](https://github.com/zendframework/zend-expressive/pull/542) modifies the 290 | `composer.json` to no longer suggest the pimple/pimple package, but rather the 291 | zendframework/zend-pimple-config package. 292 | 293 | - [#542](https://github.com/zendframework/zend-expressive/pull/542) modifies the 294 | `composer.json` to no longer suggest the aura/di package, but rather the 295 | zendframework/zend-auradi-config package. 296 | 297 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) updates the 298 | `Zend\Expressive\ConfigProvider` to reflect new, removed, and updated services 299 | and their factories. 300 | 301 | - [#554](https://github.com/zendframework/zend-expressive/pull/554) updates 302 | the `ConfigProvider` to add entries for the following constants as follows: 303 | 304 | - `IMPLICIT_HEAD_MIDDLEWARE` aliases to the `Zend\Expressive\Router\Middleware\ImplicitHeadMiddleware` service. 305 | - `IMPLICIT_OPTIONS_MIDDLEWARE` aliases to the `Zend\Expressive\Router\Middleware\ImplicitOptionsMiddleware` service. 306 | 307 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) updates 308 | `Zend\Expressive\Handler\NotFoundHandler` to implement the PSR-15 309 | `RequestHandlerInterface`. As `Zend\Expressive\Middleware\NotFoundHandler` is 310 | removed, `Zend\Expressive\Container\NotFoundHandlerFactory` has been 311 | re-purposedto create an instance of `Zend\Expressive\Handler\NotFoundHandler`. 312 | 313 | - [#561](https://github.com/zendframework/zend-expressive/pull/561) modifies the 314 | `Zend\Expressive\Handler\NotFoundHandler` to compose a response factory 315 | instead of a response prototype. 316 | 317 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) refactors 318 | `Zend\Expressive\Application` completely. 319 | 320 | The class no longer extends `Zend\Stratigility\MiddlewarePipe`, and instead 321 | implements the PSR-15 `MiddlewareInterface` and `RequestHandlerInterface`. 322 | 323 | It now **requires** the following dependencies via constructor injection, in 324 | the following order: 325 | 326 | - `Zend\Expressive\MiddlewareFactory` 327 | - `Zend\Stratigility\MiddlewarePipe`; this is the pipeline representing the application. 328 | - `Zend\Expressive\Router\RouteCollector` 329 | - `Zend\HttpHandlerRunner\RequestHandlerRunner` 330 | 331 | It removes all "getter" methods (as detailed in the "Removed" section of this 332 | release), but retains the following methods, with the changes described below. 333 | Please note: in most cases, these methods accept the same arguments as in the 334 | version 2 series, with the exception of callable double-pass middleware (these 335 | may be decorated manually using `Zend\Stratigility\doublePassMiddleware()`), 336 | and http-interop middleware (no longer supported; rewrite as PSR-15 337 | middleware). 338 | 339 | - `pipe($middlewareOrPath, $middleware = null) : void` passes its arguments to 340 | the composed `MiddlewareFactory`'s `prepare()` method; if two arguments are 341 | provided, the second is passed to the factory, and the two together are 342 | passed to `Zend\Stratigility\path()` in order to decorate them to work as 343 | middleware. The prepared middleware is then piped to the composed 344 | `MiddlewarePipe` instance. 345 | 346 | As a result of switching to use the `MiddlewareFactory` to prepare 347 | middleware, you may now pipe `RequestHandlerInterface` instances as well. 348 | 349 | - `route(string $path, $middleware, array $methods = null, string $name) : Route` 350 | passes its `$middleware` argument to the `MiddlewareFactory::prepare()` 351 | method, and then all arguments to the composed `RouteCollector` instance's 352 | `route()` method. 353 | 354 | As a result of switching to use the `MiddlewareFactory` to prepare 355 | middleware, you may now route to `RequestHandlerInterface` instances as 356 | well. 357 | 358 | - Each of `get`, `post`, `patch`, `put`, `delete`, and `any` now proxy to 359 | `route()` after marshaling the correct `$methods`. 360 | 361 | - `getRoutes() : Route[]` proxies to the composed `RouteCollector` instance. 362 | 363 | - `handle(ServerRequestInterface $request) : ResponseInterface` proxies to the 364 | composed `MiddlewarePipe` instance's `handle()` method. 365 | 366 | - `process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface` 367 | proxies to the composed `MiddlewarePipe` instance's `process()` method. 368 | 369 | - `run() : void` proxies to the composed `RequestHandlerRunner` instance. 370 | Please note that the method no longer accepts any arguments. 371 | 372 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) modifies the 373 | `Zend\Expressive\Container\ApplicationFactory` to reflect the changes to the 374 | `Zend\Expressive\Application` class as detailed above. It pulls the following 375 | services to inject via the constructor: 376 | 377 | - `Zend\Expressive\MiddlewareFactory` 378 | - `Zend\Stratigility\ApplicationPipeline`, which should resolve to a 379 | `MiddlewarePipe` instance; use the 380 | `Zend\Expressive\Container\ApplicationPipelineFactory`. 381 | - `Zend\Expressive\Router\RouteCollector` 382 | - `Zend\HttpHandlerRunner\RequestHandlerRunner` 383 | 384 | - [#581](https://github.com/zendframework/zend-expressive/pull/581) 385 | changes how the `ApplicationConfigInjectionDelegator::injectPipelineFromConfig()` 386 | method works. Previously, it would auto-inject routing and dispatch middleware 387 | if routes were configured, but no `middleware_pipeline` was present. 388 | Considering that this method will always be called manually, this 389 | functionality was removed; the method now becomes a no-op if no 390 | `middleware_pipeline` is present. 391 | 392 | - [#568](https://github.com/zendframework/zend-expressive/pull/568) updates the 393 | `ErrorHandlerFactory` to pull the `Psr\Http\Message\ResponseInterface` 394 | service, which returns a factory capable of returning a response instance, 395 | and passes it to the `Zend\Stratigility\Middleware\ErrorHandler` instance it 396 | creates, as that class changes in 3.0.0alpha4 such that it now expects a 397 | factory instead of an instance. 398 | 399 | - [#562](https://github.com/zendframework/zend-expressive/pull/562) extracts 400 | most logic from `Zend\Expressive\Middleware\ErrorResponseGenerator` to a new 401 | trait, `Zend\Expressive\Response\ErrorResponseGeneratorTrait`. A trait was 402 | used as the classes consuming it are from different namespaces, and thus 403 | different inheritance trees. The trait is used by both the 404 | `ErrorResponseGenerator` and the new `ServerRequestErrorResponseGenerator`. 405 | 406 | - [#551](https://github.com/zendframework/zend-expressive/pull/551) removes 407 | `Zend\Expressive\Container\RouteMiddlewareFactory`, as zend-expressive-router 408 | now provides a factory for the middleware. 409 | 410 | - [#551](https://github.com/zendframework/zend-expressive/pull/551) removes 411 | `Zend\Expressive\Container\DispatchMiddlewareFactory`, as zend-expressive-router 412 | now provides a factory for the middleware. 413 | 414 | - [#551](https://github.com/zendframework/zend-expressive/pull/551) removes 415 | `Zend\Expressive\Middleware\ImplicitHeadMiddleware`, as it is now provided by 416 | the zend-expressive-router package. 417 | 418 | - [#551](https://github.com/zendframework/zend-expressive/pull/551) removes 419 | `Zend\Expressive\Middleware\ImplicitOptionsMiddleware`, as it is now provided 420 | by the zend-expressive-router package. 421 | 422 | ### Deprecated 423 | 424 | - Nothing. 425 | 426 | ### Removed 427 | 428 | - [#529](https://github.com/zendframework/zend-expressive/pull/529) removes 429 | support for PHP versions prior to PHP 7.1. 430 | 431 | - [#529](https://github.com/zendframework/zend-expressive/pull/529) removes 432 | support for http-interop/http-middleware (previous PSR-15 iteration). 433 | 434 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) removes 435 | support for http-interop/http-server-middleware. 436 | 437 | - [#580](https://github.com/zendframework/zend-expressive/pull/580) removes 438 | zend-diactoros as a requirement; all usages of it within the package are 439 | currently conditional on it being installed, and can be replaced easily with 440 | any other PSR-7 implementation at this time. 441 | 442 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) removes the 443 | class `Zend\Expressive\Delegate\NotFoundDelegate`; use 444 | `Zend\Expressive\Handler\NotFoundHandler` instead. 445 | 446 | - [#546](https://github.com/zendframework/zend-expressive/pull/546) removes the 447 | service `Zend\Expressive\Delegate\DefaultDelegate`, as there is no longer a 448 | concept of a default handler invoked by the application. Instead, developers 449 | MUST pipe a request handler or middleware at the innermost layer of the 450 | pipeline guaranteed to return a response; we recommend using 451 | `Zend\Expressive\Handler\NotFoundHandler` for this purpose. 452 | 453 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) removes the 454 | class `Zend\Expressive\Middleware\RouteMiddleware`. Use the 455 | `RouteMiddleware` from zend-expressive-router instead. 456 | 457 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) removes the 458 | class `Zend\Expressive\Middleware\DispatchMiddleware`. Use the 459 | `DispatchMiddleware` from zend-expressive-router instead; the factory 460 | `Zend\Expressive\Container\DispatchMiddlewareFactory` will return an instance 461 | for you. 462 | 463 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) removes the 464 | class `Zend\Expressive\Emitter\EmitterStack`; use the class 465 | `Zend\HttpHandlerRunner\Emitter\EmitterStack` instead. 466 | 467 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) removes the 468 | following methods from `Zend\Expressive\Application`: 469 | 470 | - `pipeRoutingMiddleware()`: use `pipe(\Zend\Expressive\Router\RouteMiddleware::class)` instead. 471 | - `pipeDispatchMiddleware()`: use `pipe(\Zend\Expressive\Router\DispatchMiddleware::class)` instead. 472 | - `getContainer()` 473 | - `getDefaultDelegate()`: ensure you pipe middleware or a request handler 474 | capable of returning a response at the innermost layer; 475 | `Zend\Expressive\Handler\NotFoundHandler` can be used for this. 476 | - `getEmitter()`: use the `Zend\HttpHandlerRunner\Emitter\EmitterInterface` service from the container. 477 | - `injectPipelineFromConfig()`: use the new `ApplicationConfigInjectionDelegator` and/or the static method of the same name it defines. 478 | - `injectRoutesFromConfig()`: use the new `ApplicationConfigInjectionDelegator` and/or the static method of the same name it defines. 479 | 480 | - [#543](https://github.com/zendframework/zend-expressive/pull/543) removes the 481 | class `Zend\Expressive\AppFactory`. 482 | 483 | - The internal `Zend\Expressive\MarshalMiddlewareTrait`, 484 | `Zend\Expressive\ApplicationConfigInjectionTrait`, and 485 | `Zend\Expressive\IsCallableMiddlewareTrait` have been removed. 486 | 487 | ### Fixed 488 | 489 | - [#574](https://github.com/zendframework/zend-expressive/pull/574) updates the 490 | classes `Zend\Expressive\Exception\InvalidMiddlewareException` and 491 | `MissingDependencyException` to implement the 492 | [PSR-11](https://www.php-fig.org/psr/psr-11/) `ContainerExceptionInterface`. 493 | 494 | ## 2.2.0 - 2018-03-12 495 | 496 | ### Added 497 | 498 | - [#581](https://github.com/zendframework/zend-expressive/pull/581) adds the 499 | class `Zend\Expressive\ConfigProvider`, and exposes it to the 500 | zend-component-installer Composer plugin. We recommend updating your 501 | `config/config.php` to reference it, as well as the 502 | `Zend\Expressive\Router\ConfigProvider` shipped with zend-expressive-router 503 | versions 2.4 and up. 504 | 505 | - [#581](https://github.com/zendframework/zend-expressive/pull/581) adds the 506 | class `Zend\Expressive\Container\ApplicationConfigInjectionDelegator`. The 507 | class can act as a delegator factory, and, when enabled, will inject routes 508 | and pipeline middleware defined in configuration. 509 | 510 | Additionally, the class exposes two static methods: 511 | 512 | - `injectPipelineFromConfig(Application $app, array $config)` 513 | - `injectRoutesFromConfig(Application $app, array $config)` 514 | 515 | These may be called to modify an `Application` instance based on an array of 516 | configuration. See thd documentation for more details. 517 | 518 | - [#581](https://github.com/zendframework/zend-expressive/pull/581) adds the 519 | class `Zend\Expressive\Handler\NotFoundHandler`; the class takes over the 520 | functionality previously provided in `Zend\Expressive\Delegate\NotFoundDelegate`. 521 | 522 | ### Changed 523 | 524 | - [#581](https://github.com/zendframework/zend-expressive/pull/581) updates the 525 | minimum supported zend-stratigility version to 2.2.0. 526 | 527 | - [#581](https://github.com/zendframework/zend-expressive/pull/581) updates the 528 | minimum supported zend-expressive-router version to 2.4.0. 529 | 530 | ### Deprecated 531 | 532 | - [#581](https://github.com/zendframework/zend-expressive/pull/581) deprecates 533 | the following classes and traits: 534 | 535 | - `Zend\Expressive\AppFactory`: if you are using this, you will need to switch 536 | to direct usage of `Zend\Expressive\Application` or a 537 | `Zend\Stratigility\MiddlewarePipe` instance. 538 | 539 | - `Zend\Expressive\ApplicationConfigInjectionTrait`: if you are using it, it is 540 | marked internal, and deprecated; it will be removed in version 3. 541 | 542 | - `Zend\Expressive\Container\NotFoundDelegateFactory`: the `NotFoundDelegate` 543 | will be renamed to `Zend\Expressive\Handler\NotFoundHandler` in version 3, 544 | making this factory obsolete. 545 | 546 | - `Zend\Expressive\Delegate\NotFoundDelegate`: this class becomes 547 | `Zend\Expressive\Handler\NotFoundHandler` in v3, and the new class is added in 548 | version 2.2 as well. 549 | 550 | - `Zend\Expressive\Emitter\EmitterStack`: the emitter concept is extracted from 551 | zend-diactoros to a new component, zend-httphandlerrunner. This latter 552 | component is used in version 3, and defines the `EmitterStack` class. Unless 553 | you are extending it or interacting with it directly, this change should not 554 | affect you; the `Zend\Diactoros\Response\EmitterInterface` service will be 555 | directed to the new class in that version. 556 | 557 | - `Zend\Expressive\IsCallableInteropMiddlewareTrait`: if you are using it, it is 558 | marked internal, and deprecated; it will be removed in version 3. 559 | 560 | - `Zend\Expressive\MarshalMiddlewareTrait`: if you are using it, it is marked 561 | internal, and deprecated; it will be removed in version 3. 562 | 563 | - `Zend\Expressive\Middleware\DispatchMiddleware`: this functionality has been 564 | moved to zend-expressive-router, under the `Zend\Expressive\Router\Middleware` 565 | namespace. 566 | 567 | - `Zend\Expressive\Middleware\ImplicitHeadMiddleware`: this functionality has been 568 | moved to zend-expressive-router, under the `Zend\Expressive\Router\Middleware` 569 | namespace. 570 | 571 | - `Zend\Expressive\Middleware\ImplicitOptionsMiddleware`: this functionality has been 572 | moved to zend-expressive-router, under the `Zend\Expressive\Router\Middleware` 573 | namespace. 574 | 575 | - `Zend\Expressive\Middleware\NotFoundHandler`: this will be removed in 576 | version 3, where you can instead pipe `Zend\Expressive\Handler\NotFoundHandler` 577 | directly instead. 578 | 579 | - `Zend\Expressive\Middleware\RouteMiddleware`: this functionality has been 580 | moved to zend-expressive-router, under the `Zend\Expressive\Router\Middleware` 581 | namespace. 582 | 583 | - [#581](https://github.com/zendframework/zend-expressive/pull/581) deprecates 584 | the following methods from `Zend\Expressive\Application`: 585 | - `pipeRoutingMiddleware()` 586 | - `pipeDispatchMiddleware()` 587 | - `getContainer()`: this method is removed in version 3; container access will only be via the bootstrap. 588 | - `getDefaultDelegate()`: the concept of a default delegate is removed in version 3. 589 | - `getEmitter()`: emitters move to a different collaborator in version 3. 590 | - `injectPipelineFromConfig()` andd `injectRoutesFromConfig()` are methods 591 | defined by the `ApplicationConfigInjectionTrait`, which will be removed in 592 | version 3. Use the `ApplicationConfigInjectionDelegator` instead. 593 | 594 | ### Removed 595 | 596 | - Nothing. 597 | 598 | ### Fixed 599 | 600 | - Nothing. 601 | 602 | ## 2.1.1 - 2018-03-09 603 | 604 | ### Added 605 | 606 | - Nothing. 607 | 608 | ### Changed 609 | 610 | - Nothing. 611 | 612 | ### Deprecated 613 | 614 | - Nothing. 615 | 616 | ### Removed 617 | 618 | - Nothing. 619 | 620 | ### Fixed 621 | 622 | - [#583](https://github.com/zendframework/zend-expressive/pull/583) provides a 623 | number of minor fixes and test changes to ensure the component works with the 624 | zend-expressive-router 2.4 version. In particular, configuration-driven routes 625 | will now work properly across all versions, without deprecation notices. 626 | 627 | - [#582](https://github.com/zendframework/zend-expressive/pull/582) fixes 628 | redirects in the documentation. 629 | 630 | ## 2.1.0 - 2017-12-11 631 | 632 | ### Added 633 | 634 | - [#480](https://github.com/zendframework/zend-expressive/pull/480) updates the 635 | `ImplicitHeadMiddleware` to add a request attribute indicating the request was 636 | originally generated for a `HEAD` request before delegating the request; you 637 | can now pull the attribute `Zend\Expressive\Middleware\ImplicitHeadMiddleware::FORWARDED_HTTP_METHOD_ATTRIBUTE` 638 | in your own middleware in order to vary behavior in these scenarios. 639 | 640 | ### Changed 641 | 642 | - [#505](https://github.com/zendframework/zend-expressive/pull/505) modifies 643 | `Zend\Expressive\Application` to remove implementation of `__call()` in favor 644 | of the following new methods: 645 | 646 | - `get($path, $middleware, $name = null)` 647 | - `post($path, $middleware, $name = null)` 648 | - `put($path, $middleware, $name = null)` 649 | - `patch($path, $middleware, $name = null)` 650 | - `delete($path, $middleware, $name = null)` 651 | 652 | This change is an internal implementation detail only, and will not affect 653 | existing implementations or extensions. 654 | 655 | - [#511](https://github.com/zendframework/zend-expressive/pull/511) modifies 656 | the `NotFoundDelegate` to accept an optional `$layout` argument to its 657 | constructor; the value defaults to `layout::default` if not provided. That 658 | value will be passed for the `layout` template variable when the delegate 659 | renders a template, allowing zend-view users (and potentially other template 660 | systems) to customize the layout template used for reporting errors. 661 | 662 | You may provide the template via the configuration 663 | `zend-expressive.error_handler.layout`. 664 | 665 | ### Deprecated 666 | 667 | - Nothing. 668 | 669 | ### Removed 670 | 671 | - Nothing. 672 | 673 | ### Fixed 674 | 675 | - Nothing. 676 | 677 | ## 2.0.6 - 2017-12-11 678 | 679 | ### Added 680 | 681 | - Nothing. 682 | 683 | ### Changed 684 | 685 | - Nothing. 686 | 687 | ### Deprecated 688 | 689 | - Nothing. 690 | 691 | ### Removed 692 | 693 | - Nothing. 694 | 695 | ### Fixed 696 | 697 | - [#534](https://github.com/zendframework/zend-expressive/pull/534) provides a 698 | fix for how it detects `callable` middleware. Previously, it relied on PHP's 699 | `is_callable()`, but that function can result in false positives when provided 700 | a 2-element array where the first element is an object, as the function does 701 | not verify that the second argument is a valid method of the first. We now 702 | implement additional verifications to prevent such false positives. 703 | 704 | ## 2.0.5 - 2017-10-09 705 | 706 | ### Added 707 | 708 | - Nothing. 709 | 710 | ### Changed 711 | 712 | - Nothing. 713 | 714 | ### Deprecated 715 | 716 | - Nothing. 717 | 718 | ### Removed 719 | 720 | - Nothing. 721 | 722 | ### Fixed 723 | 724 | - [#521](https://github.com/zendframework/zend-expressive/pull/521) adds an 725 | explicit requirement on http-interop/http-middleware `^0.4.1` to the package. 726 | This is necessary as newer builds of zend-stratigility instead depend on the 727 | metapackage webimpress/http-middleware-compatibility instead of the 728 | http-interop/http-middleware package — but middleware shipped in Expressive 729 | requires it. This addition fixes problems due to missing http-middleware 730 | interfaces. 731 | 732 | ## 2.0.4 - 2017-10-09 733 | 734 | ### Added 735 | 736 | - [#508](https://github.com/zendframework/zend-expressive/pull/508) adds 737 | documentation covering `Zend\Expressive\Helper\ContentLengthMiddleware`, 738 | introduced in zend-expressive-helpers 4.1.0. 739 | 740 | ### Deprecated 741 | 742 | - Nothing. 743 | 744 | ### Removed 745 | 746 | - Nothing. 747 | 748 | ### Fixed 749 | 750 | - [#479](https://github.com/zendframework/zend-expressive/pull/479) fixes the 751 | `WhoopsErrorResponseGenerator::$whoops` dockblock Type to support Whoops 1 752 | and 2. 753 | - [#482](https://github.com/zendframework/zend-expressive/pull/482) fixes the 754 | `Application::$defaultDelegate` dockblock Type. 755 | - [#489](https://github.com/zendframework/zend-expressive/pull/489) fixes an 756 | edge case in the `WhoopsErrorHandler` whereby it would emit an error if 757 | `$_SERVER['SCRIPT_NAME']` did not exist. It now checks for that value before 758 | attempting to use it. 759 | 760 | ## 2.0.3 - 2017-03-28 761 | 762 | ### Added 763 | 764 | - Nothing. 765 | 766 | ### Changed 767 | 768 | - [#468](https://github.com/zendframework/zend-expressive/pull/468) updates 769 | references to `DefaultDelegate::class` to instead use the string 770 | `'Zend\Expressive\Delegate\DefaultDelegate'`; using the string makes it clear 771 | that the service name does not resolve to an actual class. 772 | 773 | ### Deprecated 774 | 775 | - Nothing. 776 | 777 | ### Removed 778 | 779 | - Nothing. 780 | 781 | ### Fixed 782 | 783 | - [#476](https://github.com/zendframework/zend-expressive/pull/476) fixes the 784 | `WhoopsErrorResponseGenerator` to ensure it returns a proper error status 785 | code, instead of using a `200 OK` status. 786 | 787 | ## 2.0.2 - 2017-03-13 788 | 789 | ### Added 790 | 791 | - Nothing. 792 | 793 | ### Deprecated 794 | 795 | - Nothing. 796 | 797 | ### Removed 798 | 799 | - Nothing. 800 | 801 | ### Fixed 802 | 803 | - [#467](https://github.com/zendframework/zend-expressive/pull/467) fixes an 804 | issue when passing invokable, duck-typed, interop middleware to the 805 | application without registering it with the container. Prior to the patch, it 806 | was incorrectly being decorated by 807 | `Zend\Stratigility\Middleware\CallableMiddlewareWrapper` instead of 808 | `Zend\Stratigility\Middleware\CallableInteropMiddlewareWrapper`. 809 | 810 | ## 2.0.1 - 2017-03-09 811 | 812 | ### Added 813 | 814 | - Nothing. 815 | 816 | ### Deprecated 817 | 818 | - Nothing. 819 | 820 | ### Removed 821 | 822 | - Nothing. 823 | 824 | ### Fixed 825 | 826 | - [#464](https://github.com/zendframework/zend-expressive/pull/464) fixes the 827 | `WhoopsErrorResponseGenerator` to provide a correct `Content-Type` header to 828 | the response when a JSON request occurs. 829 | 830 | ## 2.0.0 - 2017-03-07 831 | 832 | ### Added 833 | 834 | - [#450](https://github.com/zendframework/zend-expressive/pull/450) adds support 835 | for [PSR-11](http://www.php-fig.org/psr/psr-11/); Expressive is now a PSR-11 836 | consumer. 837 | 838 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) updates the 839 | zend-stratigility dependency to require `^2.0`; this allows usage of both 840 | the new middleare-based error handling system introduced in zend-stratigility 841 | 1.3, as well as usage of [http-interop/http-middleware](https://github.com/http-interop/http-middleware) 842 | implementations with Expressive. The following middleware is now supported: 843 | - Implementations of `Interop\Http\ServerMiddleware\MiddlewareInterface`. 844 | - Callable middleware that implements the same signature as 845 | `Interop\Http\ServerMiddleware\MiddlewareInterface`. 846 | - Callable middleware using the legacy double-pass signature 847 | (`function ($request, $response, callable $next)`); these are now decorated 848 | in `Zend\Stratigility\Middleware\CallableMiddlewareWrapper` instances. 849 | - Service names resolving to any of the above. 850 | - Arrays of any of the above; these will be cast to 851 | `Zend\Stratigility\MiddlewarePipe` instances, piping each middleware. 852 | 853 | - [#396](https://github.com/zendframework/zend-expressive/pull/396) adds 854 | `Zend\Expressive\Middleware\NotFoundHandler`, which provides a way to return a 855 | templated 404 response to users. This middleware should be used as innermost 856 | middleware. You may use the new `Zend\Expressive\Container\NotFoundHandlerFactory` 857 | to generate the instance via your DI container. 858 | 859 | - [#396](https://github.com/zendframework/zend-expressive/pull/396) adds 860 | `Zend\Expressive\Container\ErrorHandlerFactory`, for generating a 861 | `Zend\Stratigility\Middleware\ErrorHandler` to use with your application. 862 | If a `Zend\Expressive\Middleware\ErrorResponseGenerator` service is present in 863 | the container, it will be used to seed the `ErrorHandler` with a response 864 | generator. If you use this facility, you should enable the 865 | `zend-expressive.raise_throwables` configuration flag. 866 | 867 | - [#396](https://github.com/zendframework/zend-expressive/pull/396) adds 868 | `Zend\Expressive\Middleware\ErrorResponseGenerator` and 869 | `Zend\Expressive\Middleware\WhoopsErrorResponseGenerator`, which may be used 870 | with `Zend\Stratigility\Middleware\ErrorHandler` to generate error responses. 871 | The first will generate templated error responses if a template renderer is 872 | composed, and the latter will generate Whoops output. 873 | You may use the new `Zend\Expressive\Container\ErrorResponseGeneratorFactory` 874 | and `Zend\Expressive\Container\WhoopsErrorResponseGeneratorFactory`, 875 | respectively, to create these instances; if you do, assign these to the 876 | service name `Zend\Expressive\Middleware\ErrorResponseGenerator` to have them 877 | automatically registered with the `ErrorHandler`. 878 | 879 | - [#396](https://github.com/zendframework/zend-expressive/pull/396) adds 880 | `Zend\Expressive\ApplicationConfigInjectionTrait`, which exposes two methods, 881 | `injectRoutesFromConfig()` and `injectPipelineFromConfig()`; this trait is now 882 | composed into the `Application` class. These methods allow you to configure an 883 | `Application` instance from configuration if desired, and are now used by the 884 | `ApplicationFactory` to configure the `Application` instance. 885 | 886 | - [#396](https://github.com/zendframework/zend-expressive/pull/396) adds 887 | a vendor binary, `vendor/bin/expressive-tooling`, which will install (or 888 | uninstall) the [zend-expressive-tooling](https://github.com/zendframework/zend-expressive-tooling); 889 | this package provides migration tools for updating your application to use 890 | programmatic pipelines and the new error handling strategy, as well as tools 891 | for identifying usage of the legacy Stratigility request and response 892 | decorators and error middleware. 893 | 894 | - [#413](https://github.com/zendframework/zend-expressive/pull/413) adds the 895 | middleware `Zend\Expressive\Middleware\ImplicitHeadMiddleware`; this 896 | middleware can be used to provide implicit support for `HEAD` requests when 897 | the matched route does not explicitly support the method. 898 | 899 | - [#413](https://github.com/zendframework/zend-expressive/pull/413) adds the 900 | middleware `Zend\Expressive\Middleware\ImplicitOptionsMiddleware`; this 901 | middleware can be used to provide implicit support for `OPTIONS` requests when 902 | the matched route does not explicitly support the method; the returned 200 903 | response will also include an `Allow` header listing allowed HTTP methods for 904 | the URI. 905 | 906 | - [#426](https://github.com/zendframework/zend-expressive/pull/426) adds the 907 | method `Application::getRoutes()`, which will return the list of 908 | `Zend\Expressive\Router\Route` instances currently registered with the 909 | application. 910 | 911 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) adds the 912 | class `Zend\Expressive\Delegate\NotFoundDelegate`, an 913 | `Interop\Http\ServerMiddleware\DelegateInterface` implementation. The class 914 | will return a 404 response; if a `TemplateRendererInterface` is available and 915 | injected into the delegate, it will provide templated contents for the 404 916 | response as well. We also provide `Zend\Expressive\Container\NotFoundDelegateFactory` 917 | for providing an instance. 918 | 919 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) adds the 920 | method `Zend\Expressive\Application::getDefaultDelegate()`. This method will 921 | return the default `Interop\Http\ServerMiddleware\DelegateInterface` injected 922 | during instantiation, or, if none was injected, lazy load an instance of 923 | `Zend\Expressive\Delegate\NotFoundDelegate`. 924 | 925 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) adds the 926 | constants `DISPATCH_MIDDLEWARE` and `ROUTING_MIDDLEWARE` to 927 | `Zend\Expressive\Application`; they have identical values to the constants 928 | previously defined in `Zend\Expressive\Container\ApplicationFactory`. 929 | 930 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) adds 931 | `Zend\Expressive\Middleware\LazyLoadingMiddleware`; this essentially extracts 932 | the logic previously used within `Zend\Expressive\Application` to provide 933 | container-based middleware to allow lazy-loading only when dispatched. 934 | 935 | ### Changes 936 | 937 | - [#440](https://github.com/zendframework/zend-expressive/pull/440) changes the 938 | `Zend\Expressive\Application::__call($method, array $args)` signature; in 939 | previous versions, `$args` did not have a typehint. If you are extending the 940 | class and overriding this method, you will need to update your signature 941 | accordingly. 942 | 943 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) updates 944 | `Zend\Expressive\Container\ApplicationFactory` to ignore the 945 | `zend-expressive.raise_throwables` configuration setting; Stratigility 2.X no 946 | longer catches exceptions in its middleware dispatcher, making the setting 947 | irrelevant. 948 | 949 | - [#422](https://github.com/zendframework/zend-expressive/pull/422) updates the 950 | zend-expressive-router minimum supported version to 2.0.0. 951 | 952 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) modifies the 953 | `Zend\Expressive\Container\ApplicationFactory` constants `DISPATCH_MIDDLEWARE` 954 | and `ROUTING_MIDDLEWARE` to define themselves based on the constants of the 955 | same name now defined in `Zend\Expressive\Application`. 956 | 957 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) modifies the 958 | constructor of `Zend\Expressive\Application`; the third argument was 959 | previously a nullable callable `$finalHandler`; it is now a nullable 960 | `Interop\Http\ServerMiddleware\DelegateInterface` with the name 961 | `$defaultDelegate`. 962 | 963 | - [#450](https://github.com/zendframework/zend-expressive/pull/450) modifies the 964 | signatures in several classes to typehint against [PSR-11](http://www.php-fig.org/psr/psr-11/) 965 | instead of [container-interop](https://github.com/container-interop/container-interop); 966 | these include: 967 | 968 | - `Zend\Expressive\AppFactory::create()` 969 | - `Zend\Expressive\Application::__construct()` 970 | - `Zend\Expressive\Container\ApplicationFactory::__invoke()` 971 | - `Zend\Expressive\Container\ErrorHandlerFactory::__invoke()` 972 | - `Zend\Expressive\Container\ErrorResponseGeneratorFactory::__invoke()` 973 | - `Zend\Expressive\Container\NotFoundDelegateFactory::__invoke()` 974 | - `Zend\Expressive\Container\NotFoundHandlerFactory::__invoke()` 975 | - `Zend\Expressive\Container\WhoopsErrorResponseGeneratorFactory::__invoke()` 976 | - `Zend\Expressive\Container\WhoopsFactory::__invoke()` 977 | - `Zend\Expressive\Container\WhoopsPageHandlerFactory::__invoke()` 978 | 979 | - [#450](https://github.com/zendframework/zend-expressive/pull/450) changes the 980 | interface inheritance of `Zend\Expressive\Container\Exception\InvalidServiceException` 981 | to extend `Psr\Container\ContainerExceptionInterface` instead of 982 | `Interop\Container\Exception\ContainerException`. 983 | 984 | ### Deprecated 985 | 986 | - Nothing. 987 | 988 | ### Removed 989 | 990 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) removes the 991 | following routing/dispatch methods from `Zend\Expressive\Application`: 992 | - `routeMiddleware()`; this is now encapsulated in `Zend\Expressive\Middleware\RouteMiddleware`. 993 | - `dispatchMiddleware()`; this is now encapsulated in `Zend\Expressive\Middleware\DispatchMiddleware`. 994 | 995 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) removes the 996 | various "final handler" implementations and related factories. Users should 997 | now use the "default delegates" as detailed in sections previous. Classes 998 | and methods removed include: 999 | - `Zend\Expressive\Application::getFinalHandler()` 1000 | - `Zend\Expressive\TemplatedErrorHandler` 1001 | - `Zend\Expressive\WhoopsErrorHandler` 1002 | - `Zend\Expressive\Container\TemplatedErrorHandlerFactory` 1003 | - `Zend\Expressive\Container\WhoopsErrorHandlerFactory` 1004 | 1005 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) removes the 1006 | `Zend\Expressive\ErrorMiddlewarePipe` class, as zend-stratigility 2.X no 1007 | longer defines `Zend\Stratigility\ErrorMiddlewareInterface` or has a concept 1008 | of variant-signature error middleware. Use standard middleware to provide 1009 | error handling now. 1010 | 1011 | - [#428](https://github.com/zendframework/zend-expressive/pull/428) removes the 1012 | exception types `Zend\Expressive\Container\Exception\InvalidArgumentException` 1013 | (use `Zend\Expressive\Exception\InvalidArgumentException` instead) and 1014 | `Zend\Expressive\Container\Exception\NotFoundException` (which was never used 1015 | internally). 1016 | 1017 | ### Fixed 1018 | 1019 | - Nothing. 1020 | 1021 | ## 1.1.1 - 2017-02-14 1022 | 1023 | ### Added 1024 | 1025 | - Nothing. 1026 | 1027 | ### Deprecated 1028 | 1029 | - Nothing. 1030 | 1031 | ### Removed 1032 | 1033 | - Nothing. 1034 | 1035 | ### Fixed 1036 | 1037 | - [#447](https://github.com/zendframework/zend-expressive/pull/447) fixes an 1038 | error in the `ApplicationFactory` that occurs when the `config` service is an 1039 | `ArrayObject`. Prior to the fix, `ArrayObject` configurations would cause a 1040 | fatal error when injecting the pipeline and/or routes. 1041 | 1042 | ## 1.1.0 - 2017-02-13 1043 | 1044 | ### Added 1045 | 1046 | - [#309](https://github.com/zendframework/zend-expressive/pull/309) adds the 1047 | ability to provide options with which to instantiate the `FinalHandler` 1048 | instance, via the configuration: 1049 | 1050 | ```php 1051 | [ 1052 | 'final_handler' => [ 1053 | 'options' => [ /* array of options */ ], 1054 | ], 1055 | ``` 1056 | 1057 | - [#373](https://github.com/zendframework/zend-expressive/pull/373) adds interception 1058 | of exceptions from the `ServerRequestFactory` for invalid request information in order 1059 | to return `400` responses. 1060 | 1061 | - [#432](https://github.com/zendframework/zend-expressive/pull/432) adds two new 1062 | configuration flags for use with `Zend\Expressive\Container\ApplicationFactory`: 1063 | - `zend-expressive.programmatic_pipelines`: when enabled, the factory will 1064 | ignore the `middleware_pipeline` and `routes` configuration, allowing you to 1065 | wire these programmatically instead. We recommend creating these in the 1066 | files `config/pipeline.php` and `config/routes.php`, respectively, and 1067 | modifying your `public/index.php` to `require` these files in statements 1068 | immediately preceding the call to `$app->run()`. 1069 | - `zend-expressive.raise_throwables`: when enabled, this will be used to 1070 | notify zend-stratigility's internal dispatcher to no longer catch 1071 | exceptions/throwables, and instead allow them to bubble out. This allows you 1072 | to write custom middleware for handling errors. 1073 | 1074 | - [#429](https://github.com/zendframework/zend-expressive/pull/429) adds 1075 | `Zend\Expressive\Application::getDefaultDelegate()` as a 1076 | forwards-compatibility measure for the upcoming version 2.0.0. Currently, 1077 | it proxies to `getFinalHandler()`. 1078 | 1079 | - [#435](https://github.com/zendframework/zend-expressive/pull/435) adds support 1080 | for the 2.X versions of zend-expressive-router and the various router 1081 | implementations. This change also allows usage of zend-expressive-helpers 3.X. 1082 | 1083 | ### Changed 1084 | 1085 | - [#429](https://github.com/zendframework/zend-expressive/pull/429) updates the 1086 | minimum supported zend-stratigility version to 1.3.3. 1087 | 1088 | - [#396](https://github.com/zendframework/zend-expressive/pull/396) updates the 1089 | `Zend\Expressive\Container\ApplicationFactory` to vary creation of the 1090 | `Application` instance based on two new configuration variables: 1091 | 1092 | - `zend-expressive.programmatic_pipeline` will cause the factory to skip 1093 | injection of the middleware pipeline and routes from configuration. It is 1094 | then up to the developer to do so, or use the `Application` API to pipe 1095 | middleware and/or add routed middleware. 1096 | 1097 | - `zend-expressive.raise_throwables` will cause the factory to call the new 1098 | `raiseThrowables()` method exposed by `Application` (and inherited from 1099 | `Zend\Stratigility\MiddlewarePipe`). Doing so will cause the application to 1100 | raise any `Throwable` or `Exception` instances caught, instead of catching 1101 | them and dispatching them to (legacy) Stratigility error middleware. 1102 | 1103 | ### Deprecated 1104 | 1105 | - [#429](https://github.com/zendframework/zend-expressive/pull/429) deprecates 1106 | the following methods and classes: 1107 | - `Zend\Expressive\Application::pipeErrorHandler()`; use the 1108 | `raise_throwables` flag and standard middleware to handle errors instead. 1109 | - `Zend\Expressive\Application::routeMiddleware()`; this is extracted to a 1110 | dedicated middleware class for 2.0. 1111 | - `Zend\Expressive\Application::dispatchMiddleware()`; this is extracted to a 1112 | dedicated middleware class for 2.0. 1113 | - `Zend\Expressive\Application::getFinalHandler()` (this patch provides `getDefaultDelegate()` as a forwards-compatibility measure) 1114 | - `Zend\Expressive\Container\Exception\InvalidArgumentException`; this will be removed 1115 | in 2.0.0, and places where it was used will instead throw 1116 | `Zend\Expressive\Exception\InvalidArgumentException`. 1117 | - `Zend\Expressive\Container\Exception\NotFoundException`; this exception is 1118 | never thrown at this point. 1119 | - `Zend\Expressive\Container\TemplatedErrorHandlerFactory` 1120 | - `Zend\Expressive\Container\WhoopsErrorHandlerFactory` 1121 | - `Zend\Expressive\ErrorMiddlewarePipe`; Stratigility 1.3 deprecates its 1122 | `Zend\Stratigility\ErrorMiddlewareInterface`, and removes it in version 2.0. 1123 | use the `raise_throwables` flag and standard middleware to handle errors 1124 | instead. 1125 | - `Zend\Expressive\TemplatedErrorHandler`; the "final handler" concept is 1126 | retired in Expressive 2.0, and replaced with default delegates (classes 1127 | implementing `Interop\Http\ServerMiddleware\DelegateInterface` that will be 1128 | executed when the internal pipeline is exhausted, in order to guarantee a 1129 | response). If you are using custom final handlers, you will need to rewrite 1130 | them when adopting Expressive 2.0. 1131 | - `Zend\Expressive\WhoopsErrorHandler` 1132 | 1133 | ### Removed 1134 | 1135 | - [#406](https://github.com/zendframework/zend-expressive/pull/406) removes the 1136 | `RouteResultSubjectInterface` implementation from `Zend\Expressive\Application`, 1137 | per the deprecation prior to the 1.0 stable release. 1138 | 1139 | ### Fixed 1140 | 1141 | - [#442](https://github.com/zendframework/zend-expressive/pull/442) fixes how 1142 | the `WhoopsFactory` disables JSON output for whoops; previously, providing 1143 | boolean `false` values for either of the configuration flags 1144 | `json_exceptions.show_trace` or `json_exceptions.ajax_only` would result in 1145 | enabling the settings; these flags are now correctly evaluated by the 1146 | `WhoopsFactory`. 1147 | 1148 | ## 1.0.6 - 2017-01-09 1149 | 1150 | ### Added 1151 | 1152 | - Nothing. 1153 | 1154 | ### Deprecated 1155 | 1156 | - Nothing. 1157 | 1158 | ### Removed 1159 | 1160 | - Nothing. 1161 | 1162 | ### Fixed 1163 | 1164 | - [#420](https://github.com/zendframework/zend-expressive/pull/420) fixes the 1165 | `routeMiddleware()`'s handling of 405 errors such that it now no longer emits 1166 | deprecation notices when running under the Stratigility 1.3 series. 1167 | 1168 | ## 1.0.5 - 2016-12-08 1169 | 1170 | ### Added 1171 | 1172 | - Nothing. 1173 | 1174 | ### Deprecated 1175 | 1176 | - Nothing. 1177 | 1178 | ### Removed 1179 | 1180 | - Nothing. 1181 | 1182 | ### Fixed 1183 | 1184 | - [#403](https://github.com/zendframework/zend-expressive/pull/403) updates the 1185 | `AppFactory::create()` logic to raise exceptions in either of the following 1186 | scenarios: 1187 | - no container is specified, and the class `Zend\ServiceManager\ServiceManager` 1188 | is not available. 1189 | - no router is specified, and the class `Zend\Expressive\Router\FastRouteRouter` 1190 | is not available. 1191 | - [#405](https://github.com/zendframework/zend-expressive/pull/405) fixes how 1192 | the `TemplatedErrorHandler` injects templated content into the response. 1193 | Previously, it would `write()` directly to the existing response body, which 1194 | could lead to issues if previous middleware had written to the response (as 1195 | the templated contents would append the previous contents). With this release, 1196 | it now creates a new `Zend\Diactoros\Stream`, writes to that, and returns a 1197 | new response with that new stream, guaranteeing it only contains the new 1198 | contents. 1199 | - [#404](https://github.com/zendframework/zend-expressive/pull/404) fixes the 1200 | `swallowDeprecationNotices()` handler such that it will not swallow a global 1201 | handler once application execution completes. 1202 | 1203 | ## 1.0.4 - 2016-12-07 1204 | 1205 | ### Added 1206 | 1207 | - Nothing. 1208 | 1209 | ### Deprecated 1210 | 1211 | - Nothing. 1212 | 1213 | ### Removed 1214 | 1215 | - Nothing. 1216 | 1217 | ### Fixed 1218 | 1219 | - [#402](https://github.com/zendframework/zend-expressive/pull/402) fixes how 1220 | `Application::__invoke()` registers the error handler designed to swallow 1221 | deprecation notices, as introduced in 1.0.3. It now checks to see if another 1222 | error handler was previously registered, and, if so, creates a composite 1223 | handler that will delegate to the previous for all other errors. 1224 | 1225 | ## 1.0.3 - 2016-11-11 1226 | 1227 | ### Added 1228 | 1229 | - Nothing. 1230 | 1231 | ### Changes 1232 | 1233 | - [#395](https://github.com/zendframework/zend-expressive/pull/395) updates 1234 | `Application::__invoke()` to add an error handler to swallow deprecation 1235 | notices due to triggering error middleware when using Stratigility 1.3+. Since 1236 | error middleware is triggered whenever the `raiseThrowables` flag is not 1237 | enabled and an error or empty queue situation is encountered, handling it this 1238 | way prevents any such errors from bubbling out of the application. 1239 | 1240 | ### Deprecated 1241 | 1242 | - Nothing. 1243 | 1244 | ### Removed 1245 | 1246 | - Nothing. 1247 | 1248 | ### Fixed 1249 | 1250 | - Nothing. 1251 | 1252 | ## 1.0.2 - 2016-11-11 1253 | 1254 | ### Added 1255 | 1256 | - Nothing. 1257 | 1258 | ### Changes 1259 | 1260 | - [#393](https://github.com/zendframework/zend-expressive/pull/393) updates 1261 | `Application::run()` to inject the request with an `originalResponse` 1262 | attribute using the provided response as the value. 1263 | 1264 | ### Deprecated 1265 | 1266 | - Nothing. 1267 | 1268 | ### Removed 1269 | 1270 | - Nothing. 1271 | 1272 | ### Fixed 1273 | 1274 | - [#393](https://github.com/zendframework/zend-expressive/pull/393) fixes how 1275 | each of the `TemplatedErrorHandler` and `WhoopsErrorHandler` access the 1276 | "original" request, URI, and/or response. Previously, these used 1277 | Stratigility-specific methods; they now use request attributes, eliminating 1278 | deprecation notices emitted in Stratigility 1.3+ versions. 1279 | 1280 | ## 1.0.1 - 2016-11-11 1281 | 1282 | ### Added 1283 | 1284 | - [#306](https://github.com/zendframework/zend-expressive/pull/306) adds a 1285 | cookbook recipe covering flash messages. 1286 | - [#384](https://github.com/zendframework/zend-expressive/pull/384) adds support 1287 | for Whoops version 2 releases, providing PHP 7 support for Whoops. 1288 | 1289 | ### Deprecated 1290 | 1291 | - Nothing. 1292 | 1293 | ### Removed 1294 | 1295 | - Nothing. 1296 | 1297 | ### Fixed 1298 | 1299 | - [#391](https://github.com/zendframework/zend-expressive/pull/391) fixes the 1300 | `Application::run()` implementation to prevent emission of deprecation notices 1301 | when used with Stratigility 1.3. 1302 | 1303 | ## 1.0.0 - 2016-01-28 1304 | 1305 | Initial stable release. 1306 | 1307 | ### Added 1308 | 1309 | - [#279](https://github.com/zendframework/zend-expressive/pull/279) updates 1310 | the documentation to provide automation for pushing to GitHub pages. As part 1311 | of that work, documentation was re-organized, and a landing page provided. 1312 | Documentation can now be found at: https://zendframework.github.io/zend-expressive/ 1313 | - [#299](https://github.com/zendframework/zend-expressive/pull/299) adds 1314 | component-specific CSS to the documentation. 1315 | - [#295](https://github.com/zendframework/zend-expressive/pull/295) adds 1316 | support for handling PHP 7 engine exceptions in the templated and whoops final 1317 | handlers. 1318 | 1319 | ### Deprecated 1320 | 1321 | - Nothing. 1322 | 1323 | ### Removed 1324 | 1325 | - Nothing. 1326 | 1327 | ### Fixed 1328 | 1329 | - [#280](https://github.com/zendframework/zend-expressive/pull/280) fixes 1330 | references to the `PlatesRenderer` in the error handling documentation. 1331 | - [#284](https://github.com/zendframework/zend-expressive/pull/284) fixes 1332 | the reference to maximebf/php-debugbar in the debug bar documentation. 1333 | - [#285](https://github.com/zendframework/zend-expressive/pull/285) updates 1334 | the section on mtymek/blast-base-url in the "Using a Base Path" cookbook 1335 | recipe to conform to its latest release. 1336 | - [#286](https://github.com/zendframework/zend-expressive/pull/286) fixes the 1337 | documentation of the Composer "serve" command to correct a typo. 1338 | - [#291](https://github.com/zendframework/zend-expressive/pull/291) fixes the 1339 | documentation links to the RC5 -> v1 migration guide in both the CHANGELOG as 1340 | well as the error messages emitted, ensuring users can locate the correct 1341 | documentation in order to upgrade. 1342 | - [#287](https://github.com/zendframework/zend-expressive/pull/287) updates the 1343 | "standalone" quick start to reference calling `$app->pipeRoutingMiddleware()` 1344 | and `$app->pipeDispatchMiddleware()` per the changes in RC6. 1345 | - [#293](https://github.com/zendframework/zend-expressive/pull/293) adds 1346 | a `require 'vendor/autoload.php';` line to the bootstrap script referenced in 1347 | the zend-servicemanager examples. 1348 | - [#294](https://github.com/zendframework/zend-expressive/pull/294) updates the 1349 | namespace referenced in the modulear-layout documentation to provide a better 1350 | separation between the module/package/whatever, and the application consuming 1351 | it. 1352 | - [#298](https://github.com/zendframework/zend-expressive/pull/298) fixes a typo 1353 | in a URI generation example. 1354 | 1355 | ## 1.0.0rc7 - 2016-01-21 1356 | 1357 | Seventh release candidate. 1358 | 1359 | ### Added 1360 | 1361 | - [#277](https://github.com/zendframework/zend-expressive/pull/277) adds a new 1362 | class, `Zend\Expressive\ErrorMiddlewarePipe`. It composes a 1363 | `Zend\Stratigility\MiddlewarePipe`, but implements the error middleware 1364 | signature via its own `__invoke()` method. 1365 | 1366 | ### Deprecated 1367 | 1368 | - Nothing. 1369 | 1370 | ### Removed 1371 | 1372 | - Nothing. 1373 | 1374 | ### Fixed 1375 | 1376 | - [#277](https://github.com/zendframework/zend-expressive/pull/277) updates the 1377 | `MarshalMiddlewareTrait` to create and return an `ErrorMiddlewarePipe` when 1378 | the `$forError` argument provided indicates error middleware is expected. 1379 | This fix allows defining arrays of error middleware via configuration. 1380 | 1381 | ## 1.0.0rc6 - 2016-01-18 1382 | 1383 | Sixth release candidate. 1384 | 1385 | This release contains backwards compatibility breaks with previous release 1386 | candidates. All previous functionality should continue to work, but will 1387 | emit `E_USER_DEPRECATED` notices prompting you to update your application. 1388 | In particular: 1389 | 1390 | - The routing middleware has been split into two separate middleware 1391 | implementations, one for routing, another for dispatching. This eliminates the 1392 | need for the route result observer system, as middleware can now be placed 1393 | *between* routing and dispatching — an approach that provides for greater 1394 | flexibility with regards to providing route-based functionality. 1395 | - As a result of the above, `Zend\Expressive\Application` no longer implements 1396 | `Zend\Expressive\Router\RouteResultSubjectInterface`, though it retains the 1397 | methods associated (each emits a deprecation notice). 1398 | - Configuration for `Zend\Expressive\Container\ApplicationFactory` was modified 1399 | to implement the `middleware_pipeline` as a single queue, instead of 1400 | segregating it between `pre_routing` and `post_routing`. Each item in the 1401 | queue follows the original middleware specification from those keys, with one 1402 | addition: a `priority` key can be used to allow you to granularly shape the 1403 | execution order of the middleware pipeline. 1404 | 1405 | A [migration guide](https://zendframework.github.io/zend-expressive/reference/migration/rc-to-v1/) 1406 | was written to help developers migrate to RC6 from earlier versions. 1407 | 1408 | ### Added 1409 | 1410 | - [#255](https://github.com/zendframework/zend-expressive/pull/255) adds 1411 | documentation for the base path functionality provided by the `UrlHelper` 1412 | class of zend-expressive-helpers. 1413 | - [#227](https://github.com/zendframework/zend-expressive/pull/227) adds 1414 | a section on creating localized routes, and setting the application locale 1415 | based on the matched route. 1416 | - [#244](https://github.com/zendframework/zend-expressive/pull/244) adds 1417 | a recipe on using middleware to detect localized URIs (vs using a routing 1418 | parameter), setting the application locale based on the match detected, 1419 | and setting the `UrlHelper` base path with the same match. 1420 | - [#260](https://github.com/zendframework/zend-expressive/pull/260) adds 1421 | a recipe on how to add debug toolbars to your Expressive applications. 1422 | - [#261](https://github.com/zendframework/zend-expressive/pull/261) adds 1423 | a flow/architectural diagram to the "features" chapter. 1424 | - [#262](https://github.com/zendframework/zend-expressive/pull/262) adds 1425 | a recipe demonstrating creating classes that can intercept multiple routes. 1426 | - [#270](https://github.com/zendframework/zend-expressive/pull/270) adds 1427 | new methods to `Zend\Expressive\Application`: 1428 | - `dispatchMiddleware()` is new middleware for dispatching the middleware 1429 | matched by routing (this functionality was split from `routeMiddleware()`). 1430 | - `routeResultObserverMiddleware()` is new middleware for notifying route 1431 | result observers, and exists only to aid migration functionality; it is 1432 | marked deprecated! 1433 | - `pipeDispatchMiddleware()` will pipe the dispatch middleware to the 1434 | `Application` instance. 1435 | - `pipeRouteResultObserverMiddleware()` will pipe the route result observer 1436 | middleware to the `Application` instance; like 1437 | `routeResultObserverMiddleware()`, the method only exists for aiding 1438 | migration, and is marked deprecated. 1439 | - [#270](https://github.com/zendframework/zend-expressive/pull/270) adds 1440 | `Zend\Expressive\MarshalMiddlewareTrait`, which is composed by 1441 | `Zend\Expressive\Application`; it provides methods for marshaling 1442 | middleware based on service names or arrays of services. 1443 | 1444 | ### Deprecated 1445 | 1446 | - [#270](https://github.com/zendframework/zend-expressive/pull/270) deprecates 1447 | the following methods in `Zend\Expressive\Application`, all of which will 1448 | be removed in version 1.1: 1449 | - `attachRouteResultObserver()` 1450 | - `detachRouteResultObserver()` 1451 | - `notifyRouteResultObservers()` 1452 | - `pipeRouteResultObserverMiddleware()` 1453 | - `routeResultObserverMiddleware()` 1454 | 1455 | ### Removed 1456 | 1457 | - [#270](https://github.com/zendframework/zend-expressive/pull/270) removes the 1458 | `Zend\Expressive\Router\RouteResultSubjectInterface` implementation from 1459 | `Zend\Expressive\Application`. 1460 | - [#270](https://github.com/zendframework/zend-expressive/pull/270) eliminates 1461 | the `pre_routing`/`post_routing` terminology from the `middleware_pipeline`, 1462 | in favor of individually specified `priority` values in middleware 1463 | specifications. 1464 | 1465 | ### Fixed 1466 | 1467 | - [#263](https://github.com/zendframework/zend-expressive/pull/263) typo 1468 | fixes in documentation 1469 | 1470 | ## 1.0.0rc5 - 2015-12-22 1471 | 1472 | Fifth release candidate. 1473 | 1474 | ### Added 1475 | 1476 | - [#233](https://github.com/zendframework/zend-expressive/pull/233) adds a 1477 | documentation page detailing projects using and tutorials written on 1478 | Expressive. 1479 | - [#238](https://github.com/zendframework/zend-expressive/pull/238) adds a 1480 | cookbook recipe detailing how to handle serving an Expressive application from 1481 | a subdirectory of your web root. 1482 | - [#239](https://github.com/zendframework/zend-expressive/pull/239) adds a 1483 | cookbook recipe detailing how to create modular Expressive applications. 1484 | - [#243](https://github.com/zendframework/zend-expressive/pull/243) adds a 1485 | chapter to the helpers section detailing the new `BodyParseMiddleware`. 1486 | 1487 | ### Deprecated 1488 | 1489 | - Nothing. 1490 | 1491 | ### Removed 1492 | 1493 | - Nothing. 1494 | 1495 | ### Fixed 1496 | 1497 | - [#234](https://github.com/zendframework/zend-expressive/pull/234) fixes the 1498 | inheritance tree for `Zend\Expressive\Exception\RuntimeException` to inherit 1499 | from `RuntimeException` and not `InvalidArgumentException`. 1500 | - [#237](https://github.com/zendframework/zend-expressive/pull/237) updates the 1501 | Pimple documentation to recommend `xtreamwayz/pimple-container-interop` 1502 | instead of `mouf/pimple-interop`, as the latter consumed Pimple v1, instead of 1503 | the current stable v3. 1504 | 1505 | ## 1.0.0rc4 - 2015-12-09 1506 | 1507 | Fourth release candidate. 1508 | 1509 | ### Added 1510 | 1511 | - [#217](https://github.com/zendframework/zend-expressive/pull/217) adds a 1512 | cookbook entry to the documentation detailing how to configure zend-view 1513 | helpers from other components, as well as how to add custom view helpers. 1514 | 1515 | ### Deprecated 1516 | 1517 | - Nothing. 1518 | 1519 | ### Removed 1520 | 1521 | - Nothing. 1522 | 1523 | ### Fixed 1524 | 1525 | - [#219](https://github.com/zendframework/zend-expressive/pull/219) updates the 1526 | "Hello World Using a Configuration-Driven Container" usage case to use 1527 | zend-stdlib's `Glob::glob()` instead of the `glob()` native function, to 1528 | ensure the documented solution is portable across platforms. 1529 | - [#223](https://github.com/zendframework/zend-expressive/pull/223) updates the 1530 | documentation to refer to the `composer serve` command where relevant, and 1531 | also details how to create the command for standalone users. 1532 | - [#221](https://github.com/zendframework/zend-expressive/pull/221) splits the 1533 | various cookbook entries into separate files, so each is self-contained. 1534 | - [#224](https://github.com/zendframework/zend-expressive/pull/224) adds opening 1535 | ` 1.0-dev, dev-develop => 1.1-dev. 1620 | - Point dev dependencies on sub-components to `~1.0-dev`. 1621 | 1622 | ## 1.0.0rc1 - 2015-10-19 1623 | 1624 | First release candidate. 1625 | 1626 | ### Added 1627 | 1628 | - Nothing. 1629 | 1630 | ### Deprecated 1631 | 1632 | - Nothing. 1633 | 1634 | ### Removed 1635 | 1636 | - Nothing. 1637 | 1638 | ### Fixed 1639 | 1640 | - Nothing. 1641 | 1642 | ## 0.5.3 - 2015-10-19 1643 | 1644 | ### Added 1645 | 1646 | - Nothing. 1647 | 1648 | ### Deprecated 1649 | 1650 | - Nothing. 1651 | 1652 | ### Removed 1653 | 1654 | - Nothing. 1655 | 1656 | ### Fixed 1657 | 1658 | - [#160](https://github.com/zendframework/zend-expressive/pull/160) updates 1659 | `EmitterStack` to throw a component-specific `InvalidArgumentException` 1660 | instead of the generic SPL version. 1661 | - [#163](https://github.com/zendframework/zend-expressive/pull/163) change the 1662 | documentation on wiring middleware factories to put them in the `dependencies` 1663 | section of `routes.global.php`; this keeps the routing and middleware 1664 | configuration in the same file. 1665 | 1666 | ## 0.5.2 - 2015-10-17 1667 | 1668 | ### Added 1669 | 1670 | - [#158](https://github.com/zendframework/zend-expressive/pull/158) documents 1671 | getting started via the [installer + skeleton](https://github.com/zendframework/zend-expressive-skeleton), 1672 | and also documents "next steps" in terms of creating and wiring middleware 1673 | when using the skeleton. 1674 | 1675 | ### Deprecated 1676 | 1677 | - Nothing. 1678 | 1679 | ### Removed 1680 | 1681 | - Nothing. 1682 | 1683 | ### Fixed 1684 | 1685 | - Nothing. 1686 | 1687 | ## 0.5.1 - 2015-10-13 1688 | 1689 | ### Added 1690 | 1691 | - Nothing. 1692 | 1693 | ### Deprecated 1694 | 1695 | - Nothing. 1696 | 1697 | ### Removed 1698 | 1699 | - Nothing. 1700 | 1701 | ### Fixed 1702 | 1703 | - [#156](https://github.com/zendframework/zend-expressive/pull/156) updates how 1704 | the routing middleware pulls middleware from the container; in order to work 1705 | with zend-servicemanager v3 and allow `has()` queries to query abstract 1706 | factories, a second, boolean argument is now passed. 1707 | 1708 | ## 0.5.0 - 2015-10-10 1709 | 1710 | ### Added 1711 | 1712 | - Nothing. 1713 | 1714 | ### Deprecated 1715 | 1716 | - Nothing. 1717 | 1718 | ### Removed 1719 | 1720 | - [#131](https://github.com/zendframework/zend-expressive/pull/131) modifies the 1721 | repository to remove the concrete router and template renderer 1722 | implementations, along with any related factories; these are now in their own 1723 | packages. The classes removed include: 1724 | - `Zend\Expressive\Container\Template\PlatesRendererFactory` 1725 | - `Zend\Expressive\Container\Template\TwigRendererFactory` 1726 | - `Zend\Expressive\Container\Template\ZendViewRendererFactory` 1727 | - `Zend\Expressive\Router\AuraRouter` 1728 | - `Zend\Expressive\Router\FastRouteRouter` 1729 | - `Zend\Expressive\Router\ZendRouter` 1730 | - `Zend\Expressive\Template\PlatesRenderer` 1731 | - `Zend\Expressive\Template\TwigRenderer` 1732 | - `Zend\Expressive\Template\Twig\TwigExtension` 1733 | - `Zend\Expressive\Template\ZendViewRenderer` 1734 | - `Zend\Expressive\Template\ZendView\NamespacedPathStackResolver` 1735 | - `Zend\Expressive\Template\ZendView\ServerUrlHelper` 1736 | - `Zend\Expressive\Template\ZendView\UrlHelper` 1737 | 1738 | ### Fixed 1739 | 1740 | - Nothing. 1741 | 1742 | ## 0.4.1 - TBD 1743 | 1744 | ### Added 1745 | 1746 | - Nothing. 1747 | 1748 | ### Deprecated 1749 | 1750 | - Nothing. 1751 | 1752 | ### Removed 1753 | 1754 | - Nothing. 1755 | 1756 | ### Fixed 1757 | 1758 | - Nothing. 1759 | 1760 | ## 0.4.0 - 2015-10-10 1761 | 1762 | ### Added 1763 | 1764 | - [#132](https://github.com/zendframework/zend-expressive/pull/132) adds 1765 | `Zend\Expressive\Router\ZendRouter`, replacing 1766 | `Zend\Expressive\Router\Zf2Router`. 1767 | - [#139](https://github.com/zendframework/zend-expressive/pull/139) adds: 1768 | - `Zend\Expressive\Template\TemplateRendererInterface`, replacing 1769 | `Zend\Expressive\Template\TemplateInterface`. 1770 | - `Zend\Expressive\Template\PlatesRenderer`, replacing 1771 | `Zend\Expressive\Template\Plates`. 1772 | - `Zend\Expressive\Template\TwigRenderer`, replacing 1773 | `Zend\Expressive\Template\Twig`. 1774 | - `Zend\Expressive\Template\ZendViewRenderer`, replacing 1775 | `Zend\Expressive\Template\ZendView`. 1776 | - [#143](https://github.com/zendframework/zend-expressive/pull/143) adds 1777 | the method `addDefaultParam($templateName, $param, $value)` to 1778 | `TemplateRendererInterface`, allowing users to specify global and 1779 | template-specific default parameters to use when rendering. To implement the 1780 | feature, the patch also provides `Zend\Expressive\Template\DefaultParamsTrait` 1781 | to simplify incorporating the feature in implementations. 1782 | - [#133](https://github.com/zendframework/zend-expressive/pull/133) adds a 1783 | stipulation to `Zend\Expressive\Router\RouterInterface` that `addRoute()` 1784 | should *aggregate* `Route` instances only, and delay injection until `match()` 1785 | and/or `generateUri()` are called; all shipped routers now follow this. This 1786 | allows manipulating `Route` instances before calling `match()` or 1787 | `generateUri()` — for instance, to inject options or a name. 1788 | - [#133](https://github.com/zendframework/zend-expressive/pull/133) re-instates 1789 | the `Route::setName()` method, as the changes to lazy-inject routes means that 1790 | setting names and options after adding them to the application now works 1791 | again. 1792 | 1793 | ### Deprecated 1794 | 1795 | - Nothing. 1796 | 1797 | ### Removed 1798 | 1799 | - [#132](https://github.com/zendframework/zend-expressive/pull/132) removes 1800 | `Zend\Expressive\Router\Zf2Router`, renaming it to 1801 | `Zend\Expressive\Router\ZendRouter`. 1802 | - [#139](https://github.com/zendframework/zend-expressive/pull/139) removes: 1803 | - `Zend\Expressive\Template\TemplateInterface`, renaming it to 1804 | `Zend\Expressive\Template\TemplateRendererInterface`. 1805 | - `Zend\Expressive\Template\Plates`, renaming it to 1806 | `Zend\Expressive\Template\PlatesRenderer`. 1807 | - `Zend\Expressive\Template\Twig`, renaming it to 1808 | `Zend\Expressive\Template\TwigRenderer`. 1809 | - `Zend\Expressive\Template\ZendView`, renaming it to 1810 | `Zend\Expressive\Template\ZendViewRenderer`. 1811 | 1812 | ### Fixed 1813 | 1814 | - Nothing. 1815 | 1816 | ## 0.3.1 - 2015-10-09 1817 | 1818 | ### Added 1819 | 1820 | - [#149](https://github.com/zendframework/zend-expressive/pull/149) adds 1821 | verbiage to the `RouterInterface::generateUri()` method, specifying that the 1822 | returned URI **MUST NOT** be escaped. The `AuraRouter` implementation has been 1823 | updated to internally use `generateRaw()` to follow this guideline, and retain 1824 | parity with the other existing implementations. 1825 | 1826 | ### Deprecated 1827 | 1828 | - Nothing. 1829 | 1830 | ### Removed 1831 | 1832 | - Nothing. 1833 | 1834 | ### Fixed 1835 | 1836 | - [#140](https://github.com/zendframework/zend-expressive/pull/140) updates the 1837 | AuraRouter to use the request method from the request object, and inject that 1838 | under the `REQUEST_METHOD` server parameter key before passing the server 1839 | parameters for matching. This simplifies testing. 1840 | 1841 | ## 0.3.0 - 2015-09-12 1842 | 1843 | ### Added 1844 | 1845 | - [#128](https://github.com/zendframework/zend-expressive/pull/128) adds 1846 | container factories for each supported template implementation: 1847 | - `Zend\Expressive\Container\Template\PlatesFactory` 1848 | - `Zend\Expressive\Container\Template\TwigFactory` 1849 | - `Zend\Expressive\Container\Template\ZendViewFactory` 1850 | - [#128](https://github.com/zendframework/zend-expressive/pull/128) adds 1851 | custom `url` and `serverUrl` zend-view helper implementations, to allow 1852 | integration with any router and with PSR-7 URI instances. The newly 1853 | added `ZendViewFactory` will inject these into the `HelperPluginManager` by 1854 | default. 1855 | 1856 | ### Deprecated 1857 | 1858 | - Nothing. 1859 | 1860 | ### Removed 1861 | 1862 | - Nothing. 1863 | 1864 | ### Fixed 1865 | 1866 | - [#128](https://github.com/zendframework/zend-expressive/pull/128) fixes an 1867 | expectation in the `WhoopsErrorHandler` tests to ensure the tests can run 1868 | successfully. 1869 | 1870 | ## 0.2.1 - 2015-09-10 1871 | 1872 | ### Added 1873 | 1874 | - Nothing. 1875 | 1876 | ### Deprecated 1877 | 1878 | - Nothing. 1879 | 1880 | ### Removed 1881 | 1882 | - Nothing. 1883 | 1884 | ### Fixed 1885 | 1886 | - [#125](https://github.com/zendframework/zend-expressive/pull/125) fixes the 1887 | `WhoopsErrorHandler` to ensure it pushes the "pretty page handler" into the 1888 | Whoops runtime. 1889 | 1890 | ## 0.2.0 - 2015-09-03 1891 | 1892 | ### Added 1893 | 1894 | - [#116](https://github.com/zendframework/zend-expressive/pull/116) adds 1895 | `Application::any()` to complement the various HTTP-specific routing methods; 1896 | it has the same signature as `get()`, `post()`, `patch()`, et al, but allows 1897 | any HTTP method. 1898 | - [#120](https://github.com/zendframework/zend-expressive/pull/120) renames the 1899 | router classes for easier discoverability, to better reflect their usage, and 1900 | for better naming consistency. `Aura` becomes `AuraRouter`, `FastRoute` 1901 | becomes `FastRouteRouter` and `Zf2` becomes `Zf2Router`. 1902 | 1903 | ### Deprecated 1904 | 1905 | - Nothing. 1906 | 1907 | ### Removed 1908 | 1909 | - [#120](https://github.com/zendframework/zend-expressive/pull/120) removes the 1910 | classes `Zend\Expressive\Router\Aura`, `Zend\Expressive\Router\FastRoute`, and 1911 | `Zend\Expressive\Router\Zf`, per the "Added" section above. 1912 | 1913 | ### Fixed 1914 | 1915 | - Nothing. 1916 | 1917 | ## 0.1.1 - 2015-09-03 1918 | 1919 | ### Added 1920 | 1921 | - [#112](https://github.com/zendframework/zend-expressive/pull/112) adds a 1922 | chapter to the documentation on using Aura.Di (v3beta) with zend-expressive. 1923 | 1924 | ### Deprecated 1925 | 1926 | - Nothing. 1927 | 1928 | ### Removed 1929 | 1930 | - Nothing. 1931 | 1932 | ### Fixed 1933 | 1934 | - [#118](https://github.com/zendframework/zend-expressive/pull/118) fixes an 1935 | issue whereby route options specified via configuration were not being pushed 1936 | into generated `Route` instances before being passed to the underlying router. 1937 | 1938 | ## 0.1.0 - 2015-08-26 1939 | 1940 | Initial tagged release. 1941 | 1942 | ### Added 1943 | 1944 | - Everything. 1945 | 1946 | ### Deprecated 1947 | 1948 | - Nothing. 1949 | 1950 | ### Removed 1951 | 1952 | - Nothing. 1953 | 1954 | ### Fixed 1955 | 1956 | - Nothing. 1957 | --------------------------------------------------------------------------------