Spellcheck and edit documentation
This commit is contained in:
parent
acc5b48314
commit
0cbcd6cbfc
|
|
@ -1,14 +1,14 @@
|
||||||
Dependency Injection
|
Dependency Injection
|
||||||
====================
|
====================
|
||||||
|
|
||||||
Here are a few strategies for how to make a dependency injection container availble to middleware with WellRESTed.
|
Here are a few strategies for how to make a dependency injection container available to middleware with WellRESTed.
|
||||||
|
|
||||||
Request Attribute
|
Request Attribute
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
``Psr\Http\Message\ServerRequestInterface`` provides "attributes" that allow you attach arbitrary data to a request. You can use this to make your dependcy container available to any dispatched middleware.
|
``Psr\Http\Message\ServerRequestInterface`` provides "attributes" that allow you attach arbitrary data to a request. You can use this to make your dependency container available to any dispatched middleware.
|
||||||
|
|
||||||
When you instatiate a ``WellRESTed\Server``, you can provide an array of attributes that the server will add to the request.
|
When you instantiate a ``WellRESTed\Server``, you can provide an array of attributes that the server will add to the request.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ When the server dispatches middleware, the middleware will be able to read the c
|
||||||
Callables
|
Callables
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
Another approach is to use callables that return ``MiddlewareInterface`` instances when you assign middleware. This approach provides an oppurtunity to pass the container into the middleware's constructor.
|
Another approach is to use callables that return ``MiddlewareInterface`` instances when you assign middleware. This approach provides an opportunity to pass the container into the middleware's constructor.
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
@ -51,7 +51,7 @@ Another approach is to use callables that return ``MiddlewareInterface`` instanc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
When you add the middleware to the server or register it with a router, use a callable that passes container into the contructor.
|
When you add the middleware to the server or register it with a router, use a callable that passes container into the constructor.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ Hello, World!
|
||||||
Let's start with a very basic "Hello, world!". Here, we will create a server. A ``WellRESTed\Server`` reads the
|
Let's start with a very basic "Hello, world!". Here, we will create a server. A ``WellRESTed\Server`` reads the
|
||||||
incoming request from the client, dispatches some middleware_, and transmits a response back to the client.
|
incoming request from the client, dispatches some middleware_, and transmits a response back to the client.
|
||||||
|
|
||||||
Our middelware is a function that returns a response with the status code set to ``200`` and the body set to "Hello, world!".
|
Our middleware is a function that returns a response with the status code set to ``200`` and the body set to "Hello, world!".
|
||||||
|
|
||||||
.. _`Example 1`:
|
.. _`Example 1`:
|
||||||
.. rubric:: Example 1: Simple "Hello, world!"
|
.. rubric:: Example 1: Simple "Hello, world!"
|
||||||
|
|
@ -46,7 +46,7 @@ Our middelware is a function that returns a response with the status code set to
|
||||||
|
|
||||||
The middleware in this example provides a ``Stream`` as the body instead of a string. This is a feature or PSR-7 where HTTP message bodies are always represented by streams. This allows you to work with very large bodies without having to store the entire contents in memory.
|
The middleware in this example provides a ``Stream`` as the body instead of a string. This is a feature or PSR-7 where HTTP message bodies are always represented by streams. This allows you to work with very large bodies without having to store the entire contents in memory.
|
||||||
|
|
||||||
WellRESTed provides ``Stream`` and ``NullStream``, but you can use any implementation of ``Psr\Http\Message\StreamInteface``.
|
WellRESTed provides ``Stream`` and ``NullStream``, but you can use any implementation of ``Psr\Http\Message\StreamInterface``.
|
||||||
|
|
||||||
Routing by Path
|
Routing by Path
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ Middleware
|
||||||
|
|
||||||
The middleware_ system allows you to map build sequences of modular code that propagate from one to the next. For example, an authenticator can validate a request and forward it to a cache; the cache can check for a stored representation and forward to another middleware if no cached representation is found, etc. All of this happens without any one middleware needing to know anything about where it is in the chain or which middleware comes before or after.
|
The middleware_ system allows you to map build sequences of modular code that propagate from one to the next. For example, an authenticator can validate a request and forward it to a cache; the cache can check for a stored representation and forward to another middleware if no cached representation is found, etc. All of this happens without any one middleware needing to know anything about where it is in the chain or which middleware comes before or after.
|
||||||
|
|
||||||
Most middleware is never autoloaded or instantiated until it is needed, so a Web service with hundreds of middleware still only creates instances required for the current request-respose cycle.
|
Most middleware is never autoloaded or instantiated until it is needed, so a Web service with hundreds of middleware still only creates instances required for the current request-response cycle.
|
||||||
|
|
||||||
You can register middleware directly, register callables that return middleware (e.g., dependency container services), or register strings containing the middleware class names to autoload and instantiate on demand.
|
You can register middleware directly, register callables that return middleware (e.g., dependency container services), or register strings containing the middleware class names to autoload and instantiate on demand.
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ WellRESTed's automates responding to ``OPTIONS`` requests for each endpoint base
|
||||||
Extensible
|
Extensible
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
All classes are coded to interfaces to allow you to provide your own implementations and use them in place of the built-in classes. For example, if your Web service needs to be able to dispatch middleware that implements a different interface, you can provide your own custom ``DispatcherInterface`` implentation.
|
All classes are coded to interfaces to allow you to provide your own implementations and use them in place of the built-in classes. For example, if your Web service needs to be able to dispatch middleware that implements a different interface, you can provide your own custom ``DispatcherInterface`` implementation.
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ This example middleware shows that you can use:
|
||||||
- ``getMethod()`` to read the HTTP verb (e.g., GET, POST, OPTIONS, DELETE)
|
- ``getMethod()`` to read the HTTP verb (e.g., GET, POST, OPTIONS, DELETE)
|
||||||
- ``getQueryParams()`` to read the query as an associative array
|
- ``getQueryParams()`` to read the query as an associative array
|
||||||
|
|
||||||
Let's move on to some more intersting features.
|
Let's move on to some more interesting features.
|
||||||
|
|
||||||
Headers
|
Headers
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
|
@ -84,8 +84,8 @@ Call ``getHeaderLine($name)`` and pass the case-insensitive name of a header. Th
|
||||||
$cacheControl = $request->getHeaderLine("cache-control");
|
$cacheControl = $request->getHeaderLine("cache-control");
|
||||||
// "no-cache"
|
// "no-cache"
|
||||||
|
|
||||||
// This message does not contain any authoriation headers.
|
// This message does not contain any authorization headers.
|
||||||
$authoriziation = $request->getHeaderLine("authorization");
|
$authorization = $request->getHeaderLine("authorization");
|
||||||
// ""
|
// ""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -95,7 +95,7 @@ Call ``getHeaderLine($name)`` and pass the case-insensitive name of a header. Th
|
||||||
All methods relating to headers treat header field name case insensitively.
|
All methods relating to headers treat header field name case insensitively.
|
||||||
|
|
||||||
|
|
||||||
Because HTTP messages may contain multiple headers with the same field name, ``getHeaderLine($name)`` has one other feature: If multiple headers with the same field name are present in the message, ``getHeaderLine($name)`` returns a string containing all of the values for that field, concatenated by commas. This is more common with responses, paricularaly with the ``Set-cookie`` header, but is still possible for requests.
|
Because HTTP messages may contain multiple headers with the same field name, ``getHeaderLine($name)`` has one other feature: If multiple headers with the same field name are present in the message, ``getHeaderLine($name)`` returns a string containing all of the values for that field, concatenated by commas. This is more common with responses, particularly with the ``Set-cookie`` header, but is still possible for requests.
|
||||||
|
|
||||||
You may also use ``hasHeader($name)`` to test if a header exists, ``getHeader($name)`` to receive an array of values for this field name, and ``getHeaders()`` to receive an associative array of headers where each key is a field name and each value is an array of field values.
|
You may also use ``hasHeader($name)`` to test if a header exists, ``getHeader($name)`` to receive an array of values for this field name, and ``getHeaders()`` to receive an associative array of headers where each key is a field name and each value is an array of field values.
|
||||||
|
|
||||||
|
|
@ -309,7 +309,7 @@ Provide middleware as the first middleware that set the default conditions.
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$initialResponsePrep = function ($rqst, $resp, $next) {
|
$initialResponsePrep = function ($rqst, $resp, $next) {
|
||||||
// Set intial response and forward to subsequent middleware.
|
// Set initial response and forward to subsequent middleware.
|
||||||
$resp = $resp
|
$resp = $resp
|
||||||
->withStatus(200)
|
->withStatus(200)
|
||||||
->withHeader("X-powered-by", "My Super Cool API v1.0.2")
|
->withHeader("X-powered-by", "My Super Cool API v1.0.2")
|
||||||
|
|
@ -420,14 +420,14 @@ To check if a header exists or to remove a header, use ``hasHeader`` and ``witho
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
// Check if a header exists.
|
// Check if a header exists.
|
||||||
$reponse->hasHeader("Content-type");
|
$response->hasHeader("Content-type");
|
||||||
// true
|
// true
|
||||||
|
|
||||||
// Clone this response without the "Content-type" header.
|
// Clone this response without the "Content-type" header.
|
||||||
$response = $response->withoutHeader("Content-type");
|
$response = $response->withoutHeader("Content-type");
|
||||||
|
|
||||||
// Check if a header exists.
|
// Check if a header exists.
|
||||||
$reponse->hasHeader("Content-type");
|
$response->hasHeader("Content-type");
|
||||||
// false
|
// false
|
||||||
|
|
||||||
Body
|
Body
|
||||||
|
|
@ -440,7 +440,7 @@ To set the body for the response, pass an instance implementing ``Psr\Http\Messa
|
||||||
$stream = new \WellRESTed\Message\Stream("Hello, world!");
|
$stream = new \WellRESTed\Message\Stream("Hello, world!");
|
||||||
$response = $response->withBody($stream);
|
$response = $response->withBody($stream);
|
||||||
|
|
||||||
WellRESTed provides two ``Psr\Http\Message\Stream`` implementations. You can use these, or any other impelentation.
|
WellRESTed provides two ``Psr\Http\Message\Stream`` implementations. You can use these, or any other implementation.
|
||||||
|
|
||||||
Stream
|
Stream
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
Middleware
|
Middleware
|
||||||
==========
|
==========
|
||||||
|
|
||||||
Okay, so what exactly **is** middleware? It's a nebulous term, and it's a bit reminscent of the Underpants gnomes.
|
Okay, so what exactly **is** middleware? It's a nebulous term, and it's a bit reminiscent of the Underpants gnomes.
|
||||||
|
|
||||||
- Phase 1: Request
|
- Phase 1: Request
|
||||||
- Phase 2: ???
|
- Phase 2: ???
|
||||||
- Phase 3: Respose
|
- Phase 3: Response
|
||||||
|
|
||||||
Middleware is indeed Phase 2. It's something (a callable or object) that takes a request and a response as inputs, does something with the response, and sends the altered response back out.
|
Middleware is indeed Phase 2. It's something (a callable or object) that takes a request and a response as inputs, does something with the response, and sends the altered response back out.
|
||||||
|
|
||||||
|
|
@ -133,7 +133,7 @@ Use a middleware callable directly.
|
||||||
Instance
|
Instance
|
||||||
--------
|
--------
|
||||||
|
|
||||||
You can also provide pass an instnace directly as middleware.
|
You can also provide pass an instance directly as middleware.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
|
|
@ -150,7 +150,7 @@ Why use one middleware when you can use more?
|
||||||
|
|
||||||
Provide a sequence of middleware as an array. Each component of the array can be any of the varieties listed in this section.
|
Provide a sequence of middleware as an array. Each component of the array can be any of the varieties listed in this section.
|
||||||
|
|
||||||
When disptached, the middleware in the array will run in order, with each calling the one following via the ``$next`` parameter.
|
When dispatched, the middleware in the array will run in order, with each calling the one following via the ``$next`` parameter.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
|
|
@ -172,7 +172,7 @@ Here's an example authorization middleware using pseudocode.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
namespace Webserice;
|
namespace Webservice;
|
||||||
|
|
||||||
class Authorization implements \WellRESTed\MiddlewareInterface
|
class Authorization implements \WellRESTed\MiddlewareInterface
|
||||||
{
|
{
|
||||||
|
|
@ -201,7 +201,7 @@ We can add authorization for just the ``/widgets/{id}`` endpoint like this:
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$router->register("GET,PUT,DELETE", "/widgets/{id}", [
|
$router->register("GET,PUT,DELETE", "/widgets/{id}", [
|
||||||
'Webservice\Auhtorizaiton',
|
'Webservice\Authorization',
|
||||||
'Webservice\Widgets\WidgetHandler'
|
'Webservice\Widgets\WidgetHandler'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -211,7 +211,7 @@ Or, if you wanted to use the authorization for the entire service, you can add i
|
||||||
|
|
||||||
$server = new \WellRESTed\Server();
|
$server = new \WellRESTed\Server();
|
||||||
$server
|
$server
|
||||||
->add('Webservice\Auhtorizaiton')
|
->add('Webservice\Authorization')
|
||||||
->add($server->createRouter()
|
->add($server->createRouter()
|
||||||
->register("GET,PUT,DELETE", "/widgets/{id}", 'Webservice\Widgets\WidgetHandler')
|
->register("GET,PUT,DELETE", "/widgets/{id}", 'Webservice\Widgets\WidgetHandler')
|
||||||
)
|
)
|
||||||
|
|
@ -220,15 +220,15 @@ Or, if you wanted to use the authorization for the entire service, you can add i
|
||||||
Moving Back Down the Chain
|
Moving Back Down the Chain
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
The authorization example returned ``$next($request, $response)`` immidiately, but you can do some interesting things by working with the response that comes back from ``$next``. Think of the request as taking a round trip on the subway with each middleware being a stop along the way. Each of the stops you go through going up the chain, you also go through on the way back down.
|
The authorization example returned ``$next($request, $response)`` immediately, but you can do some interesting things by working with the response that comes back from ``$next``. Think of the request as taking a round trip on the subway with each middleware being a stop along the way. Each of the stops you go through going up the chain, you also go through on the way back down.
|
||||||
|
|
||||||
We could add a caching middleware in front of ``GET`` requests for a specific widget. This middleware will check if a cached representation exists for the resource the client requested. If it exists, it will send it out to the client without ever bothering the ``WidgetHandler``. If there's no representation cached, it will call ``$next`` to propgate the request up the chain. On the return trip (when the call to ``$next`` finishes), the caching middleware will inspect the response and store the body to the cache for next time.
|
We could add a caching middleware in front of ``GET`` requests for a specific widget. This middleware will check if a cached representation exists for the resource the client requested. If it exists, it will send it out to the client without ever bothering the ``WidgetHandler``. If there's no representation cached, it will call ``$next`` to propagate the request up the chain. On the return trip (when the call to ``$next`` finishes), the caching middleware will inspect the response and store the body to the cache for next time.
|
||||||
|
|
||||||
Here's a pseudocode example:
|
Here's a pseudocode example:
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
namespace Webserice;
|
namespace Webservice;
|
||||||
|
|
||||||
class Cache implements \WellRESTed\MiddlewareInterface
|
class Cache implements \WellRESTed\MiddlewareInterface
|
||||||
{
|
{
|
||||||
|
|
@ -240,7 +240,7 @@ Here's a pseudocode example:
|
||||||
if ($representation !== null) {
|
if ($representation !== null) {
|
||||||
// There is already a cached representation. Send it out
|
// There is already a cached representation. Send it out
|
||||||
// without propagating.
|
// without propagating.
|
||||||
return $reponse
|
return $response
|
||||||
->withStatus(200)
|
->withStatus(200)
|
||||||
->withBody($representation);
|
->withBody($representation);
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +263,7 @@ Here's a pseudocode example:
|
||||||
private function storeRepresentationToCache(ResponseInterface $response)
|
private function storeRepresentationToCache(ResponseInterface $response)
|
||||||
{
|
{
|
||||||
// Ensure the response contains a success code, a valid body,
|
// Ensure the response contains a success code, a valid body,
|
||||||
// headers that allow caching, etc. and store the represetnation.
|
// headers that allow caching, etc. and store the representation.
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -273,18 +273,18 @@ We can add this caching middleware in the chain between the authorization middle
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$router->register("GET,PUT,DELETE", "/widgets/{id}", [
|
$router->register("GET,PUT,DELETE", "/widgets/{id}", [
|
||||||
'Webservice\Auhtorizaiton',
|
'Webservice\Authorization',
|
||||||
'Webservice\Cache',
|
'Webservice\Cache',
|
||||||
'Webservice\Widgets\WidgetHandler'
|
'Webservice\Widgets\WidgetHandler'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Or, if you wanted to use the authorization and caching middelware for the entire service, you can add them to the ``Server`` in front of the ``Router``.
|
Or, if you wanted to use the authorization and caching middleware for the entire service, you can add them to the ``Server`` in front of the ``Router``.
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$server = new \WellRESTed\Server();
|
$server = new \WellRESTed\Server();
|
||||||
$server
|
$server
|
||||||
->add('Webservice\Auhtorizaiton')
|
->add('Webservice\Authorization')
|
||||||
->add('Webservice\Cache')
|
->add('Webservice\Cache')
|
||||||
->add($server->createRouter()
|
->add($server->createRouter()
|
||||||
->register("GET,PUT,DELETE", "/widgets/{id}", 'Webservice\Widgets\WidgetHandler')
|
->register("GET,PUT,DELETE", "/widgets/{id}", 'Webservice\Widgets\WidgetHandler')
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ For a request to ``/cats/molly``:
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
Template routes are very powerful, and this only scratches the surface. See `URI Templates`_ for a full explaination of the syntax supported.
|
Template routes are very powerful, and this only scratches the surface. See `URI Templates`_ for a full explanation of the syntax supported.
|
||||||
|
|
||||||
Regex Routes
|
Regex Routes
|
||||||
------------
|
------------
|
||||||
|
|
@ -128,10 +128,10 @@ Route Priority
|
||||||
A router will often contain many routes, and sometimes more than one route will match for a given request. When the router looks for a matching route, it performs these checks:
|
A router will often contain many routes, and sometimes more than one route will match for a given request. When the router looks for a matching route, it performs these checks:
|
||||||
|
|
||||||
#. If there is a static route with exact match to path, dispatch it.
|
#. If there is a static route with exact match to path, dispatch it.
|
||||||
#. If one prefix route matches the beginning of the path, disptach it.
|
#. If one prefix route matches the beginning of the path, dispatch it.
|
||||||
#. If multiple prefix routes match, dispatch the longest matching prefix route.
|
#. If multiple prefix routes match, dispatch the longest matching prefix route.
|
||||||
#. Inspect each pattern route (template and regular expression) in the order added. Dispatch the first route that matches.
|
#. Inspect each pattern route (template and regular expression) in the order added. Dispatch the first route that matches.
|
||||||
#. If no pattern routes match, return a reponse with a ``404 Not Found`` status.
|
#. If no pattern routes match, return a response with a ``404 Not Found`` status.
|
||||||
|
|
||||||
Static vs. Prefix
|
Static vs. Prefix
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
@ -179,7 +179,7 @@ Given these routes:
|
||||||
Pattern vs. Pattern
|
Pattern vs. Pattern
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
When multiple pattern routes match a path, the first one that was added to the router will be the one disptached. Be careful to add the specific routes before the general routes. For example, say you want to send traffic to two similar looking URIs to different middleware based whether the variables were supplied as numbers or letters—``/dogs/102/132`` should be dispatched to ``$numbers``, while ``/dogs/herding/australian-shepherd`` should be dispatched to ``$letters``.
|
When multiple pattern routes match a path, the first one that was added to the router will be the one dispatched. Be careful to add the specific routes before the general routes. For example, say you want to send traffic to two similar looking URIs to different middleware based whether the variables were supplied as numbers or letters—``/dogs/102/132`` should be dispatched to ``$numbers``, while ``/dogs/herding/australian-shepherd`` should be dispatched to ``$letters``.
|
||||||
|
|
||||||
This will work:
|
This will work:
|
||||||
|
|
||||||
|
|
@ -204,7 +204,7 @@ This is because ``/dogs/{group}/{breed}`` will match both ``/dogs/102/132`` and
|
||||||
Methods
|
Methods
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
|
||||||
When you register a route, you can provide a specific method, a list of methods, or a wildcard to indcate any method.
|
When you register a route, you can provide a specific method, a list of methods, or a wildcard to indicate any method.
|
||||||
|
|
||||||
Registering by Method
|
Registering by Method
|
||||||
---------------------
|
---------------------
|
||||||
|
|
@ -253,7 +253,7 @@ Specify middleware for all methods for a given path by proving a ``*`` wildcard.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The wildcard ``*`` can be useful, but be aware that the associated middleware will need to manage ``HEAD`` and ``OPTIONS`` requests, whereas this is done automatcially for non-wildcard routes.
|
The wildcard ``*`` can be useful, but be aware that the associated middleware will need to manage ``HEAD`` and ``OPTIONS`` requests, whereas this is done automatically for non-wildcard routes.
|
||||||
|
|
||||||
HEAD
|
HEAD
|
||||||
----
|
----
|
||||||
|
|
@ -282,7 +282,7 @@ An ``OPTIONS`` request to ``/cats/12`` will provide a response like:
|
||||||
HTTP/1.1 200 OK
|
HTTP/1.1 200 OK
|
||||||
Allow: GET,PUT,DELETE,HEAD,OPTIONS
|
Allow: GET,PUT,DELETE,HEAD,OPTIONS
|
||||||
|
|
||||||
Likewise, a request to an unsupport method will return a ``405 Method Not Allowed`` response with a descriptive ``Allow`` header.
|
Likewise, a request to an unsupported method will return a ``405 Method Not Allowed`` response with a descriptive ``Allow`` header.
|
||||||
|
|
||||||
A ``POST`` request to ``/cats/12`` will provide:
|
A ``POST`` request to ``/cats/12`` will provide:
|
||||||
|
|
||||||
|
|
@ -326,7 +326,7 @@ PUT /cats/ 405 Method Not Allowed
|
||||||
Nested Routers
|
Nested Routers
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
For large Web services with large numbers of endpoints, a single, monolithic router may not to optimal. To avoid having each request test every pattern-based route, you can break up a router into subrouters.
|
For large Web services with large numbers of endpoints, a single, monolithic router may not to optimal. To avoid having each request test every pattern-based route, you can break up a router into sub-routers.
|
||||||
|
|
||||||
This works because a ``Router`` is type of middleware, and can be used wherever middleware can be used.
|
This works because a ``Router`` is type of middleware, and can be used wherever middleware can be used.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@ In `URI Templates`_, we looked at the most common ways to use URI Templates. In
|
||||||
Path Components
|
Path Components
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
To matching a path componenent, include a slash ``/`` at the beginning of the variable expression. This instructs the template to match the variable if it:
|
To match a path component, include a slash ``/`` at the beginning of the variable expression. This instructs the template to match the variable if it:
|
||||||
|
|
||||||
- Begins with ``/``
|
- Begins with ``/``
|
||||||
- Contains only unreserved and percent-encoded characters
|
- Contains only unreserved and percent-encoded characters
|
||||||
|
|
||||||
You may also use the explode (``*``) modifier to match a variable number of path components and provide them as an array. When using the exlode (``*``) modifier to match paths components, the ``/`` character serves as the delimiter instead of a comma.
|
You may also use the explode (``*``) modifier to match a variable number of path components and provide them as an array. When using the explode (``*``) modifier to match paths components, the ``/`` character serves as the delimiter instead of a comma.
|
||||||
|
|
||||||
.. list-table:: Matching path components
|
.. list-table:: Matching path components
|
||||||
:header-rows: 1
|
:header-rows: 1
|
||||||
|
|
@ -57,7 +57,7 @@ Including a dot ``.`` at the beginning of the variable expression instructs the
|
||||||
- Begins with ``.``
|
- Begins with ``.``
|
||||||
- Contains only unreserved (including ``.``) and percent-encoded characters
|
- Contains only unreserved (including ``.``) and percent-encoded characters
|
||||||
|
|
||||||
You may also use the explode (``*``) modifier to match a variable number of dot-prefixed segements and store them to an array. When using the exlode (``*``) modifier to match paths components, the ``.`` character serves as the delimiter instead of a comma.
|
You may also use the explode (``*``) modifier to match a variable number of dot-prefixed segments and store them to an array. When using the explode (``*``) modifier to match paths components, the ``.`` character serves as the delimiter instead of a comma.
|
||||||
|
|
||||||
.. list-table:: Matching dot prefixes
|
.. list-table:: Matching dot prefixes
|
||||||
:header-rows: 1
|
:header-rows: 1
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
URI Templates
|
URI Templates
|
||||||
=============
|
=============
|
||||||
|
|
||||||
WellRESTed allows you to register middleware with a router using URI Templates, based on the URI Templates defined in `RFC 6570`_. These templates include variables (enclosed in curly braces) which are extracted and made availble to the disptached middleware.
|
WellRESTed allows you to register middleware with a router using URI Templates, based on the URI Templates defined in `RFC 6570`_. These templates include variables (enclosed in curly braces) which are extracted and made available to the dispatched middleware.
|
||||||
|
|
||||||
Reading Variables
|
Reading Variables
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
@ -88,11 +88,11 @@ Matching Characters
|
||||||
Unreserved Characters
|
Unreserved Characters
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
By default, URI Template variables will match only "unreserved" characters. `RFC 3968 Section 2.3`_ defines unreserved characters as alphanumeric characters, ``-``, ``.``, ``_``, and ``~``. All other characters must be percent encoded to be matched by a default template variale.
|
By default, URI Template variables will match only "unreserved" characters. `RFC 3968 Section 2.3`_ defines unreserved characters as alphanumeric characters, ``-``, ``.``, ``_``, and ``~``. All other characters must be percent encoded to be matched by a default template variable.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Percent-encoded characters matched by template variables are automatically decoded when provided as request attibutes.
|
Percent-encoded characters matched by template variables are automatically decoded when provided as request attributes.
|
||||||
|
|
||||||
Given the template ``/users/{user}``, the following paths provide these values for ``getAttribute("user")``:
|
Given the template ``/users/{user}``, the following paths provide these values for ``getAttribute("user")``:
|
||||||
|
|
||||||
|
|
@ -113,7 +113,7 @@ A request for ``GET /uses/zoidberg@planetexpress.com`` will **not** match this t
|
||||||
Reserved Characters
|
Reserved Characters
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
If you need to match a non-percent-encoded reserved character like ``@`` or ``/``, use the ``+`` operator at the begining of the variable name.
|
If you need to match a non-percent-encoded reserved character like ``@`` or ``/``, use the ``+`` operator at the beginning of the variable name.
|
||||||
|
|
||||||
Using the template ``/users/{+user}``, we can match all of the paths above, plus ``/users/zoidberg@planetexpress.com``.
|
Using the template ``/users/{+user}``, we can match all of the paths above, plus ``/users/zoidberg@planetexpress.com``.
|
||||||
|
|
||||||
|
|
@ -121,7 +121,7 @@ Reserved matching also allows matching unencoded slashes (``/``). For example, g
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
$router->register("GET", "/my-favorte-path{+path}", $pathHandler);
|
$router->register("GET", "/my-favorite-path{+path}", $pathHandler);
|
||||||
|
|
||||||
The router will dispatch ``$pathHandler`` with for a request to ``GET /my-favorite-path/has/a/few/slashes.jpg``
|
The router will dispatch ``$pathHandler`` with for a request to ``GET /my-favorite-path/has/a/few/slashes.jpg``
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue