{"id":16676568,"url":"https://github.com/johnvandeweghe/lunixrest","last_synced_at":"2025-04-09T20:40:43.467Z","repository":{"id":36393482,"uuid":"40698384","full_name":"johnvandeweghe/LunixREST","owner":"johnvandeweghe","description":"[DEPRECATED] Use the PHP API Library project instead. https://github.com/johnvandeweghe/php-api-librarary-rest  - A lightweight, extensible PHP based REST library. ","archived":false,"fork":false,"pushed_at":"2017-06-04T06:40:57.000Z","size":941,"stargazers_count":4,"open_issues_count":10,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-23T22:37:01.260Z","etag":null,"topics":["library","php","rest-api"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/johnvandeweghe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-14T05:58:47.000Z","updated_at":"2018-06-30T06:56:22.000Z","dependencies_parsed_at":"2022-08-21T11:40:46.288Z","dependency_job_id":null,"html_url":"https://github.com/johnvandeweghe/LunixREST","commit_stats":null,"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnvandeweghe%2FLunixREST","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnvandeweghe%2FLunixREST/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnvandeweghe%2FLunixREST/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnvandeweghe%2FLunixREST/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/johnvandeweghe","download_url":"https://codeload.github.com/johnvandeweghe/LunixREST/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248109624,"owners_count":21049347,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["library","php","rest-api"],"created_at":"2024-10-12T13:10:54.016Z","updated_at":"2025-04-09T20:40:43.446Z","avatar_url":"https://github.com/johnvandeweghe.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/johnvandeweghe/LunixREST.svg?branch=master)](https://travis-ci.org/johnvandeweghe/LunixREST) [![Code Coverage](https://scrutinizer-ci.com/g/johnvandeweghe/LunixREST/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/johnvandeweghe/LunixREST/?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/johnvandeweghe/LunixREST/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/johnvandeweghe/LunixREST/?branch=master)\n\n# Overview\n\nLunixREST is a highly extensible, lightweight library for writing REST APIs in PHP (7.1+).\n\nIt's primary goal is to allow the creation of a REST API in which every part of it's behaviour can be overwritten without any code hacks. Because of this, it's generally very compatible with existing codebases.\n\n## Features\n- API key access control\n- Routing to endpoints\n- API versioning\n- API Access throttling\n- PSR-2 styled\n- PSR-3 (logging) compatible\n- PSR-4 (autoloading) compatible\n- PSR-6 (caching) compatible\n- PSR-7 (http) compatible\n- Versatile output formatting\n\nSee https://github.com/johnvandeweghe/LunixREST-Basics for some basic implementations, and examples.\n\n## Project standards\n\n### Unit test coverage\n\nThis project seeks to approach as close to 100% code coverage at all times as reasonably possible. Both in numbers, and in actual code path coverage. If that is ever not the case, leave an issue and it will be addressed ASAP.\n\n### Contributing\n\nContributions for this project are really appreciated. Just leave a pull request with the requested change/addition. Preferably let me know you're working on it by leaving an issue.\nAll PRs not following the standards outlined here will not be merged until any differences are resolved.\n\n### Code style\n\nAs mentioned in the Features list above, this project adheres as closely to PSR-2 as possible. No auto stylers are utilized, so there may be portions of the code that violate this. Feel free to drop an issue ticket for any infractions and I will address them.\n\n### Namespacing\n\nNamespacing follows PSR-4. Further, namespaces should be nested by dependency. Meaning, if a Server is the only class that uses a Widget, then a Widget should be within the Server namespace. Cross dependencies should result in the depended class being no closer to root than needed.\n\n# Installation\n## Requirements\nAll dependencies are specified in the composer.json, so as long as you use composer with this library, all dependencies should be taken care of.\n\nThat being said, here are some dependencies:\n* PHP 7.1+\n* php-mbstring\n* PSR/Cache\n* PSR/HTTP-Message\n* PSR/Log\n\n## Version Notice\nThis project updates master regularly. Changes to master that are not released are not guaranteed to be stable, and should be treated as such. Use the release tags for production projects.\n\nAll minor version number updates will have guaranteed backwards compatibility. Major version changes won't be held to that standard, but generally the goal is to minimise interface changes.\n\n## Installation\n\nThis project is listed in [Packigist](https://packagist.org/packages/johnvandeweghe/lunixrest), the default repository for Composer. So installation is as simple as:\n\n``` composer require johnvandeweghe/lunixrest ```\n\n# Usage\n\n## HTTPServer\nThe basis of an implementation of LunixREST is the class HTTPServer. This class takes in a PSR-7 ServerRequestInterface and returns a ResponseInterface that can be dumped to the SAPI.\n\nHere is an example that uses Guzzle's PSR-7 implementation (which if you're using LunixREST-Basics is already included).\n```php\n$httpServer = new \\LunixREST\\HTTPServer($server, $requestFactory, $logger);\n\n$serverRequest = \\GuzzleHttp\\Psr7\\ServerRequest::fromGlobals();\n\n\\LunixREST\\HTTPServer::dumpResponse($httpServer-\u003ehandleRequest($serverRequest, new GuzzleHttp\\Psr7\\Response()));\n```\n\nLooks pretty simple, except for the obvious missing variable definitions of ```$server```, ```$requestFactory```, and ```$logger```.\nAn HTTPServer requires these to be constructed, so lets build them one at a time as an example.\n### Server/GenericServer\nA Server's jobs is to take in a APIRequest generated by the HTTPServer, an return an APIResponse (or throw an exception, if applicable to the request)\n\nBut Server is an interface, so we'll need a specific implementation to use. In this example we'll be using a GenericServer. GenericServer is an implementation that is meant to derive as much behaviour as possible from other classes.\n\n```php\n$server = new GenericServer($accessControl, $throttle, $responseFactory, $router);\n```\n\nAgain, simple, but we're missing some definitions, so lets break those down one-by-one.\n\n#### AccessControl/PublicAccessControl\n\nA GenericServer requires an AccessControl instance to handle controlling access.\n\nFor example, a PublicAccessControl takes in a request and says that it is allowed, without checking it at all. As the name implies, it's for a public API, and ignores the key entirely.\n\n```php\n$accessControl = new \\LunixREST\\Server\\AccessControl\\PublicAccessControl();\n```\n\n#### Throttle/NoThrottle\n\nA GenericServer also requires a Throttle instance to handling throttling requests if needed.\n\nFor example, a NoThrottle just returns that a given request doesn't need to be throttled, ever. Less applicable to real API implementations, beyond smaller ones. Actual implementations of Throttle will be able to be found in LunixREST-Basics.\n\n```php\n$throttle = new \\LunixREST\\Server\\Throttle\\NoThrottle();\n```\n#### ResponseFactory/RegisteredResponseFactory\n\nAnother thing that a GenericServer requires is an instance of a ResponseFactory, which it uses to form the APIResponseData into an APIResponse. A key feature to this is transforming the data in an APIResponseData object and converting it into an PSR-7 StreamInterface.\n\nFor example, a RegisteredResponseFactory takes in a list of APIResponseDataSerializers and associates them with a specific MIME type.\n\n```php\n$responseFactory = new \\LunixREST\\Server\\ResponseFactory\\RegisteredResponseFactory([\n    'application/json' =\u003e new \\LunixRESTBasics\\APIResponse\\JSONResponseDataSerializer()\n]);\n```\n\nYou'll notice that the JSONResponseDataSerializer is in the LunixREST-Basics project. This is because it requires a specific PSR-7 implementation (it uses Guzzle's). No actual implementations of APIResponseDataSerializer are included in Core because of this reason. \n\n#### Router/GenericRouter\n\nThe final thing that a GenericServer needs to function is a Router. A Router takes a request and decides which Endpoint and method on that Endpoint to call. It then proceeds to call the endpoint and return the result.\n\nFor this example, we'll be using a GenericRouter, which defines some basic behaviour, but passes most of the details off to an EndpointFactory which is used to actually find an Endpoint.\n\n```php\n$router = new \\LunixREST\\Server\\Router\\GenericRouter($endpointFactory);\n```\n\n##### EndpointFactory/SingleEndpointFactory\n\nAn EndpointFactory builds an endpoint from the requested endpoint name, and the APIRequest's parsed version.\n\nThe implementation we'll be using in this example is a SingleEndpointFactory from the Basics repo. We're also using a generic HelloWorld Endpoint, the code for which is provided after the example.\n\n```php\n$endpointFactory = new \\LunixRESTBasics\\Endpoint\\SingleEndpointFactory(new HelloWorld());\n```\n\n```php\nuse LunixREST\\Server\\APIResponse\\APIResponseData;\nuse LunixREST\\Server\\Router\\Endpoint\\DefaultEndpoint;\nuse LunixREST\\Server\\Router\\Endpoint\\Exceptions\\UnsupportedMethodException;\nuse LunixREST\\Server\\APIRequest\\APIRequest;\n\nclass HelloWorld extends DefaultEndpoint\n{\n\n    /**\n     * @param APIRequest $request\n     * @return APIResponseData\n     * @throws UnsupportedMethodException\n     */\n    public function getAll(APIRequest $request): APIResponseData\n    {\n        return new APIResponseData([\n            \"helloworld\" =\u003e \"HelloWorld\"\n        ]);\n    }\n}\n```\n\nThis is also the time where an API could take advantage of an implementation of an EndpointFactory that extends the included abstract classes LoggingEndpointFactory and CachingEndpointFactory. These implementations are written to allow the use of the logging and caching PSRs.\n\n### RequestFactory\n\nNow that we have the Server taken care of, the next thing an HTTPServer needs to function is an instance of a RequestFactory.\n\nThe job of a RequestFactory is to take in the PSR-7 ServerRequestInterface, and to parse it into an APIRequest.\n\nGenerally you'll want to use the GenericRequestFactory and define you're own URLParser and HeaderParser. If you just want to use a pre-written header parser, you can use a DefaultRequestFactory that just needs a URLParser and uses the built in DefaultHeaderParser.\n\nHowever, for this example we'll keep it a bit simpler and use another class from LunixREST-Basics: BasicRequestFactory, which extends the DefaultRequestFactory to use a BasicURLParser.\n\nThe BasicURLParser expects a request to look like this:\n\n```\n/VERSION/API_KEY/ENDPOINT[/OPTIONAL_ELEMENT].RESPONSE_TYPE_EXTENSION\n```\n\nOr to test our current example:\n\n```\n/1.0/public/helloworld.json\n```\n\nFinally, our example code:\n\n```php\n$requestFactory = new \\LunixRESTBasics\\APIRequest\\RequestFactory\\BasicRequestFactory();\n```\n\n### LoggerInterface\n\nThe final thing that an HTTPServer needs is an instance of a PSR LoggerInterface. This has been required here as the PSR offers an easy out for those who don't want to log: NullLogger. For actual logging, we recommend [Monolog](https://packagist.org/packages/monolog/monolog).\n\n```php\n$logger = new \\Psr\\Log\\NullLogger();\n```\n\n## Full Example\n\nWe now have everything we need to define a basic API using LunixREST. Our API has the following features defined:\n\n* Public\n* Explicitly avoids throttling\n* Can write JSON responses\n* Handles all requests with a single endpoint (HelloWorld)\n* Avoids any PSR-7 request body middleware, so it only can handle HTTP urlencoded/form-data requests\n\nThe code for this looks like:\n\n```php\n$accessControl = new \\LunixREST\\Server\\AccessControl\\PublicAccessControl();\n$throttle = new \\LunixREST\\Server\\Throttle\\NoThrottle();\n\n$responseFactory = new \\LunixREST\\Server\\ResponseFactory\\RegisteredResponseFactory([\n    'application/json' =\u003e new \\LunixRESTBasics\\APIResponse\\JSONResponseDataSerializer()\n]);\n\n$endpointFactory = new \\LunixRESTBasics\\Endpoint\\SingleEndpointFactory(new \\HelloWorld());\n\n$router = new \\LunixREST\\Server\\Router\\GenericRouter($endpointFactory);\n\n$server = new \\LunixREST\\Server\\GenericServer($accessControl, $throttle, $responseFactory, $router);\n\n$requestFactory = new \\LunixRESTBasics\\APIRequest\\RequestFactory\\BasicRequestFactory\\BasicRequestFactory();\n\n$logger = new \\Psr\\Log\\NullLogger();\n\n$httpServer = new \\LunixREST\\HTTPServer($server, $requestFactory, $logger);\n\n$serverRequest = \\GuzzleHttp\\Psr7\\ServerRequest::fromGlobals();\n\n\\LunixREST\\HTTPServer::dumpResponse($httpServer-\u003ehandleRequest($serverRequest, new \\GuzzleHttp\\Psr7\\Response()));\n\n```\n\nAs well as the code for our one Endpoint:\n\n```php\nuse LunixREST\\Server\\APIResponse\\APIResponseData;\nuse LunixREST\\Server\\Router\\Endpoint\\DefaultEndpoint;\nuse LunixREST\\Server\\Router\\Endpoint\\Exceptions\\UnsupportedMethodException;\nuse LunixREST\\Server\\APIRequest\\APIRequest;\n\nclass HelloWorld extends DefaultEndpoint\n{\n\n    /**\n     * @param APIRequest $request\n     * @return APIResponseData\n     * @throws UnsupportedMethodException\n     */\n    public function getAll(APIRequest $request): APIResponseData\n    {\n        return new APIResponseData([\n            \"helloworld\" =\u003e \"HelloWorld\"\n        ]);\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnvandeweghe%2Flunixrest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjohnvandeweghe%2Flunixrest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnvandeweghe%2Flunixrest/lists"}