2017 © Pedro Peláez
 

library simplerouter

Simple router, mainly for API backends, with CORS support

image

fostam/simplerouter

Simple router, mainly for API backends, with CORS support

  • Wednesday, July 18, 2018
  • by fostam
  • Repository
  • 1 Watchers
  • 1 Stars
  • 42 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 1 Forks
  • 0 Open issues
  • 6 Versions
  • 20 % Grown

The README.md

fostam/simplerouter

Simple PHP router, mainly for building API backends., (*1)

Features

  • Easy configuration
  • Response and error handling
  • Parameter input from URL, GET/POST parameters or JSON payload
  • CORS support

Install

The easiest way to install SimpleRouter is by using composer:, (*2)

$> composer require fostam/simplerouter

Usage

This is how a typical "handler" would look like:, (*3)

<?php

include "vendor/autoload.php";

use Fostam\SimpleRouter\Response;
use Fostam\SimpleRouter\Router;
use Fostam\SimpleRouter\Http;
use Fostam\SimpleRouter\Exception\InternalApiException;
use Fostam\SimpleRouter\Exception\UserApiException;

$router = new Router();
try {
    // all URLs must be prefixed with this string
    $router->setOption(Router::OPT_REQUEST_PATH_PREFIX, '/myproject/api');

    // send permissive cross origin resource sharing headers
    $router->setOption(Router::OPT_CORS_PERMISSIVE, true);

    // by default, send the response with application/json content type
    $router->setOption(Router::OPT_RESPONSE_TYPE_DEFAULT, Response::TYPE_JSON);

    // routes
    $router->createRoute('/users', Http::METHOD_GET, \MyProject\GetUsers::class);
    $router->createRoute('/users/{id}', Http::METHOD_GET, \MyProject\GetUsers::class);
    $router->createRoute('/users', Http::METHOD_POST, \MyProject\CreateUser::class);

    // resolve
    $router->resolve();
}
catch (UserApiException $e) {
    // error messages are automatically passed back as JSON
}
catch (InternalApiException $e) {
    // a generic error message is passed back as JSON; trigger the actual errors
    // (e.g. a failed database query) that should not be publicly visible, but
    // logged internally
    error_log($e);
}

$router->sendResult();

This could be a (very simplified) processor class for getting users:, (*4)

class GetUsers extends Processor {
    public function execute() {
        $userID = $this->getPathParam('id');

        if (!is_numeric($userID)) {
            throw new UserApiException('userID must be a number', Http::CODE_BAD_REQUEST, $e);
        }

        try {
            $data = $this->myUserModel->getUser(intval($userID));
        } catch (\Exception $e) {
            throw new InternalApiException("error getting data for user {$userID}", Http::CODE_INTERNAL_SERVER_ERROR, $e);
        }

        $this->setResponseData(
            [
                'data' => $data
            ]
        );
    }
}

An example class for creating a user:, (*5)

class CreateUser extends Processor {
    public function execute() {
        $data = $this->getJSONPostData();
        if (!isset($data['name'])) {
            throw new UserApiException("parameter 'name' is missing");
        }

        try {
            $userID = $this->myUserModel->createUser($data);
        } catch (\Exception $e) {
            throw new InternalApiException("error creating user", Http::CODE_INTERNAL_SERVER_ERROR, $e);
        }

        // send "201 Created"
        $this->setResponseCode(Http::CODE_CREATED);

        // send the location of the new object as header
        // here: 'Location: /myproject/api/users/123' (for $userID=123)
        $this->getResponseObject()->setLocationPath($this->getPath() . '/' . $userID);
    }
}

Reference

Router

setOption()

Router setOption($option, $value) Set a router option. The router object is returned to allow chaining. Following options are available:, (*6)

Option Value Default Value
Router::OPT_REQUEST_PATH_PREFIX prefix that is truncated from the path ""
Router::OPT_RESPONSE_TYPE_DEFAULT default response type Response::TYPE_HTML
Router::OPT_KEY_ERROR_MESSAGE key in result JSON for error message "error.message"
Router::OPT_KEY_ERROR_CODE key in result JSON for error code "error.code"
Router::OPT_INTERNAL_ERROR_MSG error message text for internal errors "internal server error"
Router::OPT_CORS_PERMISSIVE permissive CORS mode false

addRoute()

Route addRoute(Route $route), (*7)

Add a Route object to the list of routes. For convenience, the route object is returned to allow direct calling of Route methods., (*8)

createRoute()

Route createRoute(string $path, string $method, mixed $processor), (*9)

Creates a Route object from the given parameters, adds it to the list of routes and returns it. See the Route documentation for a description of the parameters., (*10)

resolve()

void resolve(string $path = '', string $method = ''), (*11)

Resolve the given path/method and execute the matching processor. If $path is empty, $_SERVER['SCRIPT_NAME'] is used as path. If $method is empty, $_SERVER['REQUEST_METHOD'] is used as method., (*12)

sendResult()

void sendResult(), (*13)

Sends the result. This include the HTTP status code, HTTP headers (including content type) and the body. Content type header and body format depend on the configured response type., (*14)

getResponseObject()

Response getResponseObject(), (*15)

Get the Response object. The response object represents what is sent when calling sendResult()., (*16)

Route

Constructor

Route __construct(array $config), (*17)

The constructor is the preferred way of creating a route when the route configuration comes from a dynamic source, e.g. from a database., (*18)

It builds a route object with the given associative array $config. The following configuration keys are available:, (*19)

Key Value Mandatory
Route::PATH path used for matching yes
Route::METHOD method used for matching yes
Route::PROCESSOR processor that is executed on a match yes

The path is the endpoint that defines when this route matches. When comparing to the actual path, the Router::OPT_REQUEST_PATH_PREFIX is prefixed, if configured., (*20)

The method is the HTTP method that needs to match along with the path, e.g. Http::METHOD_GET or Http::METHOD_POST., (*21)

If both path and method match, the processor is called. There are three different possibilities to define the processor: - A class name - this is suitable if the class has a constructor without arguments, because the instantiation is done when the class is used - An array consisting of a class name and another array with the constructor parameters - this method can be used when the constructors needs arguments - An object - this is suitable when the processor object is created in advance, (*22)

In either case, the class/object passed is required to extend the abstract Processor class., (*23)

create()

Route ::create(string $path, string $method, mixed $processor), (*24)

Static method to create a Route object from parameters. The create() method is the preferred way of creating a route when the route definitions are hardwired in PHP. Refer to the constructor for a description of the parameters., (*25)

Processor

getPath()

string getPath(), (*26)

Get the path this processor is configured for., (*27)

getMethod()

string getMethod(), (*28)

Get the HTTP method this processor is configured for., (*29)

getResponseObject()

Response getResponseObject(), (*30)

Get the response object that will be used to create the response after the processor has finished., (*31)

setResponseCode()

void setResponseCode(int $code), (*32)

Set the HTTP response code, e.g. Http::CODE_OK (_200_)., (*33)

Shorthand for getResponseObject()->setCode($code)., (*34)

setResponseType()

void setResponseType(string $type), (*35)

Set the HTTP response type, e.g. Response::TYPE_JSON. This can be either one of the TYPE_ constants from the Response class, or any valid MIME type string, e.g. application/xml. If no response type is set, the router will send the default response type (Router::OPT_RESPONSE_TYPE_DEFAULT), if set. If no default is set, text/html is sent., (*36)

Shorthand for getResponseObject()->setType($type)., (*37)

setResponseData()

void setResponseData(mixed $data), (*38)

Set the body data. This can be either an array for the Response::TYPE_JSON response type, or a string for Response::TYPE_HTML or any other response type., (*39)

Shorthand for getResponseObject()->setData($data)., (*40)

getPathParams()

string[] getPathParams(), (*41)

Get all path parameter values as key/values pairs., (*42)

Example:, (*43)

$router->createRoute('/test/{id}/user/{name}', Http::METHOD_GET, Test::class);
$router->resolve('/test/123/user/john', Http::METHOD_GET);

A call to getPathParams() in the Test processor call will return:, (*44)

array(2) {
  'id' =>
  string(3) "123"
  'name' =>
  string(4) "john"
}

getPathParam()

string getPathParam(string $param), (*45)

Get the path parameter value for a single parameter. For the example above, getPathParam('name') would return john., (*46)

getQueryParams()

string[] getQueryParams(), (*47)

Return the query parameters as key/value pairs. This is equivalent to PHP's $_GET superglobal., (*48)

getQueryParam()

string getQueryParam(string $param), (*49)

Get the query parameter value for a single parameter., (*50)

getPostParams()

string[] getPostParams(), (*51)

Return the POST parameters as key/value pairs. This is equivalent to PHP's $_POST superglobal., (*52)

getPostParam()

string getPostParam(string $param), (*53)

Get the POST parameter value for a single parameter., (*54)

getJSONPostData()

mixed getJSONPostData(), (*55)

When the body of a POST, PUT or PATCH call contains a JSON string, it's structure can be retrieved as a PHP array., (*56)

Example:, (*57)

curl 'https://example.com/test' -X POST -d '{"id": 123, "name": "john"}'

A call to getJSONPostData() will return this array:, (*58)

array(2) {
  'id' =>
  int(123)
  'name' =>
  string(4) "john"
}

Response

setCode()

void setCode(int $code), (*59)

Set the HTTP response code, e.g. Http::CODE_OK (_200_)., (*60)

getCode()

int getCode(), (*61)

Get the current response code., (*62)

setType()

void setType(string $type), (*63)

Set the HTTP response type, e.g. Response::TYPE_JSON. This can be either one of the TYPE_ constants from the Response class, or any valid MIME type string, e.g. application/xml. If no response type is set, the router will send the default response type (Router::OPT_RESPONSE_TYPE_DEFAULT), if set. If no default is set, text/html is sent., (*64)

getType()

int getType(), (*65)

Get the current response code., (*66)

setData()

void setData(mixed $data), (*67)

Set the body data. This can be either an array for the Response::TYPE_JSON response type, or a string for Response::TYPE_HTML or any other response type., (*68)

getData()

mixed getData(), (*69)

Get the current data., (*70)

setLocationPath()

void setLocationPath(string $path), (*71)

Set a location path. This path prefixed with Router::OPT_REQUEST_PATH_PREFIX, if set, and then sent as Location header., (*72)

Example:, (*73)

$router->setOption(Router::OPT_REQUEST_PATH_PREFIX, '/test/api');
...
$this->getResponseObject->setLocationPath('/users');
...
Location: /test/api/users

getLocationPath()

string getLocationPath(), (*74)

Get the location path., (*75)

setHeader()

void setHeader(string $header, string $value, bool $append = false), (*76)

Set the HTTP header $header to the value $value. If $append is true and the header had been set before, an additional header line for the same header is added., (*77)

isHeaderSet()

bool isHeaderSet(string $header), (*78)

Returns whether the header $header has been set or not., (*79)

getHeader()

array getHeader(string $header), (*80)

Get the header $header. An array with the following elements is returned: - Response::HEADER_NAME: the name of the header, e.h. Content-Type - Response::HEADER_VALUES: an array of strings, representing the values, (*81)

getHeaders()

array getHeaders(), (*82)

Get all headers. It returns an array of entries as returned by getHeader()., (*83)

clearHeader()

void clearHeader(string $header), (*84)

Clear the header $header., (*85)

clearHeaders()

void clearHeaders(), (*86)

Clear all headers., (*87)

addResponseData()

void addResponseData(string $key, string $value, string $separator = '.'), (*88)

Adds data to the response array (for the JSON response type). Sub-array keys can be separated by the $separator string., (*89)

Example:, (*90)

addResponseData('data.user.name', 'John')

would set this value:, (*91)

{
  "data": {
    "user": {
      "name": "John"
    }
  }
}

corsSetOrigin()

void corsSetOrigin(string $origin), (*92)

Set the Access-Control-Allow-Origin to $origin, e.g. corsSetOrigin('*') to allow all origins., (*93)

corsAddOrigin()

void corsAddOrigin(string $origin), (*94)

If multiple origins are required, an origin can be added, e.g. corsAddOrigin('example.org'). The list of origins is compared to the Origin request header. On a match, the Access-Control-Allow-Origin is set to the matching origin., (*95)

corsGetOrigins()

array corsGetOrigins(), (*96)

Get the list of allowed origins., (*97)

corsAllowCredentials()

void corsAllowCredentials(bool $allowed), (*98)

Used to set the Access-Control-Allow-Credentials header., (*99)

corsAddAllowedHeader()

void corsAddAllowedHeader(string $header), (*100)

Add a header to the list of allowed headers used for Access-Control-Allow-Headers., (*101)

corsAddAllowedHeaders()

void corsAddAllowedHeaders(string[] $headers), (*102)

Set an array of allowed headers., (*103)

corsSetMaxAge()

void corsSetMaxAge(int $maxAgeSeconds), (*104)

Set the maximum age in seconds used for the Access-Control-Max-Age header., (*105)

The Versions

18/07 2018

dev-master

9999999-dev

Simple router, mainly for API backends, with CORS support

  Sources   Download

MIT

The Requires

  • php >=5.6

 

The Development Requires

by Stefan Stammler

api cors rest router

18/07 2018

v1.1.2

1.1.2.0

Simple router, mainly for API backends, with CORS support

  Sources   Download

MIT

The Requires

  • php >=5.6

 

The Development Requires

by Stefan Stammler

api cors rest router

18/07 2018

v1.1.1

1.1.1.0

Simple router, mainly for API backends, with CORS support

  Sources   Download

MIT

The Requires

  • php >=5.6

 

The Development Requires

by Stefan Stammler

api cors rest router

17/07 2018

v1.1.0

1.1.0.0

Simple router, mainly for API backends, with CORS support

  Sources   Download

MIT

The Requires

  • php >=5.6

 

The Development Requires

by Stefan Stammler

api cors rest router

18/07 2017

v1.0.1

1.0.1.0

Simple router, mainly for API backends, with CORS support

  Sources   Download

MIT

The Requires

  • php ~5.6|~7.0

 

The Development Requires

by Stefan Stammler

api cors rest router

15/06 2017

v1.0.0

1.0.0.0

Simple router, mainly for API backends, with CORS support

  Sources   Download

MIT

The Requires

  • php ^5.6|^7.0

 

The Development Requires

by Stefan Stammler

api cors rest router