From db09618a4709089eec43a0aa5f76b77c82b0bbf4 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Fri, 23 Oct 2015 19:03:28 +0200 Subject: [PATCH] reorganizing the documentation --- README.md | 4 +- docs/discovery.md | 44 +++++++------------- docs/httplug.md | 53 +++++++++++++++++++++++++ docs/index.md | 86 ++++++++-------------------------------- docs/message-factory.md | 7 +++- docs/migrating.md | 21 ++++++++++ docs/package-overview.md | 48 ++++++++++++++++++++++ docs/plugins.md | 5 +++ docs/tutorial.md | 46 +++++++++++++++++++++ docs/upgrading.md | 74 ---------------------------------- docs/utils.md | 25 ++++++++++++ docs/virtual-package.md | 33 +++++++++++++++ mkdocs.yml | 2 +- 13 files changed, 270 insertions(+), 178 deletions(-) create mode 100644 docs/httplug.md create mode 100644 docs/migrating.md create mode 100644 docs/package-overview.md create mode 100644 docs/plugins.md create mode 100644 docs/tutorial.md delete mode 100644 docs/upgrading.md create mode 100644 docs/utils.md create mode 100644 docs/virtual-package.md diff --git a/README.md b/README.md index 36f3ebb..1011189 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# HTTP Adapter Documentation +# PHP-HTTP Documentation [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) -**This is the documentation repository of the HTTP Adapter software components** +**This is the documentation repository of the PHP-HTTP software components** Browse the documentation on [Read the Docs](http://php-http.readthedocs.org/). diff --git a/docs/discovery.md b/docs/discovery.md index 3dd5487..7f338ca 100644 --- a/docs/discovery.md +++ b/docs/discovery.md @@ -1,43 +1,38 @@ # Discovery -The discovery service is a set of static classes which allows to find and use installed resources. This is useful in libraries that want to offer zero-configuration services and rely only on the virtual packages, e.g. `php-http/adapter-implementation` or `psr/http-message-implementation`. +The discovery service is a set of static classes which allows to find and use installed resources. This is useful in libraries that want to offer zero-configuration services and rely only on the virtual packages, e.g. `php-http/client-implementation` or `psr/http-message-implementation`. Currently available discovery services: -- HTTP Adapter Discovery +- HTTP client Discovery - PSR-7 Message Factory Discovery - PSR-7 URI Factory Discovery The principle is always the same: you call the static `find` method on the discovery service if no explicit implementation was specified. The discovery service will try to locate a suitable implementation. If no implementation is found, an `Http\Discovery\NotFoundException` is thrown. -## HTTP Adapter Discovery +## HTTP Client Discovery -This type of discovery finds installed HTTP Adapters. - -Currently available adapters: - -- [Guzzle 6](https://github.com/php-http/guzzle6-adapter) -- [Guzzle 5](https://github.com/php-http/guzzle5-adapter) +This type of discovery finds installed HTTP Clients. ``` php -use Http\Adapter\HttpAdapter; -use Http\Discovery\HttpAdapterDiscovery; +use Http\Client\HttpClient; +use Http\Discovery\HttpClientDiscovery; class MyClass { /** - * @var HttpAdapter + * @var HttpClient */ - protected $httpAdapter; + protected $httpClient; /** - * @param HttpAdapter|null $httpAdapter to do HTTP requests. + * @param HttpClient|null $httpClient to do HTTP requests. */ - public function __construct(HttpAdapter $httpAdapter = null) + public function __construct(HttpClient $httpClient = null) { - $this->httpAdapter = $httpAdapter ?: HttpAdapterDiscovery::find(); + $this->httpClient = $httpClient ?: HttpClientDiscovery::find(); } } ``` @@ -45,13 +40,7 @@ class MyClass ## PSR-7 Message Factory Discovery -This type of discovery finds installed [PSR-7](http://www.php-fig.org/psr/psr-7/) Message implementations and their factories. - -Currently available factories: - -- [Guzzle](https://github.com/guzzle/psr7) factory -- [Diactoros](https://github.com/zendframework/zend-diactoros) factory - +This type of discovery finds installed [PSR-7](http://www.php-fig.org/psr/psr-7/) Message implementations and their (factories)[message-factory.md]. ``` php use Http\Message\MessageFactory; @@ -74,16 +63,11 @@ class MyClass } ``` + ## PSR-7 URI Factory Discovery This type of discovery finds installed [PSR-7](http://www.php-fig.org/psr/psr-7/) URI implementations and their factories. -Currently available factories: - -- [Guzzle](https://github.com/guzzle/psr7) factory -- [Diactoros](https://github.com/zendframework/zend-diactoros) factory - - ``` php use Http\Message\UriFactory; use Http\Discovery\UriFactoryDiscovery; @@ -111,7 +95,7 @@ class MyClass The `php-http/discovery` has built-in support for some implementations. To use a different implementation or override the default when several implementations are available in your codebase, you can register a class explicitly with the corresponding discovery service. For example: ``` php -HttpAdapterDiscovery::register('Acme\MyAdapter', true); +HttpClientDiscovery::register('Acme\MyClient', true); ``` - `class`: The class that is instantiated. This class MUST NOT require any constructor arguments. diff --git a/docs/httplug.md b/docs/httplug.md new file mode 100644 index 0000000..91bb7fe --- /dev/null +++ b/docs/httplug.md @@ -0,0 +1,53 @@ +# Httplug HTTP client abstraction + +Httplug is an abstraction for HTTP clients. There are two main use cases: + +1. Usage in a project +2. Usage in a reusable package + +In both cases, the client provides a `sendRequest` method to send a PSR-7 `RequestInterface` and returns a PSR-7 `ResponseInterface` or throws an exception that implements `Http\Client\Exception`. + +See the (tutorial)[tutorial.md] for a concrete example. + + +## Httplug implementations + +Httplug implementations typically are either HTTP clients of their own, or they are 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. + +See (packagist)[https://packagist.org/providers/php-http/client-implementation] for the full list of implementations. + +Note: Until Httplug 1.0 becomes stable, we will focus on the Guzzle6 adapter. + +## Usage in a project + +When writing an application, you should require a concrete client implementation. The client will in turn depend on `php-http/httplug`. + +A few things should be taken into consideration before choosing an adapter: + +- It is possible that some other dependency already has an HTTP Client requirement like Guzzle 6. It can be confusing to have more than one HTTP Client installed, so always check your other requirements and choose an adapter based on that. + + +## Installation in a reusable package + +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. + +In these cases, they 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`. There is no package with that name, but all clients and adapters implementing Httplug declare that they provide this virtual package. + +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: + +``` json +... +"require": { + "php-http/client-implementation": "^1.0" +}, +"require-dev": { + "php-http/guzzle6-adapter": "^1.0" +}, +... +``` + +For extra convenience, you can use the (Discovery)[discovery.md] 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. + +Users of your package will have to select a concrete adapter in their project to make your package installable. Best point them to the (virtual package)[virtual-package.md] howto page. + +To be able to send requests, you should not depend on a specific PSR-7 implementation, but use the (message factory)[message-factory.md] system. diff --git a/docs/index.md b/docs/index.md index b048ba0..28329a6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,87 +1,35 @@ -# HTTP Adapter +# PHP-HTTP Httplug -**This is the documentation for HTTP Adapter and it's software components.** +**This is the documentation for the Httplug HTTP client abstraction and the other PHP-HTTP components.** -The HTTP Adapter abstracts from PHP HTTP clients that are based on [PSR-7](http://www.php-fig.org/psr/psr-7/). -It allows you to write reusable libraries and applications that need a HTTP client without binding to a specific implementation. +[PSR-7](http://www.php-fig.org/psr/psr-7/) defines interfaces for HTTP requests and responses. However, it does not define how to create a request or how to send a request. Httplug abstracts from HTTP clients written in PHP, offering a simple interface. It also brings a implementation-independent plugin system to build pipelines regardless of the HTTP client implementation used. The message factory provides an implementation independent way to instantiate `Psr\RequestInterface` objects. -## History - -This project has been started by [Eric Geloen](https://github.com/egeloen) as [Ivory Http Adapter](https://github.com/egeloen/ivory-http-adapter). It never made it to be really stable, 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 adapters). +Httplug allows you to write reusable libraries and applications that need a HTTP client without binding to a specific implementation. When all packages used in an application only specify Httplug, the application developers can chose the client that fits best for their project and use the same client with all packages. -in 2015 a decision has been made to move the library to it's own organization, so PHP HTTP was born. +There are clients implementing the Httplug `Http\Client\HttpClient` interface directly, and adapter packages that implement the interface and forward the calls to HTTP clients not implementing the interface. ## Getting started -HTTP Adapter is separated into several components: - -- Adapter contract -- Client contract -- Adapter client -- Adapter implementations -- Helpers - - -### Installation - -There are many strategies how adapters and other components can be installed. However they are the same in one thing: they can be installed via [Composer](http://getcomposer.org/): - -``` bash -$ composer require php-http/adapter -``` - - -#### Installation in a reusable package +Read our [tutorial](tutorial.md). -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. -In these cases it is always a good idea not to rely on a concrete implementation (like Guzzle), but only require some implementation of an HTTP Adapter. With Composer, it is possible: +## Overview -``` json -{ - "require": { - "php-http/adapter-implementation": "^1.0" - } -} -``` +PHP-HTTP is separated into several packages: -This allows the end user to choose a concrete implementation when installs the package. Of course, during development a concrete implementation is needed: +- [Httplug](httplug.md), the HTTP client abstraction to send PSR-7 requests without binding to a specific implementation; +- [Message Factory](message-factory.md) to create PSR-7 requests without binding to a specific implementation; +- [Discovery](discovery.md) to automatically locate a suitable Httplug implementation and PSR-7 message and URI factories. +- [Utilities](utils.md) convenience tools to simplify working with Httplug in your applications. +See (package overview)[package-overview.md] for a complete list. -``` json -{ - "require-dev": { - "php-http/guzzle6-adapter": "^1.0" - } -} -``` +## History -Another good practice if the package works out-of-the-box, no or only minimal configuration is needed. While not requiring a concrete implementation is great, it also means that the end user would have to always inject the installed adapter (which is the right, but not a convenient solution). To solve this, there is a discovery components which finds and resolves other installed components: - -``` json -{ - "require": { - "php-http/discovery": "^1.0" - } -} -``` - -Read more about it in the [Discovery](discovery.md) part. - - -#### Installation in an end user package - -When installing in an application or a non-reusable package, requiring the virtual package doesn't really make sense. However there are a few things which should be taken into consideration before choosing an adapter: - -- It is possible that some other package already has an HTTP Client requirement. It can be confusing to have more than one HTTP Client installed, so always check your other requirements and choose an adapter based on that. -- Some adapters support parallel requests, some only emulate them. If parallel requests are needed, use one which supports it. - -Installing an implementation is easy: +This project has been started by [Eric Geloen](https://github.com/egeloen) as [Ivory Http Adapter](https://github.com/egeloen/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). -``` bash -$ composer require php-http/*-adapter -``` +In 2015, a decision has been made to move the library to it's own organization, so PHP HTTP was born. -_Replace * with any supported adapter name_ +See (migrating)[migrating.md] for a guide how to migrate your code from the Ivory adapter to Httplug. diff --git a/docs/message-factory.md b/docs/message-factory.md index b11b9cb..0f91c0a 100644 --- a/docs/message-factory.md +++ b/docs/message-factory.md @@ -5,7 +5,9 @@ ## Rationale -The FIG was pretty straightforward by NOT putting any construction logic into PSR-7. However there is a need for that. This does not try to be the "de facto" way to do message construction, but tries to provide an easy way to construct messages by following already existing patterns. (For example: `MessageFactory` accepts parameters in the order they appear in a request/response: method, uri, protocol version, headers, body (in case of a request)). +While it should be possible to use every PSR-7 aware HTTP client with any RequestInterface implementation, creating the request objects will still tie an application to a specific implementation. In the case of reusable libraries, an application could end up installing several request implementations. The factories abstract away from this. + +The FIG was pretty straightforward by NOT putting any construction logic into PSR-7. The `MessageFactory` aims to provide an easy way to construct messages by following already existing patterns. (For example: `MessageFactory` accepts parameters in the order they appear in a request/response: method, uri, protocol version, headers, body (in case of a request)). ## Usage @@ -20,8 +22,9 @@ This package provides interfaces for PSR-7 factories including: - `ClientContextFactory` (Combines `MessageFactory`, `StreamFactory` and `UriFactory`) -A virtual package ([php-http/message-factory-implementation](https://packagist.org/providers/php-http/message-factory-implementation)) MAY be introduced which MUST be versioned together with this package. +A [virtual package](virtual-package.md) ([php-http/message-factory-implementation](https://packagist.org/providers/php-http/message-factory-implementation)) MAY be introduced which MUST be versioned together with this package. +The adapter repositories provide wrapper classes for those factories to implement the `Http\Message\MessageFactory` interface. ### General usage diff --git a/docs/migrating.md b/docs/migrating.md new file mode 100644 index 0000000..9b73848 --- /dev/null +++ b/docs/migrating.md @@ -0,0 +1,21 @@ +# Migrating to Httplug + +If you currently use a concrete HTTP client implementation or the Ivory Http Adapter, migrating to Httplug should not be very hard. + + +## Migrating from Ivory Http Adapter + +The monolithic ivory package has been separated into several smaller, more specific packages. For a list of the packages, see the (package overview)[package-overview.md] + +Instead of `Ivory\HttpAdapter\PsrHttpAdapter`, use `Http\Client\HttpClient`. The HttpClient simply has a method to send requests. + +If you used the `Ivory\HttpAdapter\HttpAdapter`, have a look at the [Utilities](utils.md) and use the `Http\Client\Utils\HttpMethodsClient` which wraps any HttpClient and provides the convenience methods to send requests without creating RequestInterface instances. + + +## Migrating from Guzzle + +Replace usage of `GuzzleHttp\ClientInterface` with `Http\Client\HttpClient`. The `send` method is called `sendRequest`. Instead of the `$options` argument, configure the client appropriately during set up. If you need different settings, create different instances of the client. You can use [plugins](plugins.md) to further tune your client. + +If you used the `request` method, have a look at the [Utilities](utils.md) and use the `Http\Client\Utils\HttpMethodsClient` which wraps any HttpClient and provides the convenience methods to send requests without creating RequestInterface instances. + +Asynchronous request support will land in Httplug soon. diff --git a/docs/package-overview.md b/docs/package-overview.md new file mode 100644 index 0000000..8799210 --- /dev/null +++ b/docs/package-overview.md @@ -0,0 +1,48 @@ +# Overview of PHP-HTTP packages + +All packages are installed via [Composer](http://getcomposer.org/). + + +## httplug + +**Interfaces for HTTP Client** + +- Namespace: `Http\Client` +- Repository: https://github.com/php-http/httplug +- Documentation: (Httplug)[httplug.md] + + +## message-factory + +**Abstraction to create PSR-7 requests without binding to a specific implementation** + +- Namespace: `Http\Message` +- Repository: https://github.com/php-http/message-factory +- Documentation: [Message Factory](message-factory.md) + + +## *-client, *-adapter + +**Each client implementation is separated into its own package. This allows for clean requirement specification.** + +- Implementations: https://packagist.org/providers/php-http/client-implementation + +The clients are either full HTTP clients or adapters to wrap the Httplug Client interface around existing HTTP clients that do not implement the interface. + + +## discovery + +**Discovery service to find installed resources (httplug implementation, message factory)** + +- Namespace: `Http\Discovery` +- Repository: https://github.com/php-http/discovery +- Documentation: (Discovery)[discovery.md] + + +## utils + +**Utility classes for HTTP consumers** + +- Namespace: `Http\Utils` +- Repository: https://github.com/php-http/utils +- Documentation: (Utils)[utils.md] diff --git a/docs/plugins.md b/docs/plugins.md new file mode 100644 index 0000000..d5da2de --- /dev/null +++ b/docs/plugins.md @@ -0,0 +1,5 @@ +# Plugin System + +The plugin system will allow to manipulate requests and responses inside a `HttpClient`. + +TODO: finalize system and document. diff --git a/docs/tutorial.md b/docs/tutorial.md new file mode 100644 index 0000000..510fe2b --- /dev/null +++ b/docs/tutorial.md @@ -0,0 +1,46 @@ +# Httplug tutorial + +This tutorial should give you an idea how to use Httplug in your project. Httplug has two main use cases: + +1. Usage in your project; +2. Usage in a reusable package. + +This tutorial will start with the first use case and then explain the special considerations to take into account when building a reusable package. + +We use (composer)[https://getcomposer.org] for dependency management. Install it if you don't have it yet. + +## Setting up the project + +``` bash +mkdir httplug-tutorial +cd httplug-tutorial +composer init +# specify your information as you want. say no to defining the dependencies interactively +composer require php-http/guzzle6-adapter +``` + +The last command will install Guzzle as well as the Guzzle Httplug adapter and the required interface repositories. We are now ready to start coding. + +## Writing some simple code + +Create a file `demo.php` in the root folder and write the following code: + +``` php +get('http://example.com/foo'); +$bar = $client->get('http://example.com/bar', ['accept-encoding' => 'application/json']); +$post = $client->post('http://example.com/update', [], 'My post body'); +``` diff --git a/docs/virtual-package.md b/docs/virtual-package.md new file mode 100644 index 0000000..5bfdd23 --- /dev/null +++ b/docs/virtual-package.md @@ -0,0 +1,33 @@ +# 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. + + +# Using a Reusable Library + +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](https://packagist.org/providers/php-http/client-implementation). Failing to do that will lead to composer reporting this error: + +``` bash +$ composer update +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. +``` + +Doing something like the following will make this problem go away: + +``` bash +$ composer require php-http/guzzle6-adapter +``` + + +# Building a Reusable Library + +When *writing a reusable library*, the `require` section should only mention `php-http/client-implementation`, while the `require-dev` section needs to specify a concrete implementation in most cases, in order for the package to be installable on its own for development and testing. diff --git a/mkdocs.yml b/mkdocs.yml index d672076..ec4602f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: HTTP Adapter Documentation +site_name: PHP-HTTP Documentation theme: readthedocs extra_css: - css/extra.css