rest-proxy.php

Simple proxy for RESTful APIs
git clone git://git.finwo.net/app/rest-proxy.php
Log | Files | Refs | README

commit b6c416c8bd52bbe290b211f025a088fae0ad971d
parent 3208dcf7e32fd7b78c8ff0208541c45205e74e25
Author: finwo <finwo@pm.me>
Date:   Mon, 18 Apr 2016 00:14:55 +0200

Finding proper controller already functional

Diffstat:
Mcomposer.json | 8+++++---
Mcomposer.lock | 268+++++++++++++++++++------------------------------------------------------------
Mconfig/config.yml | 13+++++++++++--
Msrc/Finwo/Framework/Application.php | 85++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Asrc/Finwo/Framework/RestController.php | 9+++++++++
Asrc/Finwo/Framework/Route.php | 296+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Finwo/RestProxy/Controller/DefaultController.php | 4+++-
Asrc/Finwo/RestProxy/Controller/RestController.php | 14++++++++++++++
Asrc/Finwo/RestProxy/Document/Config.php | 11+++++++++++
Msrc/Finwo/RestProxy/RestProxy.php | 5+----
10 files changed, 497 insertions(+), 216 deletions(-)

diff --git a/composer.json b/composer.json @@ -15,12 +15,14 @@ "repositories": [ { "type": "vcs", - "url": "git@github.com:finwo/rest-client-php.git" + "url": "git@github.com:finwo/data-tools-php.git" } ], "require": { - "finwo/rest-client": "*@dev", "mustangostang/spyc": "^0.5.1", - "finwo/property-accessor": "*@dev" + "finwo/property-accessor": "*@dev", + "adoy/oauth2": "^1.3", + "finwo/data-tools": "dev-master", + "netresearch/jsonmapper": "^0.11.0" } } diff --git a/composer.lock b/composer.lock @@ -4,59 +4,70 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "2fe81bc1ad1a89bc15cec332e767fe59", - "content-hash": "ad44324d856de87133bbeba4a30ca9a0", + "hash": "280e83084986cce328d1f822ab5357c2", + "content-hash": "973564a82e976b87ea07f13913d08004", "packages": [ { - "name": "finwo/property-accessor", - "version": "dev-master", + "name": "adoy/oauth2", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/finwo/property-accessor.git", - "reference": "e5c274de0b05fedb4f8abdafbaeec5ffaf9eed68" + "url": "https://github.com/adoy/PHP-OAuth2.git", + "reference": "617d8605955cbb0ca929358fda74eab308c39cfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/finwo/property-accessor/zipball/e5c274de0b05fedb4f8abdafbaeec5ffaf9eed68", - "reference": "e5c274de0b05fedb4f8abdafbaeec5ffaf9eed68", + "url": "https://api.github.com/repos/adoy/PHP-OAuth2/zipball/617d8605955cbb0ca929358fda74eab308c39cfa", + "reference": "617d8605955cbb0ca929358fda74eab308c39cfa", "shasum": "" }, + "require": { + "php": ">=5.3.0" + }, "type": "library", "autoload": { - "psr-4": { - "Finwo\\PropertyAccessor\\": "src/" + "psr-0": { + "OAuth2": "src/" } }, "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], "authors": [ { - "name": "Robin Bron", - "email": "robin@finwo.nl" + "name": "Berejeb Anis", + "email": "anis.berejeb@gmail.com" + }, + { + "name": "Charron Pierrick", + "email": "pierrick@webstart.fr" } ], - "time": "2016-04-17 00:14:13" + "description": "Light PHP wrapper for the OAuth 2.0 protocol (based on OAuth 2.0 Authorization Protocol draft-ietf-oauth-v2-15)", + "time": "2015-08-03 19:57:06" }, { - "name": "finwo/rest-client", + "name": "finwo/data-tools", "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/finwo/rest-client-php.git", - "reference": "6447201b157cf3d012e985ef1d6b685408bc6e1e" + "url": "https://github.com/finwo/data-tools-php.git", + "reference": "c3e7eaa1f422736eb7e5079452f6fa4bb7aafb73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/finwo/rest-client-php/zipball/6447201b157cf3d012e985ef1d6b685408bc6e1e", - "reference": "6447201b157cf3d012e985ef1d6b685408bc6e1e", + "url": "https://api.github.com/repos/finwo/data-tools-php/zipball/c3e7eaa1f422736eb7e5079452f6fa4bb7aafb73", + "reference": "c3e7eaa1f422736eb7e5079452f6fa4bb7aafb73", "shasum": "" }, "require": { - "guzzlehttp/guzzle": "^6.2" + "finwo/property-accessor": "dev-master" }, "type": "library", "autoload": { "psr-4": { - "Finwo\\RestClient\\": "src" + "Finwo\\Datatools\\": "src/" } }, "authors": [ @@ -65,183 +76,40 @@ "email": "robin@finwo.nl" } ], - "description": "Generic rest client for php", "support": { - "source": "https://github.com/finwo/rest-client-php/tree/master", - "issues": "https://github.com/finwo/rest-client-php/issues" + "source": "https://github.com/finwo/data-tools-php/tree/master", + "issues": "https://github.com/finwo/data-tools-php/issues" }, - "time": "2016-04-16 23:18:35" + "time": "2016-04-17 17:02:21" }, { - "name": "guzzlehttp/guzzle", + "name": "finwo/property-accessor", "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "85cb758d7367f3aaaa8ffc9269e777919c5f68bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/85cb758d7367f3aaaa8ffc9269e777919c5f68bb", - "reference": "85cb758d7367f3aaaa8ffc9269e777919c5f68bb", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "~1.0", - "guzzlehttp/psr7": "~1.1", - "php": ">=5.5.0" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "~4.0", - "psr/log": "~1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.2-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2016-04-06 17:59:33" - }, - { - "name": "guzzlehttp/promises", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8" + "url": "https://github.com/finwo/property-accessor.git", + "reference": "3135b3e4f34f6887b37e0c23811aa9566df4abab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/bb9024c526b22f3fe6ae55a561fd70653d470aa8", - "reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8", + "url": "https://api.github.com/repos/finwo/property-accessor/zipball/3135b3e4f34f6887b37e0c23811aa9566df4abab", + "reference": "3135b3e4f34f6887b37e0c23811aa9566df4abab", "shasum": "" }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, "autoload": { "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-03-08 01:15:46" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "31382fef2889136415751badebbd1cb022a4ed72" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/31382fef2889136415751badebbd1cb022a4ed72", - "reference": "31382fef2889136415751badebbd1cb022a4ed72", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" + "Finwo\\PropertyAccessor\\": "src/" } }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Robin Bron", + "email": "robin@finwo.nl" } ], - "description": "PSR-7 message implementation", - "keywords": [ - "http", - "message", - "stream", - "uri" - ], - "time": "2016-04-13 19:56:01" + "time": "2016-04-17 19:15:10" }, { "name": "mustangostang/spyc", @@ -294,61 +162,51 @@ "time": "2015-08-13 21:51:08" }, { - "name": "psr/http-message", - "version": "dev-master", + "name": "netresearch/jsonmapper", + "version": "v0.11.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "979abda4b128415c642b06f07db615e75cfd3173" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/979abda4b128415c642b06f07db615e75cfd3173", + "reference": "979abda4b128415c642b06f07db615e75cfd3173", "shasum": "" }, - "require": { - "php": ">=5.3.0" + "require-dev": { + "phpunit/phpunit": "4.2.*", + "squizlabs/php_codesniffer": "~1.5" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" + "psr-0": { + "JsonMapper": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "OSL-3.0" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" } ], - "description": "Common interface for HTTP messages", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2015-05-04 20:22:00" + "description": "Map nested JSON structures onto PHP classes", + "time": "2016-04-14 21:59:35" } ], "packages-dev": [], "aliases": [], "minimum-stability": "dev", "stability-flags": { - "finwo/rest-client": 20, - "finwo/property-accessor": 20 + "finwo/property-accessor": 20, + "finwo/data-tools": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/config/config.yml b/config/config.yml @@ -4,4 +4,13 @@ application: Finwo\RestProxy # Note of the authors authors: - - Robin Bron <robin@finwo.nl> -\ No newline at end of file + - Robin Bron <robin@finwo.nl> + +routes: + rest_proxy: + type: rest + path: ^\/(?<resource>[a-z\/]+)(\.(?<extension>[a-z]+))?$ +# controller: Finwo\RestProxy:Rest:get + method: GET + defaults: + extension: json +\ No newline at end of file diff --git a/src/Finwo/Framework/Application.php b/src/Finwo/Framework/Application.php @@ -67,6 +67,15 @@ class Application } $this->container->set('config', $config); + // Transform routes into route objects, for easy usage + $routes = array(); + foreach ($this->container->get('config.routes') as $name => $route) { + $routes[] = $route = new Route($name, $route); + $route->map( array_merge($_SERVER, $_REQUEST) ); + + } + $this->container->set('config.routes', $routes); + // Check if we can do something useful with the application $app = $this->getApplicationObject( $this->container->get('config.application') ); if ($app === false) { @@ -111,6 +120,80 @@ class Application return $this->app->launch(); } - return 'tadaa'; + // Check if we match any known routes + $routes = $this->container->get('config.routes'); + /** @var Route $route */ + $route = @array_shift(array_filter($this->container->get('config.routes'), function(Route $route) { + return $route->match(); + })); + + // Start known route if possible + if (!is_null($route)) { + + // Fetch the controller + $callable = $this->routeToCallable($route); + + var_dump($route, $callable); + die(); + + // Search for the appropriate controller + + } + + var_dump($route); + die(get_class($this)); + } + + protected function routeToCallable( Route $route ) + { + @list( $namespace, $controller, $method ) = explode(':', $route->getController()); + + // Pre-fetch uri, we might need to work with it + $uri = explode('/', trim($route->getRequestUri(), '/')); + + // Auto-detect namespace if needed + if (is_null($namespace) || !strlen($namespace)) { + $ownClass = explode('\\', get_class($this)); + array_pop($ownClass); + $namespace = implode('\\', $ownClass); + } + + // Add "Controller" to the namespace + $namespace .= '\\Controller'; + + // Check if the controller exists + if(!class_exists(sprintf("%s\\%sController", $namespace, $controller))) { + + // Try to fetch from uri + if(count($uri) && class_exists(sprintf("%s\\%sController", $namespace, ucfirst($uri[0])))) { + $controller = ucfirst(array_shift($uri)); + } + + // Try the defaultcontroller + if(!strlen($controller) && class_exists(sprintf("%s\\DefaultController", $namespace))) { + $controller = 'Default'; + } + + if(!strlen($controller)) { + // Too bad, no controller found + throw new \Exception('No proper controller found'); + } + } + + // Merge fields into full controller class name + $controller = sprintf("%s\\%sController", $namespace, $controller); + + // Fetch proper method + + // But first, debugging + if(method_exists($controller, 'indexAction')) { + die('VICTORY!!'); + } else { + die('FAILURE'); + } + + var_dump($namespace, $controller, $method); + var_dump($actualController); + return null; } } \ No newline at end of file diff --git a/src/Finwo/Framework/RestController.php b/src/Finwo/Framework/RestController.php @@ -0,0 +1,8 @@ +<?php + +namespace Finwo\Framework; + +class RestController extends Controller +{ + +} +\ No newline at end of file diff --git a/src/Finwo/Framework/Route.php b/src/Finwo/Framework/Route.php @@ -0,0 +1,295 @@ +<?php + +namespace Finwo\Framework; + +use Finwo\Datatools\Mappable; + +class Route extends Mappable +{ + // Custom/matching values + protected $type = 'default'; + protected $name; + protected $host; + protected $path; + protected $method; + protected $controller; + protected $defaults; + protected $prefix; + + // After-parse values + protected $parameters; + + // Request info + protected $requestUri = ''; + protected $requestMethod = ''; + protected $httpHost = ''; + + public function __construct($name, $config) + { + $this->name = $name; + parent::__construct($config); + } + + public function match() + { + // If this function gets called, process the request.. No sooner + + // Host match + if (!is_null($this->host) && !preg_match('/' . $this->host . '/i', $this->httpHost)) { + return false; + } + + // Method match + if (!is_null($this->method) && !preg_match('/' . $this->method . '/i', $this->requestMethod)) { + return false; + } + + // Handle path prefix + if(strlen($this->prefix)) { + if( substr($this->requestUri, 0, strlen($this->prefix)) == $this->prefix ) { + $this->requestUri = substr($this->requestUri, strlen($this->prefix)); + } else { + return false; + } + } + + // Parse the path + $parsed = array_merge(array( + 'path' => '/', + 'query' => '' + ), parse_url($this->requestUri)); + if (!is_null($this->path) && !preg_match('/' . $this->path . '/i', $parsed['path'], $this->parameters)) { + return false; + } + + // Strip parameters of numeric keys + foreach ($this->parameters as $key => $parameter) { + if (is_int($key)) { + unset($this->parameters[$key]); + } + } + + // Parse the query + parse_str($parsed['query'], $matches); + + $this->parameters = array_merge((array)$this->defaults, $this->parameters, $matches); + + return true; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * @param string $type + * @return Route + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * @return null + */ + public function getName() + { + return $this->name; + } + + /** + * @param null $name + * @return Route + */ + public function setName($name) + { + $this->name = $name; + return $this; + } + + /** + * @return mixed + */ + public function getHost() + { + return $this->host; + } + + /** + * @param mixed $host + * @return Route + */ + public function setHost($host) + { + $this->host = $host; + return $this; + } + + /** + * @return mixed + */ + public function getPath() + { + return $this->path; + } + + /** + * @param mixed $path + * @return Route + */ + public function setPath($path) + { + $this->path = $path; + return $this; + } + + /** + * @return mixed + */ + public function getMethod() + { + return $this->method; + } + + /** + * @param mixed $method + * @return Route + */ + public function setMethod($method) + { + $this->method = $method; + return $this; + } + + /** + * @return mixed + */ + public function getController() + { + return $this->controller; + } + + /** + * @param mixed $controller + * @return Route + */ + public function setController($controller) + { + $this->controller = $controller; + return $this; + } + + /** + * @return mixed + */ + public function getDefaults() + { + return $this->defaults; + } + + /** + * @param mixed $defaults + * @return Route + */ + public function setDefaults($defaults) + { + $this->defaults = $defaults; + return $this; + } + + /** + * @return mixed + */ + public function getPrefix() + { + return $this->prefix; + } + + /** + * @param mixed $prefix + * @return Route + */ + public function setPrefix($prefix) + { + $this->prefix = $prefix; + return $this; + } + + /** + * @return string + */ + public function getRequestUri() + { + return $this->requestUri; + } + + /** + * @param string $requestUri + * @return Route + */ + public function setRequestUri($requestUri) + { + $this->requestUri = $requestUri; + return $this; + } + + /** + * @return string + */ + public function getRequestMethod() + { + return $this->requestMethod; + } + + /** + * @param string $requestMethod + * @return Route + */ + public function setRequestMethod($requestMethod) + { + $this->requestMethod = $requestMethod; + return $this; + } + + /** + * @return string + */ + public function getHttpHost() + { + return $this->httpHost; + } + + /** + * @param string $httpHost + * @return Route + */ + public function setHttpHost($httpHost) + { + $this->httpHost = $httpHost; + return $this; + } + + /** + * @return mixed + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * @param mixed $parameters + * @return Route + */ + public function setParameters($parameters) + { + $this->parameters = $parameters; + return $this; + } +} +\ No newline at end of file diff --git a/src/Finwo/RestProxy/Controller/DefaultController.php b/src/Finwo/RestProxy/Controller/DefaultController.php @@ -2,7 +2,9 @@ namespace Finwo\RestProxy\Controller; -class DefaultController +use Finwo\Framework\Controller; + +class DefaultController extends Controller { public function indexAction() { diff --git a/src/Finwo/RestProxy/Controller/RestController.php b/src/Finwo/RestProxy/Controller/RestController.php @@ -0,0 +1,13 @@ +<?php + +namespace Finwo\RestProxy\Controller; + +use Finwo\Framework\RestController as BaseController; + +class RestController extends BaseController +{ + public function indexAction() + { + return false; + } +} +\ No newline at end of file diff --git a/src/Finwo/RestProxy/Document/Config.php b/src/Finwo/RestProxy/Document/Config.php @@ -0,0 +1,10 @@ +<?php + +namespace Finwo\RestProxy\Document; + +use Finwo\Datatools\Mappable; + +class Config extends Mappable +{ + +} +\ No newline at end of file diff --git a/src/Finwo/RestProxy/RestProxy.php b/src/Finwo/RestProxy/RestProxy.php @@ -6,8 +6,5 @@ use Finwo\Framework\Application; class RestProxy extends Application { - public function launch() - { - die(__CLASS__); - } + } \ No newline at end of file