├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── UPGRADING.md ├── composer.json ├── phpdoc.dist.xml ├── phpunit.xml.dist ├── src └── Klein │ ├── AbstractResponse.php │ ├── AbstractRouteFactory.php │ ├── App.php │ ├── DataCollection │ ├── DataCollection.php │ ├── HeaderDataCollection.php │ ├── ResponseCookieDataCollection.php │ ├── RouteCollection.php │ └── ServerDataCollection.php │ ├── Exceptions │ ├── DispatchHaltedException.php │ ├── DuplicateServiceException.php │ ├── HttpException.php │ ├── HttpExceptionInterface.php │ ├── KleinExceptionInterface.php │ ├── LockedResponseException.php │ ├── RegularExpressionCompilationException.php │ ├── ResponseAlreadySentException.php │ ├── RoutePathCompilationException.php │ ├── UnhandledException.php │ ├── UnknownServiceException.php │ └── ValidationException.php │ ├── HttpStatus.php │ ├── Klein.php │ ├── Request.php │ ├── Response.php │ ├── ResponseCookie.php │ ├── Route.php │ ├── RouteFactory.php │ ├── ServiceProvider.php │ └── Validator.php └── tests ├── Klein └── Tests │ ├── AbstractKleinTest.php │ ├── AbstractRouteFactoryTest.php │ ├── AppTest.php │ ├── DataCollection │ ├── DataCollectionTest.php │ ├── HeaderDataCollectionTest.php │ ├── ResponseCookieDataCollectionTest.php │ ├── RouteCollectionTest.php │ └── ServerDataCollectionTest.php │ ├── HttpStatusTest.php │ ├── KleinTest.php │ ├── Mocks │ ├── MockRequestFactory.php │ └── TestClass.php │ ├── RequestTest.php │ ├── ResponseCookieTest.php │ ├── ResponseTest.php │ ├── RouteFactoryTest.php │ ├── RouteTest.php │ ├── RoutingTest.php │ ├── ServiceProviderTest.php │ ├── ValidationsTest.php │ ├── routes │ └── random.php │ └── views │ ├── layout.php │ └── test.php ├── bootstrap.php └── functions-bootstrap.php /.gitignore: -------------------------------------------------------------------------------- 1 | # Composer 2 | composer.lock 3 | vendor/ 4 | 5 | # Auto-generated documentation directory (phpDocumentor) 6 | docs/ 7 | 8 | # Auto-generated code coverage report 9 | report/ 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: php 4 | php: 5 | - 5.3 6 | - 5.4 7 | - 5.5 8 | - 5.6 9 | - 7.0 10 | - nightly 11 | - hhvm 12 | 13 | matrix: 14 | allow_failures: 15 | - php: nightly 16 | - php: hhvm 17 | fast_finish: true 18 | 19 | before_script: 20 | - composer install --prefer-dist 21 | 22 | script: 23 | - composer validate 24 | - ./vendor/bin/phpunit 25 | - ./vendor/bin/phpcs --standard=PSR2 --encoding=utf-8 -p src/ tests/ 26 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | 4 | ## 2.1.2 5 | 6 | ### Features 7 | 8 | - PHP 7 `Throwable`s will now properly be caught and sent up the exception handling chain. 9 | - Expanded compatibility with other exception types in some method signatures 10 | 11 | ### Bug fixes 12 | 13 | - Broad exception catch statements will now properly handle PHP 7 `Throwable` types 14 | 15 | 16 | ## 2.1.1 17 | 18 | ### Features 19 | 20 | - Header keys are now normalized, by default, to their canonical MIME format for consistency 21 | - Header key normalization is now customizable 22 | - Internal callback data-structures were moved from arrays to more appropriate SplQueue and SplStack instances, providing performance and memory footprint improvements 23 | - The PHPUnit version used for tests has been updated for HHVM compatibility 24 | - PHP 7.0 and HHVM compatibility! 25 | 26 | ### Bug fixes 27 | 28 | - A few internal property/attribute names have been updated for consistency 29 | - An iteration bug effecting tests run under certain HHVM runtime versions has been fixed 30 | - The README document has been updated to fix a few errors 31 | - The `file()` method in the `Response` class has been updated to fix an issue found when run under PHP-FPM 32 | - The `file()` method in the `Response` class will no longer send the `Content-Length` header when the response has been chunked, to comply with the HTTP requirements defined in RFC 2616 33 | - References to the old https://github.com/chriso/klein.php repository URL have been updated to the new repository URL home of Klein: https://github.com/klein/klein.php 34 | - Tests were updated to pass under an expanded number of PHP runtime versions and configurations 35 | - A potential output buffer stack miss-handling in the dispatch process has been fixed 36 | 37 | 38 | ## 2.1.0 39 | 40 | ### Features 41 | 42 | - New exception and helper methods to help control the dispatch flow 43 | - New `abort()` method to allow stopping the routing process and returning a response code 44 | - Routes are now instances of a new `Route` class, instead of just being a set of meta properties and a callback 45 | - Routes are now stored in a `RouteCollection` class, which extends the `DataCollection` class 46 | - New `keys()` and `clear()` methods for the `DataCollection` class 47 | - Added the capability of reverse routing! 48 | - Now allowing for route callbacks to change the response object by returning a new ApiResponse instance 49 | - New "slug" type for route param matching 50 | - New `isEmpty()` and `cloneEmpty()` methods for the `DataCollection` class 51 | - The `$matched` route callback parameter is now an instance of a `RouteCollection`, instead of just an integer 52 | - Route callbacks are now passed the Klein instance for easier closure/class-scope use 53 | - Regular expression routing is now more accurate and will match more special characters in a similar way to Sinatra 54 | - Routes are now built with a dependency injected `AbstractRouteFactory` instance, allowing the building of routes to be customized more easily 55 | - New `options()` and `head()` alias methods for matching OPTIONS and HEAD requests respectively 56 | - The `Response` class has been abstracted into an `AbstractResponse` and a separate `Response` class for cleaner 3rd-party extension 57 | - New "after dispatch" callbacks can be registered for firing a series of callbacks after the dispatch loop has completed 58 | - New `patch()` alias method for matching PATCH requests 59 | - New HTTP error handling via exceptions and callback registration for a more direct (and less magical) API for controlling HTTP errors 60 | - The `escape()` method in the `ServiceProvider` class now allows for the passing of entity escaping flags 61 | - Route regular expressions are now validated and provide helpful errors upon a validation failure 62 | - Routes can now contain an empty string path 63 | - The composer autoloader is now compatible with the PSR-4 standard. 64 | - Regular expression compilation performance has been improved 65 | - 100% Code Coverage 66 | 67 | ### Bug fixes 68 | 69 | - The README document has been updated to fix a few typos and inconsistencies 70 | - Route params are now properly URL decoded 71 | - 404/405 routes now properly set the appropriate status code automatically 72 | - Silencing the locked response exceptions as the behavior is designed to be transparent/automatic 73 | - Allow route callables to be an array suitable for `call_user_func()` callable behavior 74 | - More proper handling for 404's that also call the 404 error handlers 75 | - The `file()` and `json()` methods in the `Response` class no longer override system-configured time processing limits 76 | - Now checking if the output buffer is open before attempting to close it 77 | - The methods matched counter (`$methods_matched`) is now much more accurate, not counting methods that shouldn't have been considered matches 78 | - Various PHPdoc inaccuracies and inconsistencies have been fixed 79 | - Regular expressions are now quoted during compilation in a much safer manner 80 | - The PHPdoc tags have been updated to use the more modern syntax 81 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributing is absolutely encouraged, but a few things should be taken into account: 4 | 5 | - Always test any bug-fixes or changes with [unit testing][unit-testing] 6 | - When adding or changing a feature, make sure to write a **new** [unit test][unit-testing] 7 | - This project adheres to the [PSR-2][psr-2] standards. Please make sure your contributions [comply][code-sniffer]. 8 | - Code and comment styles should be made as consistent as possible with the rest of the project 9 | - Make sure to document your code with the [PHPDoc syntax][php-doc] 10 | - Pull Requests and Issues should contain no more than **1** bug-fix, feature, or documentation change 11 | - Keep the number of lines changed in a pull request to a minimum necessary to complete the PR's subject 12 | - Pull requests shouldn't contain commits from other pull requests. They should be separate, independent branches 13 | - When creating pull requests 14 | - make sure to create useful/verbose PR messages 15 | - don't be afraid to squash your commits 16 | - rebase onto the parent's upstream branch before pushing your remote 17 | 18 | Klein is an open library designed for a specific purpose. You may find that a certain requested feature or change may not be accepted. Please don't take those actions personally, as the controlling contributors are simply just trying to keep the project's purpose clear and designated. 19 | 20 | [unit-testing]: README.md#unit-testing 21 | [psr-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md 22 | [code-sniffer]: https://github.com/squizlabs/PHP_CodeSniffer 23 | [php-doc]: http://www.phpdoc.org/docs/latest/for-users/phpdoc-reference.html 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Chris O'Hara 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /UPGRADING.md: -------------------------------------------------------------------------------- 1 | # Klein Upgrade Guide 2 | 3 | 4 | ## 2.1.1 to 2.1.2 5 | 6 | ### Interface Changes 7 | 8 | - The `RoutePathCompilationException::createFromRoute()` method signature has changed to allow both `Exception` and `Throwable` types with dual support for PHP 5 and PHP 7 9 | - The 4th parameter to the callbacks supported by `Klein#onError` will now be able to receive `Throwable` types under PHP 7 10 | 11 | 12 | ## 2.1.0 to 2.1.1 13 | 14 | ### Deprecations 15 | 16 | - The `HeaderDataCollection::normalizeName()` method has been deprecated in favor of using new normalization options (via constant switches) and other more specific methods on the same class 17 | 18 | ### Interface Changes 19 | 20 | - Three of the Klein internal callback attributes have changed both name and data structure. These attributes are protected, so the effect will only be felt by users that have extended and/or overwritten Klein's internal behaviors. The following changes were made: 21 | - `Klein#errorCallbacks` was renamed to `Klein#error_callbacks` and it's array data-structure was changed to use an `SplStack` 22 | - `Klein#httpErrorCallbacks` was renamed to `Klein#http_error_callbacks` and it's array data-structure was changed to use an `SplStack` 23 | - `Klein#afterFilterCallbacks` was renamed to `Klein#after_filter_callbacks` and it's array data-structure was changed to use an `SplQueue` 24 | - `Validator#defaultAdded` was renamed to `Validator#default_added` 25 | 26 | 27 | ## 2.0.x to 2.1.0 28 | 29 | ### Deprecations 30 | 31 | - Handling 404 and 405 errors with a specially registered route callback is now deprecated. It's now suggested to use Klein's new `onHttpError()` method instead. 32 | - Autoloading the library with Composer no longer utilizes the PSR-0 spec. The composer autoloader now uses PSR-4. 33 | 34 | ### Interface Changes 35 | 36 | - Some of the route callback params have changed. This will effect any route definitions with callbacks using the more advanced parameters. 37 | - The old params were (in order): 38 | - `Request $request` 39 | - `Response $response` 40 | - `Service $service` 41 | - `App $app` 42 | - `int $matched` 43 | - `array $methods_matched` 44 | - The new params are (in order): 45 | - `Request $request` 46 | - `Response $response` 47 | - `Service $service` 48 | - `App $app` 49 | - `Klein $klein` 50 | - `RouteCollection $matched` 51 | - `array $methods_matched` 52 | - Non-match routes (routes that are wildcard and shouldn't consider as "matches") will no longer be considered as part of the "methods matched" array, since they aren't supposed to be matches in the first place 53 | - This may have implications for users that have created "match-all" OPTIONS method routes, as the OPTIONS method will no longer be considered a match. 54 | - If you'd like to conserve the old match behavior, you can simply mark the route as one that should be counted as a match with `$route->setCountMatch(true)` 55 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "klein/klein", 3 | "description": "A lightning fast router for PHP", 4 | "keywords": ["router", "routing", "sinatra", "boilerplate"], 5 | "homepage": "https://github.com/klein/klein.php", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Chris O'Hara", 10 | "email": "cohara87@gmail.com", 11 | "homepage": "http://chris6f.com/", 12 | "role": "Creator/Developer" 13 | }, 14 | { 15 | "name": "Trevor Suarez", 16 | "email": "rican7@gmail.com", 17 | "homepage": "https://trevorsuarez.com/", 18 | "role": "Contributor/Developer" 19 | } 20 | ], 21 | "require": { 22 | "php": ">=5.3.0" 23 | }, 24 | "require-dev": { 25 | "phpunit/phpunit": "^4.8", 26 | "phpunit/php-code-coverage": "^2.2", 27 | "squizlabs/php_codesniffer": "1.4.8" 28 | }, 29 | "autoload": { 30 | "psr-4": { 31 | "Klein\\": "src/Klein/" 32 | } 33 | }, 34 | "autoload-dev": { 35 | "psr-4": { 36 | "Klein\\Tests\\": "tests/Klein/Tests" 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /phpdoc.dist.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Klein 5 | 6 | src 7 | 8 | 9 | docs 10 | 11 | 12 | docs 13 | 14 | 15 |