Skip to content

Commit

Permalink
Merge pull request #65 from php-http/merge-httplug-intro
Browse files Browse the repository at this point in the history
Merge HTTPlug intro and re-group TOC
  • Loading branch information
ddeboer committed Jan 3, 2016
2 parents ace1a8a + b4a7cf3 commit e1402ab
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 180 deletions.
15 changes: 14 additions & 1 deletion clients.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Clients & Adapters
There are clients implementing one of the HTTPlug interfaces directly,
and adapter packages that implement the interface and forward the calls to HTTP clients not implementing the interface.

TODO
.. _`php-http/client-implementation`: https://packagist.org/providers/php-http/client-implementation
.. _`php-http/async-client-implementation`: https://packagist.org/providers/php-http/async-client-implementation:


Clients:

Expand All @@ -21,3 +23,14 @@ Client adapters:
clients/guzzle5-adapter
clients/guzzle6-adapter
clients/react-adapter

Composer Virtual Packages
-------------------------

Virtual packages are a way to specify the dependency on an implementation of an interface-only repository
without forcing a specific implementation. For HTTPlug, the virtual package is called ``php-http/client-implementation``.

There is no project registered with that name. However, all client implementations including client adapters for
HTTPlug use the ``provide`` section to tell composer that they do provide the client-implementation.


1 change: 1 addition & 0 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,5 @@
rst_epilog = """
.. _PSR-7: http://www.php-fig.org/psr/psr-7
.. _Composer: https://getcomposer.org
.. _HttplugBundle: https://github.com/php-http/HttplugBundle
"""
29 changes: 0 additions & 29 deletions httplug.rst

This file was deleted.

11 changes: 11 additions & 0 deletions httplug/application-developers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
HTTPlug for application developers
==================================

Framework integration
---------------------

HTTPlug can be used in any PHP based project. Nonetheless, we provide
integration for some popular frameworks:

- HttplugBundle_: integration with the Symfony framework.

113 changes: 42 additions & 71 deletions httplug/introduction.rst
Original file line number Diff line number Diff line change
@@ -1,95 +1,66 @@
Introduction to HTTPlug
=======================
HTTPlug: HTTP client abstraction
================================

HTTPlug implementations
-----------------------
HTTPlug allows you to write reusable libraries and applications that need
an HTTP client without binding to a specific implementation.
When all packages used in an application only specify HTTPlug,
the application developers can choose the client that best fits their project
and use the same client with all packages.

HTTPlug implementations typically are either HTTP clients of their own, or adapters wrapping existing clients
like Guzzle 6. In the latter case, they will depend on the required client implementation,
so you only need to require the adapter and not the actual client.
The client interfaces
---------------------

HTTPlug defines two HTTP client interfaces that we kept as simple as possible:

There are two kind of implementations:
* ``HttpClient`` defines a ``sendRequest`` method that sends a PSR-7
``RequestInterface`` and either returns a PSR-7 ``ResponseInterface`` or
throws an exception that implements ``Http\Client\Exception``.

- `php-http/client-implementation`_:
the synchronous implementation that waits for the response / error before returning from the ``sendRequest`` method.
* ``HttpAsyncClient`` defines a ``sendAsyncRequest`` method that sends a request
asynchronously and always returns a ``Http\Client\Promise``.

- `php-http/async-client-implementation`_:
the asynchronous implementation that immediately returns a ``Http\Promise\Promise``,
allowing to send several requests in parallel and handling responses later.
Implementations
---------------

Check links above for the full list of implementations.
PHP-HTTP offers two types of clients that implement the above interfaces:

.. _`php-http/client-implementation`: https://packagist.org/providers/php-http/client-implementation
.. _`php-http/async-client-implementation`: https://packagist.org/providers/php-http/async-client-implementation:
1. Standalone clients that directly implement the interfaces.

Usage in an application
-----------------------
Examples: :doc:`/clients/curl-client` and :doc:`/clients/socket-client`.

When writing an application, you need to require a concrete implementation_.
2. Adapters that wrap existing HTTP client, such as Guzzle. These adapters act
as a bridge between the HTTPlug interfaces and the clients that do not (yet)
implement these interfaces.

See :doc:`virtual-package` for more information on the topic of working with HTTPlug implementations.
Examples: :doc:`/clients/guzzle6-adapter` and :doc:`/clients/react-adapter`.

Installation in a reusable package
----------------------------------
.. note::

In many cases, packages are designed to be reused from the very beginning.
For example, API clients are usually used in other packages/applications, not on their own.
Ideally, all HTTP client libraries out there will implement the HTTPlug
interfaces. At that point, our adapters will no longer be necessary.

Reusable packages should **not rely on a concrete implementation** (like Guzzle 6),
but only require any implementation of HTTPlug. HTTPlug uses the concept of virtual packages.
Instead of depending on only the interfaces, which would be missing an implementation,
or depending on one concrete implementation, you should depend on the virtual package ``php-http/client-implementation``
or ``php-http/async-client-implementation``. There is no package with that name,
but all clients and adapters implementing HTTPlug declare that they provide one of this virtual package or both.
Usage
-----

You need to edit the ``composer.json`` of your package to add the virtual package.
For development (installing the package standalone, running tests),
add a concrete implementation in the ``require-dev`` section to make the project installable:
There are two main use cases for HTTPlug:

.. code-block:: json
{
"require": {
"php-http/client-implementation": "^1.0"
},
"require-dev": {
"php-http/guzzle6-adapter": "^1.0"
},
}
For extra convenience, you can use the :doc:`/discovery` system to free the user of your
package from having to instantiate the client.
You should however always accept injecting the client instance to allow the user to configure the client as needed.
You can find an example in the :doc:`/discovery` documentation.

Users of your package will have to select a concrete adapter in their project to make your package installable.
Best point them to the :doc:`virtual-package` page.

To be able to send requests, you should not depend on a specific PSR-7 implementation,
but use the :ref:`message-factory` system.

Framework Integration
^^^^^^^^^^^^^^^^^^^^^

HTTPlug can be used in any PHP based project.
Nonetheless, we provide particular integration for some popular frameworks:

- HttplugBundle_: integration with the Symfony framework.
* usage in an application that executes HTTP requests (see :doc:`application-developers`).
* usage in a reusable package that executes HTTP requests (see :doc:`library-developers`).

History
-------

This project has been started by `Eric Geloen`_ as `Ivory Http Adapter`_. It never made it to a stable release,
but it relied on PSR-7 which was not stable either that time. Because of the constantly changing PSR-7,
Eric had to rewrite the library over and over again (at least the message handling part,
which in most cases affected every adapter as well).
This project has been started by `Eric Geloen`_ as `Ivory Http Adapter`_. It
never made it to a stable release, but it relied on PSR-7 which was not stable
either that time. Because of the constantly changing PSR-7, Eric had to rewrite
the library over and over again (at least the message handling part, which in
most cases affected every adapter as well).

In 2015, a decision has been made to move the library to its own organization, so PHP HTTP was born.
In 2015, a decision has been made to move the library to its own organization,
so PHP-HTTP was born.

See :doc:`migrating` for a guide how to migrate your code from the Ivory adapter to HTTPlug.
See :doc:`migrating` for a guide how to migrate your code from the Ivory
adapter.

.. _implementation: https://packagist.org/providers/php-http/client-implementation
.. _HttplugBundle: https://github.com/php-http/HttplugBundle
.. _`Eric Geloen`: https://github.com/egeloen
.. _`Ivory Http Adapter`: https://github.com/egeloen/ivory-http-adapter).
.. _`Ivory Http Adapter`: https://github.com/egeloen/ivory-http-adapter
76 changes: 76 additions & 0 deletions httplug/library-developers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
HTTPlug for library developers
==============================

If you’re developing a library or framework that performs HTTP requests, you
should not be dependent on concrete HTTP client libraries (such as Guzzle).
Instead, you should only make sure that *some* HTTP client is available. It is
then up to your users to decide which HTTP client they want to include in their
projects.

Manage dependencies
-------------------

To depend on *some* HTTP client, specify either
``php-http/client-implementation`` or ``php-http/async-client-implementation``
in your library’s ``composer.json``. These are virtual Composer packages that
will throw an error if no concrete client was found:

.. code-block:: json
{
"name": "you/and-your-awesome-library",
"require": {
"php-http/client-implementation": "^1.0"
}
}
Your users then include your project alongside with a HTTP client of their
choosing in their project’s ``composer.json``. In this case, the user decided
to include the Socket client:

.. code-block:: json
{
"name": "some-user/nice-project",
"require": {
"you/and-your-awesome-library": "^1.2",
"php-http/socket-client": "^1.0"
}
}
Standalone installation
-----------------------

This is sufficient for your library’s users. For the library’s developers,
however, it’s best if some specific client is installed when they run
``composer install`` in the library’s directory. So specify any concrete client
in the ``require-dev`` section in your library’s ``composer.json``. In this
example, we chose the Guzzle 6 adapter:

.. code-block:: json
{
"name": "you/and-your-awesome-library",
"require": {
"php-http/client-implementation": "^1.0"
},
"require-dev": {
"php-http/guzzle6-adapter": "^1.0"
}
}
For extra convenience, you can use :doc:`/discovery` to free your users from
having to instantiate the client.

Messages
--------

When you construct HTTP message objects in your library, you should not depend
on a concrete PSR-7 message implementation. Instead, use the
:ref:`PHP-HTTP message factory <message-factory>`.

User documentation
------------------

To explain to your users that they need to install a concrete HTTP client,
you can point them to :doc:`users`.
5 changes: 0 additions & 5 deletions httplug/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,3 @@ Handling errors
---------------

TODO: explain how to handle exceptions, distinction between network exception and HttpException.

Writing a reusable package
--------------------------

See :ref:`httplug-building-reusable-library`
12 changes: 12 additions & 0 deletions httplug/usage.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
HTTPlug usage
=============

HTTPlug is relevant for three groups of users:

.. toctree::
:maxdepth: 1

Library users <users>
Application developers <application-developers>
Library developers <library-developers>

56 changes: 56 additions & 0 deletions httplug/users.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
HTTPlug for library users
=========================

If you use a library that depends on HTTPlug (say, ``some/awesome-library``),
you need to include an HTTPlug client in your project before you can include
``awesome-library``.

From the list of :doc:`clients </clients>`, choose on that best fits your
application, then include it in your project. For instance, if you decide to
use the Socket client:

.. code-block:: bash
$ composer require php-http/socket-client
Instead of an HTTPlug client, you may want to use an adapter for your favorite
HTTP client. If that turns out to be Guzzle:

.. code-block:: bash
$ composer require php-http/guzzle6-adapter
Then you can include the library:

.. code-block:: bash
$ composer require some/awesome-library
Troubleshooting
---------------

If you try to include the HTTPlug-dependent library before you have included a
HTTP client in your project, Composer will throw an error:

.. code-block:: none
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
- The requested package php-http/client-implementation could not be found in any version,
there may be a typo in the package name.
You can solve this by including a HTTP client or adapter, as described above.

Background
----------

Reusable libraries do not depend on a concrete implementation but only on the virtual package
``php-http/client-implementation``. This is to avoid hard coupling and allows the user of the
library to choose the implementation. You can think of this as an "interface" or "contract" for packages.

When *using a reusable library* in an application, one must ``require`` a concrete implementation.
Make sure the ``require`` section includes a package that provides ``php-http/client-implementation``.
Failing to do that will lead to composer reporting this error:

0 comments on commit e1402ab

Please sign in to comment.