Code Monkey home page Code Monkey logo

apix's Introduction

APIx, RESTful services for PHP Build Status

Latest Stable Version Build Status Code Quality Code Coverage License

APIx is a (micro-)framework to build RESTful Web services. It will run alognside your existing framework/application with minimum fuss.

Some of its features:

  • Supports many data inputs such as GET/POST parameters, XML, JSON, CSV, ...
  • Provides various output representation such as XML, JSONP, HTML, PHP, ...
  • Provides on-demand resources documention, using GET /help or 'OPTIONS'.
  • Uses annotations to document and set service behaviours.
  • Handles most HTTP methods, including PUT, DELETE, HEAD, OPTIONS and PATCH (TRACE to some extend).
  • Bundle with many plugins and adapters for Authentification and ACL, caching...
  • Follows the standards such as rfc2616 rfc2616, rfc2617 rfc2617, rfc2388 rfc2388, rfc2854 rfc2854, rfc4627 rfc4627, rfc4329 rfc4329, rfc2046 rfc2046, rfc3676 rfc3676, rfc3023 rfc3023, etc...
  • Provides method-override usign X-HTTP-Method-Override (Google recommendation) and/or using a query-param (customisable).
  • Supports content negotiation (which can also be overriden).
  • Take advantages of network caches -- supports HEAD test.
  • Available as a standalone PHAR file, or via Composer or as a PEAR pear package.
  • Continuous integration against PHP 5.x, and 7.x.
  • Read the documentation!

Todo:

  • Self-generated API resources testing.
  • Add support for WSDL 2.0 / WADL.
  • Eventually SOAP (and XML_RPC) bridging.

Feel free to comment, send pull requests and patches...

Basic usage

<?php
    require 'apix.phar';

    // Instantiate the server (using the default config)
    $api = new Apix\Server;

    // Create a GET handler $name is required
    $api->onRead('/hello/:name', function($name) {
        return array('Hello ' . $name);
    });

    $api->run();

Another example using annotations.

    // $type and $stuff are required parameters.
    // $optional is not mandatory.
    $api->onRead('/search/:type/with/:stuff/:optional',
        /**
         * Search for things by type that have stuff.
         *
         * @param     string  $type         A type of thing to search upon
         * @param     string  $stuff        One or many stuff to filter against
         * @param     string  $optional     An optional field
         * @return    array
         * @api_auth  groups=clients,employes,admins users=franck,jon
         * @api_cache ttl=12mins tags=searches,indexes
         */
        function($type, $stuff, $optional = null) {
            // some logic
            return $results;
        }
    );

    $api->run();

Advanced usage

Routing

A route defines the path to a resource, once matched the corresponding resource's controller and dedicated handlers are invoked.

Any returned value emanating from a resource's controller, generally an associative array, will become the main subject of the response.

Essentially, a route is made of:

  1. A route controller that corresponds to a HTTP header method:
    onCreate()   ->   POST          |        onModify()   ->   PATCH
    onRead()     ->   GET           |        onHelp()     ->   OPTIONS
    onUpdate()   ->   PUT           |        onTest()     ->   HEAD
    onDelete()   ->   DELETE        |        onTrace()    ->   TRACE
  1. A route path corresponding to a Request-URI.
    • It may represent a specific and static resource entity, such as:
      /search/france/paris
    • It may also be dynamic, and may include one or many variables indicated by a colon :, such as:
      /search/:country/:city

Controller definitions

A resource controller may be declared as either:

  • a public method from some user defined classes,
  • a closure/lambda function, defined at runtime (Sinatra style).

It will use:

  • variable name to inherit values from the route's path, e.g. $name inherited from /category/:name.

  • type hinting to inject any of the current scope Apix's objects, e.g. Request, Response, etc...

    See Apix's own [Documentation] apixdoc for what's available.

Here is an example showing these in context:

    $api->onRead('/category/:name', function(Request $request, $name) {

        // retrieve a named param
        $page = (int) $request->getParam('page');

        // retrieve the body params, parsed from XML, JSON, ...
        $params = $request->getBodyParams();

        ...

        return $list_defs;
    });

Configuration

Check the inline comments in the config.dist.php file shipped with the distribution.

Bootstrap

To boostrap an Apix server, add the required file and create an instance of the Apix\Server.

A dedicated configuration file can be injected to an Apix server:

    <?php
        require 'apix.phar';

        $api = new Apix\Server(require 'my_config.php');

        $api->run();

PHAR Console

Apix PHAR distribution contains a built-in console. Try invoking the api.phar file on the command line as follow:

$ php apix.phar --help

Web server configuration

Use one of the vhost file provided within the distribution and follow the relevant instructions provided in the comments to set your web server environement.

TODO: Add ngynx and lighttpd files to the distrib.

Annotations

Annotations can be used to define many aspects of a resource entity.

Here is a self explanatory example:

    <?php
        $api->onRead('/download/:app/version/:version',
            /**
             * Retrieve the named sotfware
             * Anyone can use this resource entity to download apps. If no
             * version is specified the latest revision will be returned.
             *
             * @param     string    $app        The name of the app
             * @param     string    $version    The version number.
             * @return    array     A response array.
             *
             * @api_auth  groups=public
             * @api_cache ttl=1week tags=downloads
             */
            function($app, $version=null) {
                // ...
                return array(
                    $app => 'the version string of software.'
                );
            }
        );

        $api->onCreate('/upload/:software',
            /**
             * Upload a new software
             * Admin users use this resource entity to upload new software.
             *
             * @param      Request  $request   The Server Request object.
             * @param      string   $software
             * @return     array    A response array.
             *
             * @api_auth   groups=admin users=franck
             * @api_cache  purge=downloads
             */
            function(Request $request, $software) {
                // ...
            }
        );

        $api->run();

Installation

Apix requires PHP 5.3 or later.

  • [Phar file] phar (recommended)

  • If you are creating a component that relies on Apix locally:

    • either update your composer.json file:

      {
        "require": {
          "apix/apix": "0.3.*"
        }
      }
    • or update your package.xml file as follow:

    <dependencies>
      <required>
        <package>
          <name>apix_server</name>
          <channel>pear.ouarz.net</channel>
          <min>1.0.0</min>
          <max>1.999.9999</max>
        </package>
      </required>
    </dependencies>
  • For a system-wide installation using PEAR:
    sudo pear channel-discover pear.ouarz.net
    sudo pear install --alldeps ouarz/apix

For more details see pear.ouarz.net.

Testing

To run the unit test suite simply run phpunit from within the main dir.

Integration and functional tests are also available in the src/tests.

License

APIx is licensed under the New BSD license -- see the LICENSE.txt for the full license details.

  _|_|    _|_|    _|     _|      _|
_|    _| _|    _|         _|    _|
_|    _| _|    _| _|        _|_|
_|_|_|_| _|_|_|   _| _|_|   _|_|
_|    _| _|       _|      _|    _|
_|    _| _|       _|     _|      _|

apix's People

Contributors

frqnck avatar jspalink avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

apix's Issues

403 “Not a valid CORS request.”

It is (probably) not strictly correct for the CORS plugin to return a 403 “Not a valid CORS request.”.
The Web browser really should make that decision rather than the API?
Although, this 403 is currently serving us well and may deter the ‘scrapping’ kids…

TODO: Check against https://www.w3.org/TR/cors/

Maybe make this an optional feature?

Somehow that 403 may affect JSONP request, legacy browser probably don’t follow same origin policy anyway. Currently, JSONP requests require to disable the CORS plugin (using the _no_cors param).

Error in Apix\Exception

The parameters for Apix\Exception::errorHandler are incorrect. The final parameter $ctx should be \Exception $e, the previous Exception that is passed along with it. As it currently stands, the following error is passed, and can be replicated with the following code:

php > throw new ErrorException("an oops occurred", 400, 0, 'somefile', 10, array());
PHP Fatal error:  Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno  [, Exception $previous = NULL]]]]]]) in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
PHP   2. ErrorException->__construct() php shell code:1

Fatal error: Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno  [, Exception $previous = NULL]]]]]]) in php shell code on line 1

Call Stack:
  336.6461     239752   1. {main}() php shell code:0
  336.6462     240640   2. ErrorException->__construct() php shell code:1

An empty array, BTW, is what is getting passed in, but I'm not sure where from - the error code that I'm seeing doesn't give me a clear indication of where it is. The error code from the API I'm working on looks like this:

Fatal error: Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno  [, Exception $previous = NULL]]]]]]) in /home/jspalink/dev/info-econtext-api/vendor/apix/apix/src/php/Apix/Exception.php on line 36

Call Stack:
    0.0001     239728   1. {main}() /home/jspalink/dev/info-econtext-api/public/index.php:0
    0.0070    1011240   2. Apix\Main->run() /home/jspalink/dev/info-econtext-api/public/index.php:12
    0.0260    1241392   3. Apix\Response->generate() /home/jspalink/dev/info-econtext-api/vendor/apix/apix/src/php/Apix/Main.php:201
    0.0260    1242144   4. Apix\Exception::errorHandler() /home/jspalink/dev/info-econtext-api/vendor/apix/apix/src/php/Apix/Main.php:391
    0.0261    1249280   5. ErrorException->__construct() /home/jspalink/dev/info-econtext-api/vendor/apix/apix/src/php/Apix/Exception.php:36


<h1>500 Internal Server Error</h1>#1 Shutdown:- Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno  [, Exception $previous = NULL]]]]]]) @ /home/jspalink/dev/info-econtext-api/vendor/apix/apix/src/php/Apix/Exception.php:36

Obviously, there is no /apix/apix/src/php/Apix/Main.php:391

Problem in Exception.php with shutdownHandler()

Not sure the best way to fix as I haven't spent any time messing with it yet, but figure you have a good idea of how to solve this. It might be as simple as turning the DEBUG constant here to "false".

If there is an error in an internal function (database query, json_encode, etc) and it is caught and handled appropriately by the user, error_get_last() still returns the error. This means that we can intend to return an appropriate response to the user, but it will have a 500 appended (in HTML) to the response.

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.