Giter Site home page Giter Site logo

rest's Introduction

Respect\Rest

Build Status Code Coverage Latest Version Total Downloads License

Thin controller for RESTful applications and APIs.

  • Very thin and lightweight.
  • Don't try to change PHP, small learning curve.
  • Completely RESTful, the right way to build apps.

Table of contents

rest's People

Contributors

augustohp avatar carusogabriel avatar casimiroarruda avatar danielcosta avatar edinella avatar eduardomarcate avatar filhodanuvem avatar fusselwurm avatar grizmar avatar hellochrisbrown avatar henriquemoody avatar kinncj avatar kleberhs007 avatar lleitep3 avatar nickl- avatar pablolmiranda avatar ramsey avatar rawebone avatar rogeriopradoj avatar silverwolfx10 avatar sokolnikov911 avatar thiagophx avatar tybulewicz avatar wesleyvicthor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rest's Issues

On hypermedia

@alganet on #php-respect 20120711

dunno yet I'd like to see $router->any('/messages/*')->linkTo($mailboxRoute);
something between the route objects
but I'm not sure about the API

PHP Fatal error: Function name must be a string

As an example, the given code provided by @ramsey.

<?php
/**
 * In PHP 5.4.0, this works perfectly. In PHP 5.3.3, it creates a fatal error:
 *
 *     PHP Fatal error:  Function name must be a string
 */


class Foo
{
    public function getBar($bar)
    {
        return $bar;
    }
}

$foo = new Foo();

$methodCall = array($foo, 'getBar');

if (is_callable($methodCall)) {
    echo $methodCall('bar');
}

Consider setting 403 Forbidden on failed authBasic()

Consider the following code example using the authBasic() routine:

<?php
$r3 = new \Respect\Rest\Router();

$r3->get('/', function() {
    echo 'Hello';
})->authBasic('My Realm', function($user, $pass) {
    return $user === 'admin' && $pass === 'pass';
});

When I query this without providing basic auth headers, I get the correct 401 Authorization Required response that I expect:

HTTP/1.1 401 Authorization Required
Date: Tue, 15 May 2012 22:55:38 GMT
Server: Apache/2.2.20 (Ubuntu)
X-Powered-By: PHP/5.4.0-3~oneiric+4
WWW-Authenticate: Basic realm="My Realm"
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html

However, if I do provide authentication headers, but the username and password are incorrect, causing the authBasic() routine to return false, then I get back a 200 OK response with no content.

HTTP/1.1 200 OK
Date: Tue, 15 May 2012 22:57:08 GMT
Server: Apache/2.2.20 (Ubuntu)
X-Powered-By: PHP/5.4.0-3~oneiric+4
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html

There is no security concern here, since you are properly blocking the client from receiving the content, but the 200 OK doesn't seem appropriate. Perhaps a 403 Forbidden is more appropriate by default, or we can continue to leave it up to the application developer.

Here's an example of how I'm accomplishing this right now:

<?php
$r3 = new \Respect\Rest\Router();

$r3->get('/', function() {
    echo 'Hello';
})->authBasic('My Realm', function($user, $pass) {
    if ($user === 'admin' && $pass === 'pass') {
        return true;
    } else {
        header('HTTP/1.1 403 Forbidden');
        return false;
    }   
});

Automatically set Content-Type header when an Accept is matched

Assuming I have the following route defined:

<?php
$r3->get('/', 'MyClass')->accept(array(
    'application/json' => 'json_encode',
));

When it sends the content back to the client, the Content-Type header is still using PHP's default type of text/html (or whatever is defined as default in your php.ini). If I manually set the header() in MyClass::get(), then I can return application/json as the Content-Type, but if I have multiple types I want to accept (i.e. application/xml), then this won't work.

Please consider automatically setting the Content-Type header to the appropriately matched Accept type.

Can't override Accept routine

If I have something like that

public function testAccept()
{
$this->object->always('Accept', array('application/json' => function($data) {
return 'ha';
}));
$request = new Request('get', '/users/alganet');
$_SERVER['HTTP_ACCEPT'] = 'application/json';
$this->object->get('/users/*', function() {
return range(0, 10);
})->accept(array('application/json' => function ($d)
{
var_dump($d);
}));
$r = $this->object->dispatchRequest($request)->response();
$this->assertEquals(json_encode(range(0, 10)), $r);
}

The always accept is execute before the accept of the route.
In my opinion, olny the route accept shloud be run, not both.

Routine for view rendering

A routine that can map routes to specific rendering engines (such as template engines or serializers).

Overload POST to support PUT/DELETE with _method query string parameter

Some clients don't support PUT or DELETE very well. For these cases, consider reading the optional "_method" query string parameter and supporting "PUT" and "DELETE" values only if the current HTTP method is POST. The routing should work exactly as if the client had used the HTTP PUT or DELETE methods.

See page 451 of RESTful Web Services by Richardson and Ruby for reference on "Overloading POST."

Using a by (before) approach?

What is the difference in using the by approach versus just putting the code in the beginning of the route? What would be better is being able to register a by routine and have it apply to all routes. These two approaches shown below work the same way.

$r1 = new Router;

$r1->get('/alert/key/*', function($keyValue) {
        $status = new AlertStatus();
        return $status->getStatus(Config::$alertMsgFileXml);
})->by(function($keyValue) {
    $users = new Users(Config::$alertUserListXml,$keyValue);
    if (!$users->isKeyValid()){
        header('HTTP/1.1 403 Forbidden');
        return "get out of here";
    }
});

// the above works the same way as below
$r1->get('/alert/key/*', function($keyValue) {
    $users = new Users(Config::$alertUserListXml,$keyValue);
    if (!$users->isKeyValid()){
        header('HTTP/1.1 403 Forbidden');
        return "get out of here";
    }
    $status = new AlertStatus();
    return $status->getStatus(Config::$alertMsgFileXml);
});

Thanks
Eric Palmer

Class routes: interpret optional parameters

When you register a route, you can have optional parameters, like /users/*, if you declare in the function that the parameter is optional, than if none is given the route matches and is dispatched. This doesn't happen with classes used as routes. #sadpanda

Direct PHP stream output

As a feature seen and described in codeguy/Slim#205, a possible usage:

<?php
$r3->get('/text/*', function($filename) {
    return fopen('data/'.$filename, 'r+');
})->acceptEncoding(array(
    'deflate' => function($stream) {
        stream_filter_append($stream, 'zlib.deflate', STREAM_FILTER_READ);
        return $stream; //now deflated on demand 
    }
));

Implement conditional requests: If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since and Last-Modified

This feature is dependent on the implementation of the ETag see #40

Implement capabilities required for conditional requests:

Because these requests require knowledge of the actual response and to prevent us having to re-compose the response for every question this will benefit considerably from a server side cache solution as suggested in #60

Did I miss anything?

What are your thoughts, suggestions, special requirements? Do you know of any current implementations we might benefit from referencing? Warnings? Concerns? Are you able to help?

Get involved and you can also be part of making Respect/Rest even more awesome than it is, there is more than enough ways for you to help, feel free to contact any of the Respect developers if you need help getting involved!

Also a big thank you to our current supporters you guys rock! Keep up the good work!

Better header checks

Our tests are messy, declaring header functions everywhere, as of PHP 5.4 we can use http_response_code function to check headers and xdebug_get_headers together to check for HTTP header changes on our tests.

Implementing our own header abstraction would pose work without much benefit - other than having better tests.

  • Move version constraint to PHP 5.4 on composer.json (we could go higher).
  • Implement assertHttpStatusCode assertion.
  • Implement assertHeaderContains assertion.

Original post

Issues #18 and #25 showed we need to manipulate the HTTP header sometimes, despite the correction of the issues we should implement some way to handle header manipulation in a way that fits inside the Respect/Rest/Router and feels right.

"How we are going to do that?" is the question that this issue should fix, hopefully with a nice and sweet push =D

$router->autoDispatched = false has no effect

This was identified on a improvised mini-workshop session with @marcelonovaes and @knorrium.

We were developing on Mac OS X Lion using the bundled PHP 5.3.10 and bundled Apache with no php.ini or httpd.conf changes. Setting $router->autoDispatched = false had no effect at all, dispatching the router anyway. I have no idea why yet.

Route matching

Hey mate, how is it going?

I think I may have found a bug.

Check it out.
The method AbstractRoute::match(), does not use the Accept to check whether or not the route is correct.

Example

<?php

$router = new Router();
$router->get('/images', 'MyApp\Controller\ImageJson')->accept(array('application/json' => $jsonHandler));
$router->get('/images', 'MyApp\Controller\ImageHtml')->accept(array('text/html' => $htmlHandler));

In this example, if you have an Accept: text/html,application/json, it'll always use the first route.

Command line routing and routines

We could create a CliRequest that when injected into the Router instead of the traditional Request could route things via Cli calls. Bash and linux are somewhat RESTful. An experimental mocked cli request is in the Router test suite for a long time now, but it isn't very friendly for users.

Considering a $r->get('/users/*', 'MyUsersController') sample route, both a HTTP GET /users/alganet and a php application.php get users alganet cli route should route to the same point. Custom route verbs could be used, such as $r->install('/', 'MyInstallController');.

Much of the code from the current Request class would be moved to an AbstractRequest that would be extended to both Request and CliRequest.

Unit Tests

We currently don't have real unit tests, our tests are more functional/BBDish. I'm gonna write the proper units and keep the old tests as legacy, already started!

Implement server-side response cache

This is a topic I've been burning to raise but there are still features required that takes a higher priority than this. Since the RESTful API architecture involves extensive CACHE considerations there is not much need to further motivate the benefit of having a properly implemented CACHE solution at the end-point, aside from the obvious performance and load shedding advantages, to be able to verify and test conformance of the developed REST implementation without the need for external CACHE providersp

It is only until now that we are discussing conditional requests that this has become pertinent as the framework will see a huge benefit if it is able to cache and make request provisioning decisions based on cached variants rather than re-requesting the Routers to populate a response on every request. for state information.

2616 allows for ETag to be used as an "opaque" identifier instead of dates:

The ETag response-header field value, an entity tag, provides for an "opaque" cache validator. This might allow more reliable validation in situations where it is inconvenient to store modification dates, where the one-second resolution of HTTP date values is not sufficient, or where the origin server wishes to avoid certain paradoxes that might arise from the use of modification dates.

Although I this will not be sufficient as the only identifier and we will benefit from having an additionally indexed key when ETag is not available, based on a calculated checksum of the following HTTP artifacts:
(Of the top of my head this will have to be verified)

  • location

  • accept header

  • method

    In the interim it is safe to speculate that we would consider plug-able cache provisioning utilizing some/all of the following :

  • via file cache - simple and free from dependencies utilizing PHPs file_put/file_get_contents();

  • via PDO as database driven cache

  • via APC provisioned

  • via REDIS provisioned

  • via Memcache provisioned

  • via APC provisioned

  • via Solr provisioned

  • via ElasticSearch provisioned

  • via Reverse Proxy (Squid probably) provisioned (not sure if this is exactly what we have in mind though.

Aside from the obvious requirement that the design should be flexible to easily cater for additions to this list of providers I would additionally see the functionality being transparently exposing an API that can be utilized by other components of the application where this functionality may be required without impacting the core cache.

What are your thoughts?

ETag support

Automatic generation by MD5ing the content. Custom logic can be implemented separately.

ReflectionException when having AbstractAccept routine

When running this piece of code:

<?php

require 'bootstrap.php'; // PSR-0 autoloader in there

class RouteKnowsGet implements \Respect\Rest\Routable {
    public function get($param) {
        return "ok: $param";
    }
}
class RouteKnowsNothing implements \Respect\Rest\Routable {
}

$_SERVER['HTTP_ACCEPT'] = 'application/json';

$router = new \Respect\Rest\Router();
$router->isAutoDispatched = false;

$r1 = $router->any('/meow/*', 'RouteKnowsGet');
$r1->accept(array('application/json' => 'json_encode')); // some routine inheriting from AbstractAccept 

$router->any('/moo/*', 'RouteKnowsNothing');

$out = $router->run(new \Respect\Rest\Request('get', '/meow/blub')); // ReflectionException

echo "I survived! Result is: '$out'\n";

I get the following exception:

PHP Fatal error:  Uncaught exception 'ReflectionException' with message 'Method RouteKnowsNothing::GET() does not exist' in /home/fusselwurm/dev/src/Rest/library/Respect/Rest/Routes/ClassName.php:43
Stack trace:
#0 /home/fusselwurm/dev/src/Rest/library/Respect/Rest/Routes/ClassName.php(43): ReflectionMethod->__construct('RouteKnowsNothi...', 'GET')
#1 /home/fusselwurm/dev/src/Rest/library/Respect/Rest/Request.php(75): Respect\Rest\Routes\ClassName->getReflection('GET')
#2 /home/fusselwurm/dev/src/Rest/library/Respect/Rest/Routes/AbstractRoute.php(102): Respect\Rest\Request->routineCall('when', 'GET', Object(Respect\Rest\Routines\Accept), Array)
#3 /home/fusselwurm/dev/src/Rest/library/Respect/Rest/Router.php(197): Respect\Rest\Routes\AbstractRoute->matchRoutines(Object(Respect\Rest\Request), Array)
#4 /home/fusselwurm/dev/src/Rest/library/Respect/Rest/Router.php(215): Respect\Rest\Router->dispatchRequest(Object(Respect\Rest\Request))
#5 /home/fusselwurm/dev/src/Rest/tests/moo2.php(24): Respect\Rest\Router->run(Object(Respect\R in /home/fusselwurm/dev/src/Rest/library/Respect/Rest/Routes/ClassName.php on line 43

User-agent routine

As seen on fabpot/Silex#183 a routine for asserting User-Agent strings would be quite useful and simple to implement.

<?php
$r3->get('/about', function() {
    return array('v' => 2.0);
})->acceptLanguage(array(
    'en' => function($data) { return array("Version" => $data['v']); },
    'pt' => function($data) { return array("Versão"  => $data['v']); }
))->userAgent(array(
    'Songbird (\d\.\d)[\d\/]*?'=>function($data) { return $data; },
    '(msie) ([\w.]+)' => function($data) { return $data; },
    '(mozilla)(?:.*? rv:([\w.]+))?' => function($data) { return $data; }
    '*' => function($data) { return false; } // Don't respond for any other userAgent
));

Implement TODOs

As noted in RequestTest see @76230e77928d9a6ebbae6977aaf02edf4cdf45a2

//TODO change ->uri to ->path, populate other parse_url keys
//TODO same behavior for env vars and constructor params regarding parse_url

namepsace issue?

PHP 5.3.9 ZendServer 5.6
installed via pear

<?php
echo get_include_path();
use Respect\Rest\Router;

$r3 = new Router;

$r3->get('/', function() {
    return 'Hello World';
    }

);

include_path is
.:/usr/local/zend/share/ZendFramework/library:/usr/local/zend/share/pear

Error reported is
.:/usr/local/zend/share/ZendFramework/library:/usr/local/zend/share/pear

I did verify that Respect/... is installed in /usr/local/zend/share/pear

Thanks for your help.

RateLimit Routine

A routine that receives an IP address and must return false if not being rate-limited or an integer with number of seconds to retry. Implement 429 status code as well.

binding controller classes

Currently binding controller classes like below:

$r3->any('/', 'HomeController');

causes fatal errors. Its not indicated in the README that these classes should implement interface Routable.
Had to go deeply through the code to figure that out. Please update the README or set an option for users to choose
whether they want it this way.

"Always" routine assignment only accepts one parameter

This was identified on a improvised mini-workshop session with @marcelonovaes and @knorrium.

Routines in Respect\Rest are abstracted in routine classes. The magic builder that allows you to create them and assign them to Route instances like $route->foo($param) leading to $route->appendRoutine(new Routines\Foo($param)) currently accepts just one parameter, so $route->bar($param, $other) actually leads to an inconsistent $route->appendRoutine(new Routines\Bar($param), without the second argument.

This bug was introduced back when we created the first routine with two parameters. I believe it was the AuthBasic one. Fix should be simple.

Hierarchical Routing

Routes inside routes respect their parents patterns by concatenating them. Parents acts as hubs:

<?php

$router = new Respect\Rest\Router;

$router->any('/users/*', function($username=null) {
    return showMyUserPlease($username);
})->children(
    $router->any('/lists', function($username=null) {
        return showMyUserLists($username);
    })
);

Sample above would match /users/alganet and /users/alganet/lists and route each url to its proper children.

Children could be reused:

<?php

$router = new Respect\Rest\Router;

$listsRoute = $router->any('/lists', function($username=null) {
    return showMyUserLists($username);
}

$router->any('/users/*', function($username=null) {
    return showMyUserPlease($username);
})->children($listsRoute);


$router->any('/admins/*', function($username=null) {
    return showMyUserPlease($username);
})->children($listsRoute);

A new empty route type could be created to be just a namespace for other routes:

<?php

$router = new Respect\Rest\Router;

$router->any('/users/*')->children(
    $router->any('/lists', function($username=null) {
        return showMyUserLists($username);
    }),
    $router->any('/followers', function($username=null) {
        return showFollowers($username);
    })
);

Sample above will match /users/alganet/lists and /users/alganet/followers, but will not match just /users/alganet.

Required parameters evaluating as optional

I created a route that looks like this:

/accounts/*/catalogs/*

According to the documentation, that first asterisk is not an optional parameter. However, requests to /accounts/catalogs is matching on that. Shouldn't it be giving me a 404 or something?

Reproduction script:

<?php

include '../vendor/autoload.php';

$r3 = new \Respect\Rest\Router();

$r3->get('/accounts/*/catalogs/*', function($accountId, $catalogId = null) {
    echo "Account ID: {$accountId}, Catalog ID: {$catalogId}";
});

Request:

GET /accounts/catalogs HTTP/1.1
Host: localhost:8181
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Accept-Encoding: identity, deflate, compress, gzip
Accept: */*
User-Agent: HTTPie/0.1.7-dev

Response:

HTTP/1.1 200 OK
Date: Thu, 10 May 2012 17:39:41 GMT
Server: Apache/2.2.20 (Ubuntu)
X-Powered-By: PHP/5.4.0-3~oneiric+4
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 42
Content-Type: text/html

Account ID: , Catalog ID: 

Incorrect documentation

The documentation suggests in Controller splitting that you may log the request path like such:

<?php
    $logRoutine = function() use ($myLogger, $r3) {
        $myLogger->logVisit($r3->request->path);
    };

    $r3->any('/users', 'UsersController')->by($logRoutine);
    $r3->any('/products', 'ProductsController')->by($logRoutine);

But Router does not expose the request neither does request expose any path, request does have the uri exposed as public though.

This is an intuitive approach to this common use case, I suggest we adjust the source code to reflect the documentation.

Combine the Accept Headers and handle as one

After looking into 2295 and 2296 it has become evident that we cannot treat these headers separately when doing coneg.

For example the link lists returned, the "q" value calculations and in a broader sense any part of analyzing and handling these headers are done as a whole and not in isolation. You don't respond to the content type of the Accept header alone, you also consider the language, encoding, features etc.

Will we not better be served if we combine these headers instead of treating them like any other header?

Example concern, but everything else is the same really:

16.1 Computing overall quality values

As a first step in the local variant selection algorithm, the overall qualities associated with all variant descriptions in the list are computed.

The overall quality Q of a variant description is the value

Q = round5( qs * qt * qc * ql * qf * qa )

where rounds5 is a function which rounds a floating point value to 5 decimal places after the point. It is assumed that the user agent can run on multiple platforms: the rounding function makes the algorithm independent of the exact characteristics of the underlying floating point hardware.

The factors qs, qt, qc, ql, qf, and qa are determined as follows.

  • qs Is the source quality factor in the variant description.
  • qt The media type quality factor is 1 if there is no type attribute in the variant description. Otherwise, it is the quality value assigned to this type by the configuration database. If the database does not assign a value, then the factor is 0.
  • qc The charset quality factor is 1 if there is no charset attribute in the variant description. Otherwise, it is the quality value assigned to this charset by the configuration database. If the database does not assign a value, then the factor is 0.
  • ql The language quality factor is 1 if there is no language attribute in the variant description. Otherwise, it is the highest quality value the configuration database assigns to any of the languages listed in the language attribute. If the database does not assign a value to any of the languages listed, then the factor is 0.
  • qf The features quality factor is 1 if there is no features attribute in the variant description. Otherwise, it is the quality degradation factor computed for the features attribute using the feature set of the current request.
  • qa The quality adjustment factor is 0 if the variant description lists a media type - charset combination which is `forbidden' by the table, and 1 otherwise.

As an example, if a variant list contains the variant description

{"paper.2" 0.7 {type text/html} {language fr}}

and if the configuration database contains the quality value assignments

types:     text/html;q=1.0, type application/postscript;q=0.8
languages: en;q=1.0, fr;q=0.5

then the local variant selection algorithm will compute the overall quality for the variant description as follows:

{"paper.2" 0.7 {type text/html} {language fr}}
            |           |                 |
            |           |                 |
            V           V                 V
  round5 ( 0.7   *     1.0        *      0.5 ) = 0.35000

With same configuration database, the variant list

{"paper.1" 0.9 {type text/html} {language en}},
{"paper.2" 0.7 {type text/html} {language fr}},
{"paper.3" 1.0 {type application/postscript} {language en}}

would yield the following computations:

 round5 ( qs  * qt  * qc  * ql  * qf  * qa ) = Q
          ---   ---   ---   ---   ---   ---
paper.1:  0.9 * 1.0 * 1.0 * 1.0 * 1.0 * 1.0  = 0.90000
paper.1:  0.7 * 1.0 * 1.0 * 0.5 * 1.0 * 1.0  = 0.35000
paper.3:  1.0 * 0.8 * 1.0 * 1.0 * 1.0 * 1.0  = 0.80000

Router throwing exception in __destruct

As written in the php documentation "Attempting to throw an exception from a destructor (called in the time of script termination) causes a fatal error."
Router.php destructor throws an exception when theres an error. This causes a very unhelpful fatal error message:
"Fatal error: Exception thrown without a stack frame in Unknown on line 0"

Fixed it by wrapping it in a try-catch block

if (!$this->autoDispatched || !isset($_SERVER['SERVER_PROTOCOL']))
    return;

try {
    $response = $this->dispatch();
    if ($response)
        echo $response->response();
} catch (\Exception $e) {
    echo $e->getTraceAsString(); //or something more meaningful instead
}

is_callable vs function/method_exists

Busy fixing the tests after reintroducing the factory params needing an example that can take string, array as arguments I thought awesome ArrayObject will do the trick but lo and behold, for some weird and wonderful reason 'ArrayObject" 'offsetSet' is not callable, even though it works on the instance and method_exists sees it to be so. Strange?

var_export(method_exists('ArrayObject', 'offsetSet'));
// output: true
var_export(is_callable(array(new ArrayObject, 'offsetSet')));
// output: true
var_export(is_callable(array('ArrayObject', 'offsetSet')));
// output: false

Performance is also an issue as bob at thethirdshift dot net will tell you on PHP.net
Benchmark results:

Did 10000 is_callables in 0.0640790462494 seconds
Did 10000 function_exists in 0.0304429531097 seconds

We would have to do a combination of is_array, function_exist, method_exist; and then produce the benchmarks to see how it would affect us but if it fails in this example where else would it be mistaken?

Route forwarding

Forward to another route by instance:

<?php

$router = new Respect\Rest\Router;

$foo = $router->any('/foo', function() {
    return array('alganet', 'php', 'respect');
});

$bar = $router->any('/bar', function() use($foo) {
    if ($baz)
        return 'Hi';
    else
        return $foo;
});

When a route is returned inside another route, the framework should use it as a forward (internal, without http redirects). On any(), the method should be the same originated in the request.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.