Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176

This commit is contained in:
Pantheon Automation 2015-08-17 17:00:26 -07:00 committed by Greg Anderson
commit 9921556621
13277 changed files with 1459781 additions and 0 deletions

View file

@ -0,0 +1,153 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Guzzle.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Guzzle.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/Guzzle"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Guzzle"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

View file

@ -0,0 +1,3 @@
<li><a href="https://github.com/guzzle/guzzle">GitHub</a></li>
<li><a href="https://groups.google.com/forum/?hl=en#!forum/guzzle">Forum</a></li>
<li><a href="irc:irc.freenode.com/#guzzlephp">IRC</a></li>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
import sys, os
from sphinx.highlighting import lexers
from pygments.lexers.web import PhpLexer
lexers['php'] = PhpLexer(startinline=True, linenos=1)
lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1)
primary_domain = 'php'
extensions = []
templates_path = ['_templates']
source_suffix = '.rst'
master_doc = 'index'
project = u'Guzzle'
copyright = u'2014, Michael Dowling'
version = '5.0.0'
html_title = "Guzzle Documentation"
html_short_title = "Guzzle"
exclude_patterns = ['_build']
html_static_path = ['_static']
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]

View file

@ -0,0 +1,520 @@
============
Event System
============
Guzzle uses an event emitter to allow you to easily extend the behavior of a
request, change the response associated with a request, and implement custom
error handling. All events in Guzzle are managed and emitted by an
**event emitter**.
Event Emitters
==============
Clients, requests, and any other class that implements the
``GuzzleHttp\Event\HasEmitterInterface`` interface have a
``GuzzleHttp\Event\Emitter`` object. You can add event *listeners* and
event *subscribers* to an event *emitter*.
emitter
An object that implements ``GuzzleHttp\Event\EmitterInterface``. This
object emits named events to event listeners. You may register event
listeners on subscribers on an emitter.
event listeners
Callable functions that are registered on an event emitter for specific
events. Event listeners are registered on an emitter with a *priority*
setting. If no priority is provided, ``0`` is used by default.
event subscribers
Classes that tell an event emitter what methods to listen to and what
functions on the class to invoke when the event is triggered. Event
subscribers subscribe event listeners to an event emitter. They should be
used when creating more complex event based logic in applications (i.e.,
cookie handling is implemented using an event subscriber because it's
easier to share a subscriber than an anonymous function and because
handling cookies is a complex process).
priority
Describes the order in which event listeners are invoked when an event is
emitted. The higher a priority value, the earlier the event listener will
be invoked (a higher priority means the listener is more important). If
no priority is provided, the priority is assumed to be ``0``.
When specifying an event priority, you can pass ``"first"`` or ``"last"`` to
dynamically specify the priority based on the current event priorities
associated with the given event name in the emitter. Use ``"first"`` to set
the priority to the current highest priority plus one. Use ``"last"`` to
set the priority to the current lowest event priority minus one. It is
important to remember that these dynamic priorities are calculated only at
the point of insertion into the emitter and they are not rearranged after
subsequent listeners are added to an emitter.
propagation
Describes whether or not other event listeners are triggered. Event
emitters will trigger every event listener registered to a specific event
in priority order until all of the listeners have been triggered **or**
until the propagation of an event is stopped.
Getting an EventEmitter
-----------------------
You can get the event emitter of ``GuzzleHttp\Event\HasEmitterInterface``
object using the the ``getEmitter()`` method. Here's an example of getting a
client object's event emitter.
.. code-block:: php
$client = new GuzzleHttp\Client();
$emitter = $client->getEmitter();
.. note::
You'll notice that the event emitter used in Guzzle is very similar to the
`Symfony2 EventDispatcher component <https://github.com/symfony/symfony/tree/master/src/Symfony/Component/EventDispatcher>`_.
This is because the Guzzle event system is based on the Symfony2 event
system with several changes. Guzzle uses its own event emitter to improve
performance, isolate Guzzle from changes to the Symfony, and provide a few
improvements that make it easier to use for an HTTP client (e.g., the
addition of the ``once()`` method).
Adding Event Listeners
----------------------
After you have the emitter, you can register event listeners that listen to
specific events using the ``on()`` method. When registering an event listener,
you must tell the emitter what event to listen to (e.g., "before", "after",
"progress", "complete", "error", etc.), what callable to invoke when the
event is triggered, and optionally provide a priority.
.. code-block:: php
use GuzzleHttp\Event\BeforeEvent;
$emitter->on('before', function (BeforeEvent $event) {
echo $event->getRequest();
});
When a listener is triggered, it is passed an event that implements the
``GuzzleHttp\Event\EventInterface`` interface, the name of the event, and the
event emitter itself. The above example could more verbosely be written as
follows:
.. code-block:: php
use GuzzleHttp\Event\BeforeEvent;
$emitter->on('before', function (
BeforeEvent $event,
$name,
EmitterInterface $emitter
) {
echo $event->getRequest();
});
You can add an event listener that automatically removes itself after it is
triggered using the ``once()`` method of an event emitter.
.. code-block:: php
$client = new GuzzleHttp\Client();
$client->getEmitter()->once('before', function () {
echo 'This will only happen once... per request!';
});
Event Propagation
-----------------
Event listeners can prevent other event listeners from being triggered by
stopping an event's propagation.
Stopping event propagation can be useful, for example, if an event listener has
changed the state of the subject to such an extent that allowing subsequent
event listeners to be triggered could place the subject in an inconsistent
state. This technique is used in Guzzle extensively when intercepting error
events with responses.
You can stop the propagation of an event using the ``stopPropagation()`` method
of a ``GuzzleHttp\Event\EventInterface`` object:
.. code-block:: php
use GuzzleHttp\Event\ErrorEvent;
$emitter->on('error', function (ErrorEvent $event) {
$event->stopPropagation();
});
After stopping the propagation of an event, any subsequent event listeners that
have not yet been triggered will not be triggered. You can check to see if the
propagation of an event was stopped using the ``isPropagationStopped()`` method
of the event.
.. code-block:: php
$client = new GuzzleHttp\Client();
$emitter = $client->getEmitter();
// Note: assume that the $errorEvent was created
if ($emitter->emit('error', $errorEvent)->isPropagationStopped()) {
echo 'It was stopped!';
}
.. hint::
When emitting events, the event that was emitted is returned from the
emitter. This allows you to easily chain calls as shown in the above
example.
Event Subscribers
-----------------
Event subscribers are classes that implement the
``GuzzleHttp\Event\SubscriberInterface`` object. They are used to register
one or more event listeners to methods of the class. Event subscribers tell
event emitters exactly which events to listen to and what method to invoke on
the class when the event is triggered by called the ``getEvents()`` method of
a subscriber.
The following example registers event listeners to the ``before`` and
``complete`` event of a request. When the ``before`` event is emitted, the
``onBefore`` instance method of the subscriber is invoked. When the
``complete`` event is emitted, the ``onComplete`` event of the subscriber is
invoked. Each array value in the ``getEvents()`` return value MUST
contain the name of the method to invoke and can optionally contain the
priority of the listener (as shown in the ``before`` listener in the example).
.. code-block:: php
use GuzzleHttp\Event\EmitterInterface;
use GuzzleHttp\Event\SubscriberInterface;
use GuzzleHttp\Event\BeforeEvent;
use GuzzleHttp\Event\CompleteEvent;
class SimpleSubscriber implements SubscriberInterface
{
public function getEvents()
{
return [
// Provide name and optional priority
'before' => ['onBefore', 100],
'complete' => ['onComplete'],
// You can pass a list of listeners with different priorities
'error' => [['beforeError', 'first'], ['afterError', 'last']]
];
}
public function onBefore(BeforeEvent $event, $name)
{
echo 'Before!';
}
public function onComplete(CompleteEvent $event, $name)
{
echo 'Complete!';
}
}
To register the listeners the subscriber needs to be attached to the emitter:
.. code-block:: php
$client = new GuzzleHttp\Client();
$emitter = $client->getEmitter();
$subscriber = new SimpleSubscriber();
$emitter->attach($subscriber);
//to remove the listeners
$emitter->detach($subscriber);
.. note::
You can specify event priorities using integers or ``"first"`` and
``"last"`` to dynamically determine the priority.
Event Priorities
================
When adding event listeners or subscribers, you can provide an optional event
priority. This priority is used to determine how early or late a listener is
triggered. Specifying the correct priority is an important aspect of ensuring
a listener behaves as expected. For example, if you wanted to ensure that
cookies associated with a redirect were added to a cookie jar, you'd need to
make sure that the listener that collects the cookies is triggered before the
listener that performs the redirect.
In order to help make the process of determining the correct event priority of
a listener easier, Guzzle provides several pre-determined named event
priorities. These priorities are exposed as constants on the
``GuzzleHttp\Event\RequestEvents`` object.
last
Use ``"last"`` as an event priority to set the priority to the current
lowest event priority minus one.
first
Use ``"first"`` as an event priority to set the priority to the current
highest priority plus one.
``GuzzleHttp\Event\RequestEvents::EARLY``
Used when you want a listener to be triggered as early as possible in the
event chain.
``GuzzleHttp\Event\RequestEvents::LATE``
Used when you want a listener to be to be triggered as late as possible in
the event chain.
``GuzzleHttp\Event\RequestEvents::PREPARE_REQUEST``
Used when you want a listener to be trigger while a request is being
prepared during the ``before`` event. This event priority is used by the
``GuzzleHttp\Subscriber\Prepare`` event subscriber which is responsible for
guessing a Content-Type, Content-Length, and Expect header of a request.
You should subscribe after this event is triggered if you want to ensure
that this subscriber has already been triggered.
``GuzzleHttp\Event\RequestEvents::SIGN_REQUEST``
Used when you want a listener to be triggered when a request is about to be
signed. Any listener triggered at this point should expect that the request
object will no longer be mutated. If you are implementing a custom
signature subscriber, then you should use this event priority to sign
requests.
``GuzzleHttp\Event\RequestEvents::VERIFY_RESPONSE``
Used when you want a listener to be triggered when a response is being
validated during the ``complete`` event. The
``GuzzleHttp\Subscriber\HttpError`` event subscriber uses this event
priority to check if an exception should be thrown due to a 4xx or 5xx
level response status code. If you are doing any kind of verification of a
response during the complete event, it should happen at this priority.
``GuzzleHttp\Event\RequestEvents::REDIRECT_RESPONSE``
Used when you want a listener to be triggered when a response is being
redirected during the ``complete`` event. The
``GuzzleHttp\Subscriber\Redirect`` event subscriber uses this event
priority when performing redirects.
You can use the above event priorities as a guideline for determining the
priority of you event listeners. You can use these constants and add to or
subtract from them to ensure that a listener happens before or after the named
priority.
.. note::
"first" and "last" priorities are not adjusted after they added to an
emitter. For example, if you add a listener with a priority of "first",
you can still add subsequent listeners with a higher priority which would
be triggered before the listener added with a priority of "first".
Working With Request Events
===========================
Requests emit lifecycle events when they are transferred.
.. important::
Excluding the ``end`` event, request lifecycle events may be triggered
multiple times due to redirects, retries, or reusing a request multiple
times. Use the ``once()`` method want the event to be triggered once. You
can also remove an event listener from an emitter by using the emitter which
is provided to the listener.
.. _before_event:
before
------
The ``before`` event is emitted before a request is sent. The event emitted is
a ``GuzzleHttp\Event\BeforeEvent``.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Event\EmitterInterface;
use GuzzleHttp\Event\BeforeEvent;
$client = new Client(['base_url' => 'http://httpbin.org']);
$request = $client->createRequest('GET', '/');
$request->getEmitter()->on(
'before',
function (BeforeEvent $e, $name, EmitterInterface $emitter) {
echo $name . "\n";
// "before"
echo $e->getRequest()->getMethod() . "\n";
// "GET" / "POST" / "PUT" / etc.
echo get_class($e->getClient());
// "GuzzleHttp\Client"
}
);
You can intercept a request with a response before the request is sent over the
wire. The ``intercept()`` method of the ``BeforeEvent`` accepts a
``GuzzleHttp\Message\ResponseInterface``. Intercepting the event will prevent
the request from being sent over the wire and stops the propagation of the
``before`` event, preventing subsequent event listeners from being invoked.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Event\BeforeEvent;
use GuzzleHttp\Message\Response;
$client = new Client(['base_url' => 'http://httpbin.org']);
$request = $client->createRequest('GET', '/status/500');
$request->getEmitter()->on('before', function (BeforeEvent $e) {
$response = new Response(200);
$e->intercept($response);
});
$response = $client->send($request);
echo $response->getStatusCode();
// 200
.. attention::
Any exception encountered while executing the ``before`` event will trigger
the ``error`` event of a request.
.. _complete_event:
complete
--------
The ``complete`` event is emitted after a transaction completes and an entire
response has been received. The event is a ``GuzzleHttp\Event\CompleteEvent``.
You can intercept the ``complete`` event with a different response if needed
using the ``intercept()`` method of the event. This can be useful, for example,
for changing the response for caching.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Event\CompleteEvent;
use GuzzleHttp\Message\Response;
$client = new Client(['base_url' => 'http://httpbin.org']);
$request = $client->createRequest('GET', '/status/302');
$cachedResponse = new Response(200);
$request->getEmitter()->on(
'complete',
function (CompleteEvent $e) use ($cachedResponse) {
if ($e->getResponse()->getStatusCode() == 302) {
// Intercept the original transaction with the new response
$e->intercept($cachedResponse);
}
}
);
$response = $client->send($request);
echo $response->getStatusCode();
// 200
.. attention::
Any ``GuzzleHttp\Exception\RequestException`` encountered while executing
the ``complete`` event will trigger the ``error`` event of a request.
.. _error_event:
error
-----
The ``error`` event is emitted when a request fails (whether it's from a
networking error or an HTTP protocol error). The event emitted is a
``GuzzleHttp\Event\ErrorEvent``.
This event is useful for retrying failed requests. Here's an example of
retrying failed basic auth requests by re-sending the original request with
a username and password.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Event\ErrorEvent;
$client = new Client(['base_url' => 'http://httpbin.org']);
$request = $client->createRequest('GET', '/basic-auth/foo/bar');
$request->getEmitter()->on('error', function (ErrorEvent $e) {
if ($e->getResponse()->getStatusCode() == 401) {
// Add authentication stuff as needed and retry the request
$e->getRequest()->setHeader('Authorization', 'Basic ' . base64_encode('foo:bar'));
// Get the client of the event and retry the request
$newResponse = $e->getClient()->send($e->getRequest());
// Intercept the original transaction with the new response
$e->intercept($newResponse);
}
});
.. attention::
If an ``error`` event is intercepted with a response, then the ``complete``
event of a request is triggered. If the ``complete`` event fails, then the
``error`` event is triggered once again.
.. _progress_event:
progress
--------
The ``progress`` event is emitted when data is uploaded or downloaded. The
event emitted is a ``GuzzleHttp\Event\ProgressEvent``.
You can access the emitted progress values using the corresponding public
properties of the event object:
- ``$downloadSize``: The number of bytes that will be downloaded (if known)
- ``$downloaded``: The number of bytes that have been downloaded
- ``$uploadSize``: The number of bytes that will be uploaded (if known)
- ``$uploaded``: The number of bytes that have been uploaded
This event cannot be intercepted.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Event\ProgressEvent;
$client = new Client(['base_url' => 'http://httpbin.org']);
$request = $client->createRequest('PUT', '/put', [
'body' => str_repeat('.', 100000)
]);
$request->getEmitter()->on('progress', function (ProgressEvent $e) {
echo 'Downloaded ' . $e->downloaded . ' of ' . $e->downloadSize . ' '
. 'Uploaded ' . $e->uploaded . ' of ' . $e->uploadSize . "\r";
});
$client->send($request);
echo "\n";
.. _end_event:
end
---
The ``end`` event is a terminal event, emitted once per request, that provides
access to the response that was received or the exception that was encountered.
The event emitted is a ``GuzzleHttp\Event\EndEvent``.
This event can be intercepted, but keep in mind that the ``complete`` event
will not fire after intercepting this event.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Event\EndEvent;
$client = new Client(['base_url' => 'http://httpbin.org']);
$request = $client->createRequest('PUT', '/put', [
'body' => str_repeat('.', 100000)
]);
$request->getEmitter()->on('end', function (EndEvent $e) {
if ($e->getException()) {
echo 'Error: ' . $e->getException()->getMessage();
} else {
echo 'Response: ' . $e->getResponse();
}
});
$client->send($request);
echo "\n";

View file

@ -0,0 +1,199 @@
===
FAQ
===
Why should I use Guzzle?
========================
Guzzle makes it easy to send HTTP requests and super simple to integrate with
web services. Guzzle manages things like persistent connections, represents
query strings as collections, makes it simple to send streaming POST requests
with fields and files, and abstracts away the underlying HTTP transport layer.
By providing an object oriented interface for HTTP clients, requests, responses,
headers, and message bodies, Guzzle makes it so that you no longer need to fool
around with cURL options, stream contexts, or sockets.
**Asynchronous and Synchronous Requests**
Guzzle allows you to send both asynchronous and synchronous requests using the
same interface and no direct dependency on an event loop. This flexibility
allows Guzzle to send an HTTP request using the most appropriate HTTP handler
based on the request being sent. For example, when sending synchronous
requests, Guzzle will by default send requests using cURL easy handles to
ensure you're using the fastest possible method for serially transferring HTTP
requests. When sending asynchronous requests, Guzzle might use cURL's multi
interface or any other asynchronous handler you configure. When you request
streaming data, Guzzle will by default use PHP's stream wrapper.
**Streams**
Request and response message bodies use :doc:`Guzzle Streams <streams>`,
allowing you to stream data without needing to load it all into memory.
Guzzle's stream layer provides a large suite of functionality:
- You can modify streams at runtime using custom or a number of
pre-made decorators.
- You can emit progress events as data is read from a stream.
- You can validate the integrity of a stream using a rolling hash as data is
read from a stream.
**Event System and Plugins**
Guzzle's event system allows you to completely modify the behavior of a client
or request at runtime to cater them for any API. You can send a request with a
client, and the client can do things like automatically retry your request if
it fails, automatically redirect, log HTTP messages that are sent over the
wire, emit progress events as data is uploaded and downloaded, sign requests
using OAuth 1.0, verify the integrity of messages before and after they are
sent over the wire, and anything else you might need.
**Testable**
Another important aspect of Guzzle is that it's really
:doc:`easy to test clients <testing>`. You can mock HTTP responses and when
testing an handler implementation, Guzzle provides a mock node.js web server.
**Ecosystem**
Guzzle has a large `ecosystem of plugins <http://guzzle.readthedocs.org/en/latest/index.html#http-components>`_,
including `service descriptions <https://github.com/guzzle/guzzle-services>`_
which allows you to abstract web services using service descriptions. These
service descriptions define how to serialize an HTTP request and how to parse
an HTTP response into a more meaningful model object.
- `Guzzle Command <https://github.com/guzzle/command>`_: Provides the building
blocks for service description abstraction.
- `Guzzle Services <https://github.com/guzzle/guzzle-services>`_: Provides an
implementation of "Guzzle Command" that utilizes Guzzle's service description
format.
Does Guzzle require cURL?
=========================
No. Guzzle can use any HTTP handler to send requests. This means that Guzzle
can be used with cURL, PHP's stream wrapper, sockets, and non-blocking libraries
like `React <http://reactphp.org/>`_. You just need to configure a
`RingPHP <http://guzzle-ring.readthedocs.org/en/latest/>`_ handler to use a
different method of sending requests.
.. note::
Guzzle has historically only utilized cURL to send HTTP requests. cURL is
an amazing HTTP client (arguably the best), and Guzzle will continue to use
it by default when it is available. It is rare, but some developers don't
have cURL installed on their systems or run into version specific issues.
By allowing swappable HTTP handlers, Guzzle is now much more customizable
and able to adapt to fit the needs of more developers.
Can Guzzle send asynchronous requests?
======================================
Yes. Pass the ``future`` true request option to a request to send it
asynchronously. Guzzle will then return a ``GuzzleHttp\Message\FutureResponse``
object that can be used synchronously by accessing the response object like a
normal response, and it can be used asynchronously using a promise that is
notified when the response is resolved with a real response or rejected with an
exception.
.. code-block:: php
$request = $client->createRequest('GET', ['future' => true]);
$client->send($request)->then(function ($response) {
echo 'Got a response! ' . $response;
});
You can force an asynchronous response to complete using the ``wait()`` method
of a response.
.. code-block:: php
$request = $client->createRequest('GET', ['future' => true]);
$futureResponse = $client->send($request);
$futureResponse->wait();
How can I add custom cURL options?
==================================
cURL offer a huge number of `customizable options <http://us1.php.net/curl_setopt>`_.
While Guzzle normalizes many of these options across different handlers, there
are times when you need to set custom cURL options. This can be accomplished
by passing an associative array of cURL settings in the **curl** key of the
**config** request option.
For example, let's say you need to customize the outgoing network interface
used with a client.
.. code-block:: php
$client->get('/', [
'config' => [
'curl' => [
CURLOPT_INTERFACE => 'xxx.xxx.xxx.xxx'
]
]
]);
How can I add custom stream context options?
============================================
You can pass custom `stream context options <http://www.php.net/manual/en/context.php>`_
using the **stream_context** key of the **config** request option. The
**stream_context** array is an associative array where each key is a PHP
transport, and each value is an associative array of transport options.
For example, let's say you need to customize the outgoing network interface
used with a client and allow self-signed certificates.
.. code-block:: php
$client->get('/', [
'stream' => true,
'config' => [
'stream_context' => [
'ssl' => [
'allow_self_signed' => true
],
'socket' => [
'bindto' => 'xxx.xxx.xxx.xxx'
]
]
]
]);
Why am I getting an SSL verification error?
===========================================
You need to specify the path on disk to the CA bundle used by Guzzle for
verifying the peer certificate. See :ref:`verify-option`.
What is this Maximum function nesting error?
============================================
Maximum function nesting level of '100' reached, aborting
You could run into this error if you have the XDebug extension installed and
you execute a lot of requests in callbacks. This error message comes
specifically from the XDebug extension. PHP itself does not have a function
nesting limit. Change this setting in your php.ini to increase the limit::
xdebug.max_nesting_level = 1000
Why am I getting a 417 error response?
======================================
This can occur for a number of reasons, but if you are sending PUT, POST, or
PATCH requests with an ``Expect: 100-Continue`` header, a server that does not
support this header will return a 417 response. You can work around this by
setting the ``expect`` request option to ``false``:
.. code-block:: php
$client = new GuzzleHttp\Client();
// Disable the expect header on a single request
$response = $client->put('/', [], 'the body', [
'expect' => false
]);
// Disable the expect header on all client requests
$client->setDefaultOption('expect', false)

View file

@ -0,0 +1,43 @@
================
RingPHP Handlers
================
Guzzle uses RingPHP handlers to send HTTP requests over the wire.
RingPHP provides a low-level library that can be used to "glue" Guzzle with
any transport method you choose. By default, Guzzle utilizes cURL and PHP's
stream wrappers to send HTTP requests.
RingPHP handlers makes it extremely simple to integrate Guzzle with any
HTTP transport. For example, you could quite easily bridge Guzzle and React
to use Guzzle in React's event loop.
Using a handler
---------------
You can change the handler used by a client using the ``handler`` option in the
``GuzzleHttp\Client`` constructor.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Ring\Client\MockHandler;
// Create a mock handler that always returns a 200 response.
$handler = new MockHandler(['status' => 200]);
// Configure to client to use the mock handler.
$client = new Client(['handler' => $handler]);
At its core, handlers are simply PHP callables that accept a request array
and return a ``GuzzleHttp\Ring\Future\FutureArrayInterface``. This future array
can be used just like a normal PHP array, causing it to block, or you can use
the promise interface using the ``then()`` method of the future. Guzzle hooks
up to the RingPHP project using a very simple bridge class
(``GuzzleHttp\RingBridge``).
Creating a handler
------------------
See the `RingPHP <http://ringphp.readthedocs.org>`_ project
documentation for more information on creating custom handlers that can be
used with Guzzle clients.

View file

@ -0,0 +1,483 @@
=============================
Request and Response Messages
=============================
Guzzle is an HTTP client that sends HTTP requests to a server and receives HTTP
responses. Both requests and responses are referred to as messages.
Headers
=======
Both request and response messages contain HTTP headers.
Complex Headers
---------------
Some headers contain additional key value pair information. For example, Link
headers contain a link and several key value pairs:
::
<http://foo.com>; rel="thing"; type="image/jpeg"
Guzzle provides a convenience feature that can be used to parse these types of
headers:
.. code-block:: php
use GuzzleHttp\Message\Request;
$request = new Request('GET', '/', [
'Link' => '<http:/.../front.jpeg>; rel="front"; type="image/jpeg"'
]);
$parsed = Request::parseHeader($request, 'Link');
var_export($parsed);
Will output:
.. code-block:: php
array (
0 =>
array (
0 => '<http:/.../front.jpeg>',
'rel' => 'front',
'type' => 'image/jpeg',
),
)
The result contains a hash of key value pairs. Header values that have no key
(i.e., the link) are indexed numerically while headers parts that form a key
value pair are added as a key value pair.
See :ref:`headers` for information on how the headers of a request and response
can be accessed and modified.
Body
====
Both request and response messages can contain a body.
You can check to see if a request or response has a body using the
``getBody()`` method:
.. code-block:: php
$response = GuzzleHttp\get('http://httpbin.org/get');
if ($response->getBody()) {
echo $response->getBody();
// JSON string: { ... }
}
The body used in request and response objects is a
``GuzzleHttp\Stream\StreamInterface``. This stream is used for both uploading
data and downloading data. Guzzle will, by default, store the body of a message
in a stream that uses PHP temp streams. When the size of the body exceeds
2 MB, the stream will automatically switch to storing data on disk rather than
in memory (protecting your application from memory exhaustion).
You can change the body used in a request or response using the ``setBody()``
method:
.. code-block:: php
use GuzzleHttp\Stream\Stream;
$request = $client->createRequest('PUT', 'http://httpbin.org/put');
$request->setBody(Stream::factory('foo'));
The easiest way to create a body for a request is using the static
``GuzzleHttp\Stream\Stream::factory()`` method. This method accepts various
inputs like strings, resources returned from ``fopen()``, and other
``GuzzleHttp\Stream\StreamInterface`` objects.
The body of a request or response can be cast to a string or you can read and
write bytes off of the stream as needed.
.. code-block:: php
use GuzzleHttp\Stream\Stream;
$request = $client->createRequest('PUT', 'http://httpbin.org/put', ['body' => 'testing...']);
echo $request->getBody()->read(4);
// test
echo $request->getBody()->read(4);
// ing.
echo $request->getBody()->read(1024);
// ..
var_export($request->eof());
// true
You can find out more about Guzzle stream objects in :doc:`streams`.
Requests
========
Requests are sent from a client to a server. Requests include the method to
be applied to a resource, the identifier of the resource, and the protocol
version to use.
Clients are used to create request messages. More precisely, clients use
a ``GuzzleHttp\Message\MessageFactoryInterface`` to create request messages.
You create requests with a client using the ``createRequest()`` method.
.. code-block:: php
// Create a request but don't send it immediately
$request = $client->createRequest('GET', 'http://httpbin.org/get');
Request Methods
---------------
When creating a request, you are expected to provide the HTTP method you wish
to perform. You can specify any method you'd like, including a custom method
that might not be part of RFC 7231 (like "MOVE").
.. code-block:: php
// Create a request using a completely custom HTTP method
$request = $client->createRequest('MOVE', 'http://httpbin.org/move', ['exceptions' => false]);
echo $request->getMethod();
// MOVE
$response = $client->send($request);
echo $response->getStatusCode();
// 405
You can create and send a request using methods on a client that map to the
HTTP method you wish to use.
:GET: ``$client->get('http://httpbin.org/get', [/** options **/])``
:POST: ``$client->post('http://httpbin.org/post', [/** options **/])``
:HEAD: ``$client->head('http://httpbin.org/get', [/** options **/])``
:PUT: ``$client->put('http://httpbin.org/put', [/** options **/])``
:DELETE: ``$client->delete('http://httpbin.org/delete', [/** options **/])``
:OPTIONS: ``$client->options('http://httpbin.org/get', [/** options **/])``
:PATCH: ``$client->patch('http://httpbin.org/put', [/** options **/])``
.. code-block:: php
$response = $client->patch('http://httpbin.org/patch', ['body' => 'content']);
Request URI
-----------
The resource you are requesting with an HTTP request is identified by the
path of the request, the query string, and the "Host" header of the request.
When creating a request, you can provide the entire resource URI as a URL.
.. code-block:: php
$response = $client->get('http://httbin.org/get?q=foo');
Using the above code, you will send a request that uses ``httpbin.org`` as
the Host header, sends the request over port 80, uses ``/get`` as the path,
and sends ``?q=foo`` as the query string. All of this is parsed automatically
from the provided URI.
Sometimes you don't know what the entire request will be when it is created.
In these cases, you can modify the request as needed before sending it using
the ``createRequest()`` method of the client and methods on the request that
allow you to change it.
.. code-block:: php
$request = $client->createRequest('GET', 'http://httbin.org');
You can change the path of the request using ``setPath()``:
.. code-block:: php
$request->setPath('/get');
echo $request->getPath();
// /get
echo $request->getUrl();
// http://httpbin.com/get
Scheme
~~~~~~
The `scheme <http://tools.ietf.org/html/rfc3986#section-3.1>`_ of a request
specifies the protocol to use when sending the request. When using Guzzle, the
scheme can be set to "http" or "https".
You can change the scheme of the request using the ``setScheme()`` method:
.. code-block:: php
$request = $client->createRequest('GET', 'http://httbin.org');
$request->setScheme('https');
echo $request->getScheme();
// https
echo $request->getUrl();
// https://httpbin.com/get
Port
~~~~
No port is necessary when using the "http" or "https" schemes, but you can
override the port using ``setPort()``. If you need to modify the port used with
the specified scheme from the default setting, then you must use the
``setPort()`` method.
.. code-block:: php
$request = $client->createRequest('GET', 'http://httbin.org');
$request->setPort(8080);
echo $request->getPort();
// 8080
echo $request->getUrl();
// https://httpbin.com:8080/get
// Set the port back to the default value for the scheme
$request->setPort(443);
echo $request->getUrl();
// https://httpbin.com/get
Query string
~~~~~~~~~~~~
You can get the query string of the request using the ``getQuery()`` method.
This method returns a ``GuzzleHttp\Query`` object. A Query object can be
accessed like a PHP array, iterated in a foreach statement like a PHP array,
and cast to a string.
.. code-block:: php
$request = $client->createRequest('GET', 'http://httbin.org');
$query = $request->getQuery();
$query['foo'] = 'bar';
$query['baz'] = 'bam';
$query['bam'] = ['test' => 'abc'];
echo $request->getQuery();
// foo=bar&baz=bam&bam%5Btest%5D=abc
echo $request->getQuery()['foo'];
// bar
echo $request->getQuery()->get('foo');
// bar
echo $request->getQuery()->get('foo');
// bar
var_export($request->getQuery()['bam']);
// array('test' => 'abc')
foreach ($query as $key => $value) {
var_export($value);
}
echo $request->getUrl();
// https://httpbin.com/get?foo=bar&baz=bam&bam%5Btest%5D=abc
Query Aggregators
^^^^^^^^^^^^^^^^^
Query objects can store scalar values or arrays of values. When an array of
values is added to a query object, the query object uses a query aggregator to
convert the complex structure into a string. Query objects will use
`PHP style query strings <http://www.php.net/http_build_query>`_ when complex
query string parameters are converted to a string. You can customize how
complex query string parameters are aggregated using the ``setAggregator()``
method of a query string object.
.. code-block:: php
$query->setAggregator($query::duplicateAggregator());
In the above example, we've changed the query object to use the
"duplicateAggregator". This aggregator will allow duplicate entries to appear
in a query string rather than appending "[n]" to each value. So if you had a
query string with ``['a' => ['b', 'c']]``, the duplicate aggregator would
convert this to "a=b&a=c" while the default aggregator would convert this to
"a[0]=b&a[1]=c" (with urlencoded brackets).
The ``setAggregator()`` method accepts a ``callable`` which is used to convert
a deeply nested array of query string variables into a flattened array of key
value pairs. The callable accepts an array of query data and returns a
flattened array of key value pairs where each value is an array of strings.
You can use the ``GuzzleHttp\Query::walkQuery()`` static function to easily
create custom query aggregators.
Host
~~~~
You can change the host header of the request in a predictable way using the
``setHost()`` method of a request:
.. code-block:: php
$request->setHost('www.google.com');
echo $request->getHost();
// www.google.com
echo $request->getUrl();
// https://www.google.com/get?foo=bar&baz=bam
.. note::
The Host header can also be changed by modifying the Host header of a
request directly, but modifying the Host header directly could result in
sending a request to a different Host than what is specified in the Host
header (sometimes this is actually the desired behavior).
Resource
~~~~~~~~
You can use the ``getResource()`` method of a request to return the path and
query string of a request in a single string.
.. code-block:: php
$request = $client->createRequest('GET', 'http://httpbin.org/get?baz=bar');
echo $request->getResource();
// /get?baz=bar
Request Config
--------------
Request messages contain a configuration collection that can be used by
event listeners and HTTP handlers to modify how a request behaves or is
transferred over the wire. For example, many of the request options that are
specified when creating a request are actually set as config options that are
only acted upon by handlers and listeners when the request is sent.
You can get access to the request's config object using the ``getConfig()``
method of a request.
.. code-block:: php
$request = $client->createRequest('GET', '/');
$config = $request->getConfig();
The config object is a ``GuzzleHttp\Collection`` object that acts like
an associative array. You can grab values from the collection using array like
access. You can also modify and remove values using array like access.
.. code-block:: php
$config['foo'] = 'bar';
echo $config['foo'];
// bar
var_export(isset($config['foo']));
// true
unset($config['foo']);
var_export(isset($config['foo']));
// false
var_export($config['foo']);
// NULL
HTTP handlers and event listeners can expose additional customization options
through request config settings. For example, in order to specify custom cURL
options to the cURL handler, you need to specify an associative array in the
``curl`` ``config`` request option.
.. code-block:: php
$client->get('/', [
'config' => [
'curl' => [
CURLOPT_HTTPAUTH => CURLAUTH_NTLM,
CURLOPT_USERPWD => 'username:password'
]
]
]);
Consult the HTTP handlers and event listeners you are using to see if they
allow customization through request configuration options.
Event Emitter
-------------
Request objects implement ``GuzzleHttp\Event\HasEmitterInterface``, so they
have a method called ``getEmitter()`` that can be used to get an event emitter
used by the request. Any listener or subscriber attached to a request will only
be triggered for the lifecycle events of a specific request. Conversely, adding
an event listener or subscriber to a client will listen to all lifecycle events
of all requests created by the client.
See :doc:`events` for more information.
Responses
=========
Responses are the HTTP messages a client receives from a server after sending
an HTTP request message.
Start-Line
----------
The start-line of a response contains the protocol and protocol version,
status code, and reason phrase.
.. code-block:: php
$response = GuzzleHttp\get('http://httpbin.org/get');
echo $response->getStatusCode();
// 200
echo $response->getReasonPhrase();
// OK
echo $response->getProtocolVersion();
// 1.1
Body
----
As described earlier, you can get the body of a response using the
``getBody()`` method.
.. code-block:: php
if ($body = $response->getBody()) {
echo $body;
// Cast to a string: { ... }
$body->seek(0);
// Rewind the body
$body->read(1024);
// Read bytes of the body
}
When working with JSON responses, you can use the ``json()`` method of a
response:
.. code-block:: php
$json = $response->json();
.. note::
Guzzle uses the ``json_decode()`` method of PHP and uses arrays rather than
``stdClass`` objects for objects.
You can use the ``xml()`` method when working with XML data.
.. code-block:: php
$xml = $response->xml();
.. note::
Guzzle uses the ``SimpleXMLElement`` objects when converting response
bodies to XML.
Effective URL
-------------
The URL that was ultimately accessed that returned a response can be accessed
using the ``getEffectiveUrl()`` method of a response. This method will return
the URL of a request or the URL of the last redirected URL if any redirects
occurred while transferring a request.
.. code-block:: php
$response = GuzzleHttp\get('http://httpbin.org/get');
echo $response->getEffectiveUrl();
// http://httpbin.org/get
$response = GuzzleHttp\get('http://httpbin.org/redirect-to?url=http://www.google.com');
echo $response->getEffectiveUrl();
// http://www.google.com

View file

@ -0,0 +1,98 @@
.. title:: Guzzle | PHP HTTP client and framework for consuming RESTful web services
======
Guzzle
======
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
trivial to integrate with web services.
- Manages things like persistent connections, represents query strings as
collections, simplifies sending streaming POST requests with fields and
files, and abstracts away the underlying HTTP transport layer.
- Can send both synchronous and asynchronous requests using the same interface
without requiring a dependency on a specific event loop.
- Pluggable HTTP handlers allows Guzzle to integrate with any method you choose
for sending HTTP requests over the wire (e.g., cURL, sockets, PHP's stream
wrapper, non-blocking event loops like `React <http://reactphp.org/>`_, etc.).
- Guzzle makes it so that you no longer need to fool around with cURL options,
stream contexts, or sockets.
.. code-block:: php
$client = new GuzzleHttp\Client();
$response = $client->get('http://guzzlephp.org');
$res = $client->get('https://api.github.com/user', ['auth' => ['user', 'pass']]);
echo $res->getStatusCode();
// "200"
echo $res->getHeader('content-type');
// 'application/json; charset=utf8'
echo $res->getBody();
// {"type":"User"...'
var_export($res->json());
// Outputs the JSON decoded data
// Send an asynchronous request.
$req = $client->createRequest('GET', 'http://httpbin.org', ['future' => true]);
$client->send($req)->then(function ($response) {
echo 'I completed! ' . $response;
});
User guide
----------
.. toctree::
:maxdepth: 2
overview
quickstart
clients
http-messages
events
streams
handlers
testing
faq
HTTP Components
---------------
There are a number of optional libraries you can use along with Guzzle's HTTP
layer to add capabilities to the client.
`Log Subscriber <https://github.com/guzzle/log-subscriber>`_
Logs HTTP requests and responses sent over the wire using customizable
log message templates.
`OAuth Subscriber <https://github.com/guzzle/oauth-subscriber>`_
Signs requests using OAuth 1.0.
`Cache Subscriber <https://github.com/guzzle/cache-subscriber>`_
Implements a private transparent proxy cache that caches HTTP responses.
`Retry Subscriber <https://github.com/guzzle/retry-subscriber>`_
Retries failed requests using customizable retry strategies (e.g., retry
based on response status code, cURL error codes, etc.)
`Message Integrity Subscriber <https://github.com/guzzle/message-integrity-subscriber>`_
Verifies the message integrity of HTTP responses using customizable
validators. This plugin can be used, for example, to verify the Content-MD5
headers of responses.
Service Description Commands
----------------------------
You can use the **Guzzle Command** library to encapsulate interaction with a
web service using command objects. Building on top of Guzzle's command
abstraction allows you to easily implement things like service description that
can be used to serialize requests and parse responses using a meta-description
of a web service.
`Guzzle Command <https://github.com/guzzle/command>`_
Provides the foundational elements used to build high-level, command based,
web service clients with Guzzle.
`Guzzle Services <https://github.com/guzzle/guzzle-services>`_
Provides an implementation of the *Guzzle Command* library that uses
Guzzle service descriptions to describe web services, serialize requests,
and parse responses into easy to use model structures.

View file

@ -0,0 +1,150 @@
========
Overview
========
Requirements
============
#. PHP 5.4.0
#. To use the PHP stream handler, ``allow_url_fopen`` must be enabled in your
system's php.ini.
#. To use the cURL handler, you must have a recent version of cURL >= 7.16.2
compiled with OpenSSL and zlib.
.. note::
Guzzle no longer requires cURL in order to send HTTP requests. Guzzle will
use the PHP stream wrapper to send HTTP requests if cURL is not installed.
Alternatively, you can provide your own HTTP handler used to send requests.
.. _installation:
Installation
============
The recommended way to install Guzzle is with `Composer <http://getcomposer.org>`_. Composer is a dependency
management tool for PHP that allows you to declare the dependencies your project needs and installs them into your
project.
.. code-block:: bash
# Install Composer
curl -sS https://getcomposer.org/installer | php
You can add Guzzle as a dependency using the composer.phar CLI:
.. code-block:: bash
php composer.phar require guzzlehttp/guzzle:~5.0
Alternatively, you can specify Guzzle as a dependency in your project's
existing composer.json file:
.. code-block:: js
{
"require": {
"guzzlehttp/guzzle": "~5.0"
}
}
After installing, you need to require Composer's autoloader:
.. code-block:: php
require 'vendor/autoload.php';
You can find out more on how to install Composer, configure autoloading, and
other best-practices for defining dependencies at `getcomposer.org <http://getcomposer.org>`_.
Bleeding edge
-------------
During your development, you can keep up with the latest changes on the master
branch by setting the version requirement for Guzzle to ``~5.0@dev``.
.. code-block:: js
{
"require": {
"guzzlehttp/guzzle": "~5.0@dev"
}
}
License
=======
Licensed using the `MIT license <http://opensource.org/licenses/MIT>`_.
Copyright (c) 2014 Michael Dowling <https://github.com/mtdowling>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Contributing
============
Guidelines
----------
1. Guzzle follows PSR-0, PSR-1, and PSR-2.
2. Guzzle is meant to be lean and fast with very few dependencies.
3. Guzzle has a minimum PHP version requirement of PHP 5.4. Pull requests must
not require a PHP version greater than PHP 5.4.
4. All pull requests must include unit tests to ensure the change works as
expected and to prevent regressions.
Running the tests
-----------------
In order to contribute, you'll need to checkout the source from GitHub and
install Guzzle's dependencies using Composer:
.. code-block:: bash
git clone https://github.com/guzzle/guzzle.git
cd guzzle && curl -s http://getcomposer.org/installer | php && ./composer.phar install --dev
Guzzle is unit tested with PHPUnit. Run the tests using the vendored PHPUnit
binary:
.. code-block:: bash
vendor/bin/phpunit
.. note::
You'll need to install node.js v0.5.0 or newer in order to perform
integration tests on Guzzle's HTTP handlers.
Reporting a security vulnerability
==================================
We want to ensure that Guzzle is a secure HTTP client library for everyone. If
you've discovered a security vulnerability in Guzzle, we appreciate your help
in disclosing it to us in a `responsible manner <http://en.wikipedia.org/wiki/Responsible_disclosure>`_.
Publicly disclosing a vulnerability can put the entire community at risk. If
you've discovered a security concern, please email us at
security@guzzlephp.org. We'll work with you to make sure that we understand the
scope of the issue, and that we fully address your concern. We consider
correspondence sent to security@guzzlephp.org our highest priority, and work to
address any issues that arise as quickly as possible.
After a security vulnerability has been corrected, a security hotfix release will
be deployed as soon as possible.

View file

@ -0,0 +1,448 @@
==========
Quickstart
==========
This page provides a quick introduction to Guzzle and introductory examples.
If you have not already installed, Guzzle, head over to the :ref:`installation`
page.
Make a Request
==============
You can send requests with Guzzle using a ``GuzzleHttp\ClientInterface``
object.
Creating a Client
-----------------
The procedural API is simple but not very testable; it's best left for quick
prototyping. If you want to use Guzzle in a more flexible and testable way,
then you'll need to use a ``GuzzleHttp\ClientInterface`` object.
.. code-block:: php
use GuzzleHttp\Client;
$client = new Client();
$response = $client->get('http://httpbin.org/get');
// You can use the same methods you saw in the procedural API
$response = $client->delete('http://httpbin.org/delete');
$response = $client->head('http://httpbin.org/get');
$response = $client->options('http://httpbin.org/get');
$response = $client->patch('http://httpbin.org/patch');
$response = $client->post('http://httpbin.org/post');
$response = $client->put('http://httpbin.org/put');
You can create a request with a client and then send the request with the
client when you're ready.
.. code-block:: php
$request = $client->createRequest('GET', 'http://www.foo.com');
$response = $client->send($request);
Client objects provide a great deal of flexibility in how request are
transferred including default request options, subscribers that are attached
to each request, and a base URL that allows you to send requests with relative
URLs. You can find out all about clients in the :doc:`clients` page of the
documentation.
Using Responses
===============
In the previous examples, we retrieved a ``$response`` variable. This value is
actually a ``GuzzleHttp\Message\ResponseInterface`` object and contains lots
of helpful information.
You can get the status code and reason phrase of the response.
.. code-block:: php
$code = $response->getStatusCode();
// 200
$reason = $response->getReasonPhrase();
// OK
By providing the ``future`` request option to a request, you can send requests
asynchronously using the promise interface of a future response.
.. code-block:: php
$client->get('http://httpbin.org', ['future' => true])
->then(function ($response) {
echo $response->getStatusCode();
});
Response Body
-------------
The body of a response can be retrieved and cast to a string.
.. code-block:: php
$body = $response->getBody();
echo $body;
// { "some_json_data" ...}
You can also read read bytes from body of a response like a stream.
.. code-block:: php
$body = $response->getBody();
while (!$body->eof()) {
echo $body->read(1024);
}
JSON Responses
~~~~~~~~~~~~~~
You can more easily work with JSON responses using the ``json()`` method of a
response.
.. code-block:: php
$response = $client->get('http://httpbin.org/get');
$json = $response->json();
var_dump($json[0]['origin']);
Guzzle internally uses PHP's ``json_decode()`` function to parse responses. If
Guzzle is unable to parse the JSON response body, then a
``GuzzleHttp\Exception\ParseException`` is thrown.
XML Responses
~~~~~~~~~~~~~
You can use a response's ``xml()`` method to more easily work with responses
that contain XML data.
.. code-block:: php
$response = $client->get('https://github.com/mtdowling.atom');
$xml = $response->xml();
echo $xml->id;
// tag:github.com,2008:/mtdowling
Guzzle internally uses a ``SimpleXMLElement`` object to parse responses. If
Guzzle is unable to parse the XML response body, then a
``GuzzleHttp\Exception\ParseException`` is thrown.
Query String Parameters
=======================
Sending query string parameters with a request is easy. You can set query
string parameters in the request's URL.
.. code-block:: php
$response = $client->get('http://httpbin.org?foo=bar');
You can also specify the query string parameters using the ``query`` request
option.
.. code-block:: php
$client->get('http://httpbin.org', [
'query' => ['foo' => 'bar']
]);
And finally, you can build up the query string of a request as needed by
calling the ``getQuery()`` method of a request and modifying the request's
``GuzzleHttp\Query`` object as needed.
.. code-block:: php
$request = $client->createRequest('GET', 'http://httpbin.org');
$query = $request->getQuery();
$query->set('foo', 'bar');
// You can use the query string object like an array
$query['baz'] = 'bam';
// The query object can be cast to a string
echo $query;
// foo=bar&baz=bam
// Setting a value to false or null will cause the "=" sign to be omitted
$query['empty'] = null;
echo $query;
// foo=bar&baz=bam&empty
// Use an empty string to include the "=" sign with an empty value
$query['empty'] = '';
echo $query;
// foo=bar&baz=bam&empty=
.. _headers:
Request and Response Headers
----------------------------
You can specify request headers when sending or creating requests with a
client. In the following example, we send the ``X-Foo-Header`` with a value of
``value`` by setting the ``headers`` request option.
.. code-block:: php
$response = $client->get('http://httpbin.org/get', [
'headers' => ['X-Foo-Header' => 'value']
]);
You can view the headers of a response using header specific methods of a
response class. Headers work exactly the same way for request and response
object.
You can retrieve a header from a request or response using the ``getHeader()``
method of the object. This method is case-insensitive and by default will
return a string containing the header field value.
.. code-block:: php
$response = $client->get('http://www.yahoo.com');
$length = $response->getHeader('Content-Length');
Header fields that contain multiple values can be retrieved as a string or as
an array. Retrieving the field values as a string will naively concatenate all
of the header values together with a comma. Because not all header fields
should be represented this way (e.g., ``Set-Cookie``), you can pass an optional
flag to the ``getHeader()`` method to retrieve the header values as an array.
.. code-block:: php
$values = $response->getHeader('Set-Cookie', true);
foreach ($values as $value) {
echo $value;
}
You can test if a request or response has a specific header using the
``hasHeader()`` method. This method accepts a case-insensitive string and
returns true if the header is present or false if it is not.
You can retrieve all of the headers of a message using the ``getHeaders()``
method of a request or response. The return value is an associative array where
the keys represent the header name as it will be sent over the wire, and each
value is an array of strings associated with the header.
.. code-block:: php
$headers = $response->getHeaders();
foreach ($message->getHeaders() as $name => $values) {
echo $name . ": " . implode(", ", $values);
}
Modifying headers
-----------------
The headers of a message can be modified using the ``setHeader()``,
``addHeader()``, ``setHeaders()``, and ``removeHeader()`` methods of a request
or response object.
.. code-block:: php
$request = $client->createRequest('GET', 'http://httpbin.org/get');
// Set a single value for a header
$request->setHeader('User-Agent', 'Testing!');
// Set multiple values for a header in one call
$request->setHeader('X-Foo', ['Baz', 'Bar']);
// Add a header to the message
$request->addHeader('X-Foo', 'Bam');
echo $request->getHeader('X-Foo');
// Baz, Bar, Bam
// Remove a specific header using a case-insensitive name
$request->removeHeader('x-foo');
echo $request->getHeader('X-Foo');
// Echoes an empty string: ''
Uploading Data
==============
Guzzle provides several methods of uploading data.
You can send requests that contain a stream of data by passing a string,
resource returned from ``fopen``, or a ``GuzzleHttp\Stream\StreamInterface``
object to the ``body`` request option.
.. code-block:: php
$r = $client->post('http://httpbin.org/post', ['body' => 'raw data']);
You can easily upload JSON data using the ``json`` request option.
.. code-block:: php
$r = $client->put('http://httpbin.org/put', ['json' => ['foo' => 'bar']]);
POST Requests
-------------
In addition to specifying the raw data of a request using the ``body`` request
option, Guzzle provides helpful abstractions over sending POST data.
Sending POST Fields
~~~~~~~~~~~~~~~~~~~
Sending ``application/x-www-form-urlencoded`` POST requests requires that you
specify the body of a POST request as an array.
.. code-block:: php
$response = $client->post('http://httpbin.org/post', [
'body' => [
'field_name' => 'abc',
'other_field' => '123'
]
]);
You can also build up POST requests before sending them.
.. code-block:: php
$request = $client->createRequest('POST', 'http://httpbin.org/post');
$postBody = $request->getBody();
// $postBody is an instance of GuzzleHttp\Post\PostBodyInterface
$postBody->setField('foo', 'bar');
echo $postBody->getField('foo');
// 'bar'
echo json_encode($postBody->getFields());
// {"foo": "bar"}
// Send the POST request
$response = $client->send($request);
Sending POST Files
~~~~~~~~~~~~~~~~~~
Sending ``multipart/form-data`` POST requests (POST requests that contain
files) is the same as sending ``application/x-www-form-urlencoded``, except
some of the array values of the POST fields map to PHP ``fopen`` resources, or
``GuzzleHttp\Stream\StreamInterface``, or
``GuzzleHttp\Post\PostFileInterface`` objects.
.. code-block:: php
use GuzzleHttp\Post\PostFile;
$response = $client->post('http://httpbin.org/post', [
'body' => [
'field_name' => 'abc',
'file_filed' => fopen('/path/to/file', 'r'),
'other_file' => new PostFile('other_file', 'this is the content')
]
]);
Just like when sending POST fields, you can also build up POST requests with
files before sending them.
.. code-block:: php
use GuzzleHttp\Post\PostFile;
$request = $client->createRequest('POST', 'http://httpbin.org/post');
$postBody = $request->getBody();
$postBody->setField('foo', 'bar');
$postBody->addFile(new PostFile('test', fopen('/path/to/file', 'r')));
$response = $client->send($request);
Cookies
=======
Guzzle can maintain a cookie session for you if instructed using the
``cookies`` request option.
- Set to ``true`` to use a shared cookie session associated with the client.
- Pass an associative array containing cookies to send in the request and start
a new cookie session.
- Set to a ``GuzzleHttp\Subscriber\CookieJar\CookieJarInterface`` object to use
an existing cookie jar.
Redirects
=========
Guzzle will automatically follow redirects unless you tell it not to. You can
customize the redirect behavior using the ``allow_redirects`` request option.
- Set to true to enable normal redirects with a maximum number of 5 redirects.
This is the default setting.
- Set to false to disable redirects.
- Pass an associative array containing the 'max' key to specify the maximum
number of redirects and optionally provide a 'strict' key value to specify
whether or not to use strict RFC compliant redirects (meaning redirect POST
requests with POST requests vs. doing what most browsers do which is
redirect POST requests with GET requests).
.. code-block:: php
$response = $client->get('http://github.com');
echo $response->getStatusCode();
// 200
echo $response->getEffectiveUrl();
// 'https://github.com/'
The following example shows that redirects can be disabled.
.. code-block:: php
$response = $client->get('http://github.com', ['allow_redirects' => false]);
echo $response->getStatusCode();
// 301
echo $response->getEffectiveUrl();
// 'http://github.com/'
Exceptions
==========
Guzzle throws exceptions for errors that occur during a transfer.
- In the event of a networking error (connection timeout, DNS errors, etc.),
a ``GuzzleHttp\Exception\RequestException`` is thrown. This exception
extends from ``GuzzleHttp\Exception\TransferException``. Catching this
exception will catch any exception that can be thrown while transferring
(non-parallel) requests.
.. code-block:: php
use GuzzleHttp\Exception\RequestException;
try {
$client->get('https://github.com/_abc_123_404');
} catch (RequestException $e) {
echo $e->getRequest();
if ($e->hasResponse()) {
echo $e->getResponse();
}
}
- A ``GuzzleHttp\Exception\ClientException`` is thrown for 400
level errors if the ``exceptions`` request option is set to true. This
exception extends from ``GuzzleHttp\Exception\BadResponseException`` and
``GuzzleHttp\Exception\BadResponseException`` extends from
``GuzzleHttp\Exception\RequestException``.
.. code-block:: php
use GuzzleHttp\Exception\ClientException;
try {
$client->get('https://github.com/_abc_123_404');
} catch (ClientException $e) {
echo $e->getRequest();
echo $e->getResponse();
}
- A ``GuzzleHttp\Exception\ServerException`` is thrown for 500 level
errors if the ``exceptions`` request option is set to true. This
exception extends from ``GuzzleHttp\Exception\BadResponseException``.
- A ``GuzzleHttp\Exception\TooManyRedirectsException`` is thrown when too
many redirects are followed. This exception extends from ``GuzzleHttp\Exception\RequestException``.
All of the above exceptions extend from
``GuzzleHttp\Exception\TransferException``.

View file

@ -0,0 +1,2 @@
Sphinx>=1.2b1
guzzle_sphinx_theme>=0.6.0

View file

@ -0,0 +1,213 @@
=======
Streams
=======
Guzzle uses stream objects to represent request and response message bodies.
These stream objects allow you to work with various types of data all using a
common interface.
HTTP messages consist of a start-line, headers, and a body. The body of an HTTP
message can be very small or extremely large. Attempting to represent the body
of a message as a string can easily consume more memory than intended because
the body must be stored completely in memory. Attempting to store the body of a
request or response in memory would preclude the use of that implementation from
being able to work with large message bodies. The StreamInterface is used in
order to hide the implementation details of where a stream of data is read from
or written to.
Guzzle's StreamInterface exposes several methods that enable streams to be read
from, written to, and traversed effectively.
Streams expose their capabilities using three methods: ``isReadable()``,
``isWritable()``, and ``isSeekable()``. These methods can be used by stream
collaborators to determine if a stream is capable of their requirements.
Each stream instance has various capabilities: they can be read-only,
write-only, read-write, allow arbitrary random access (seeking forwards or
backwards to any location), or only allow sequential access (for example in the
case of a socket or pipe).
Creating Streams
================
The best way to create a stream is using the static factory method,
``GuzzleHttp\Stream\Stream::factory()``. This factory accepts strings,
resources returned from ``fopen()``, an object that implements
``__toString()``, and an object that implements
``GuzzleHttp\Stream\StreamInterface``.
.. code-block:: php
use GuzzleHttp\Stream\Stream;
$stream = Stream::factory('string data');
echo $stream;
// string data
echo $stream->read(3);
// str
echo $stream->getContents();
// ing data
var_export($stream->eof());
// true
var_export($stream->tell());
// 11
Metadata
========
Guzzle streams expose stream metadata through the ``getMetadata()`` method.
This method provides the data you would retrieve when calling PHP's
`stream_get_meta_data() function <http://php.net/manual/en/function.stream-get-meta-data.php>`_,
and can optionally expose other custom data.
.. code-block:: php
use GuzzleHttp\Stream\Stream;
$resource = fopen('/path/to/file', 'r');
$stream = Stream::factory($resource);
echo $stream->getMetadata('uri');
// /path/to/file
var_export($stream->isReadable());
// true
var_export($stream->isWritable());
// false
var_export($stream->isSeekable());
// true
Stream Decorators
=================
With the small and focused interface, add custom functionality to streams is
very simple with stream decorators. Guzzle provides several built-in decorators
that provide additional stream functionality.
CachingStream
-------------
The CachingStream is used to allow seeking over previously read bytes on
non-seekable streams. This can be useful when transferring a non-seekable
entity body fails due to needing to rewind the stream (for example, resulting
from a redirect). Data that is read from the remote stream will be buffered in
a PHP temp stream so that previously read bytes are cached first in memory,
then on disk.
.. code-block:: php
use GuzzleHttp\Stream\Stream;
use GuzzleHttp\Stream\CachingStream;
$original = Stream::factory(fopen('http://www.google.com', 'r'));
$stream = new CachingStream($original);
$stream->read(1024);
echo $stream->tell();
// 1024
$stream->seek(0);
echo $stream->tell();
// 0
LimitStream
-----------
LimitStream can be used to read a subset or slice of an existing stream object.
This can be useful for breaking a large file into smaller pieces to be sent in
chunks (e.g. Amazon S3's multipart upload API).
.. code-block:: php
use GuzzleHttp\Stream\Stream;
use GuzzleHttp\Stream\LimitStream;
$original = Stream::factory(fopen('/tmp/test.txt', 'r+'));
echo $original->getSize();
// >>> 1048576
// Limit the size of the body to 1024 bytes and start reading from byte 2048
$stream = new LimitStream($original, 1024, 2048);
echo $stream->getSize();
// >>> 1024
echo $stream->tell();
// >>> 0
NoSeekStream
------------
NoSeekStream wraps a stream and does not allow seeking.
.. code-block:: php
use GuzzleHttp\Stream\Stream;
use GuzzleHttp\Stream\LimitStream;
$original = Stream::factory('foo');
$noSeek = new NoSeekStream($original);
echo $noSeek->read(3);
// foo
var_export($noSeek->isSeekable());
// false
$noSeek->seek(0);
var_export($noSeek->read(3));
// NULL
Creating Custom Decorators
--------------------------
Creating a stream decorator is very easy thanks to the
``GuzzleHttp\Stream\StreamDecoratorTrait``. This trait provides methods that
implement ``GuzzleHttp\Stream\StreamInterface`` by proxying to an underlying
stream. Just ``use`` the ``StreamDecoratorTrait`` and implement your custom
methods.
For example, let's say we wanted to call a specific function each time the last
byte is read from a stream. This could be implemented by overriding the
``read()`` method.
.. code-block:: php
use GuzzleHttp\Stream\StreamDecoratorTrait;
class EofCallbackStream implements StreamInterface
{
use StreamDecoratorTrait;
private $callback;
public function __construct(StreamInterface $stream, callable $callback)
{
$this->stream = $stream;
$this->callback = $callback;
}
public function read($length)
{
$result = $this->stream->read($length);
// Invoke the callback when EOF is hit.
if ($this->eof()) {
call_user_func($this->callback);
}
return $result;
}
}
This decorator could be added to any existing stream and used like so:
.. code-block:: php
use GuzzleHttp\Stream\Stream;
$original = Stream::factory('foo');
$eofStream = new EofCallbackStream($original, function () {
echo 'EOF!';
});
$eofStream->read(2);
$eofStream->read(1);
// echoes "EOF!"
$eofStream->seek(0);
$eofStream->read(3);
// echoes "EOF!"

View file

@ -0,0 +1,232 @@
======================
Testing Guzzle Clients
======================
Guzzle provides several tools that will enable you to easily mock the HTTP
layer without needing to send requests over the internet.
* Mock subscriber
* Mock handler
* Node.js web server for integration testing
Mock Subscriber
===============
When testing HTTP clients, you often need to simulate specific scenarios like
returning a successful response, returning an error, or returning specific
responses in a certain order. Because unit tests need to be predictable, easy
to bootstrap, and fast, hitting an actual remote API is a test smell.
Guzzle provides a mock subscriber that can be attached to clients or requests
that allows you to queue up a list of responses to use rather than hitting a
remote API.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Subscriber\Mock;
use GuzzleHttp\Message\Response;
$client = new Client();
// Create a mock subscriber and queue two responses.
$mock = new Mock([
new Response(200, ['X-Foo' => 'Bar']), // Use response object
"HTTP/1.1 202 OK\r\nContent-Length: 0\r\n\r\n" // Use a response string
]);
// Add the mock subscriber to the client.
$client->getEmitter()->attach($mock);
// The first request is intercepted with the first response.
echo $client->get('/')->getStatusCode();
//> 200
// The second request is intercepted with the second response.
echo $client->get('/')->getStatusCode();
//> 202
When no more responses are in the queue and a request is sent, an
``OutOfBoundsException`` is thrown.
History Subscriber
==================
When using things like the ``Mock`` subscriber, you often need to know if the
requests you expected to send were sent exactly as you intended. While the mock
subscriber responds with mocked responses, the ``GuzzleHttp\Subscriber\History``
subscriber maintains a history of the requests that were sent by a client.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Subscriber\History;
$client = new Client();
$history = new History();
// Add the history subscriber to the client.
$client->getEmitter()->attach($history);
$client->get('http://httpbin.org/get');
$client->head('http://httpbin.org/get');
// Count the number of transactions
echo count($history);
//> 2
// Get the last request
$lastRequest = $history->getLastRequest();
// Get the last response
$lastRequest = $history->getLastResponse();
// Iterate over the transactions that were sent
foreach ($history as $transaction) {
echo $transaction['request']->getMethod();
//> GET, HEAD
echo $transaction['response']->getStatusCode();
//> 200, 200
}
The history subscriber can also be printed, revealing the requests and
responses that were sent as a string, in order.
.. code-block:: php
echo $history;
::
> GET /get HTTP/1.1
Host: httpbin.org
User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
< HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json
Date: Tue, 25 Mar 2014 03:53:27 GMT
Server: gunicorn/0.17.4
Content-Length: 270
Connection: keep-alive
{
"headers": {
"Connection": "close",
"X-Request-Id": "3d0f7d5c-c937-4394-8248-2b8e03fcccdb",
"User-Agent": "Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8",
"Host": "httpbin.org"
},
"origin": "76.104.247.1",
"args": {},
"url": "http://httpbin.org/get"
}
> HEAD /get HTTP/1.1
Host: httpbin.org
User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
< HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-length: 270
Content-Type: application/json
Date: Tue, 25 Mar 2014 03:53:27 GMT
Server: gunicorn/0.17.4
Connection: keep-alive
Mock Adapter
============
In addition to using the Mock subscriber, you can use the
``GuzzleHttp\Ring\Client\MockAdapter`` as the handler of a client to return the
same response over and over or return the result of a callable function.
Test Web Server
===============
Using mock responses is almost always enough when testing a web service client.
When implementing custom :doc:`HTTP handlers <handlers>`, you'll need to send
actual HTTP requests in order to sufficiently test the handler. However, a
best practice is to contact a local web server rather than a server over the
internet.
- Tests are more reliable
- Tests do not require a network connection
- Tests have no external dependencies
Using the test server
---------------------
.. warning::
The following functionality is provided to help developers of Guzzle
develop HTTP handlers. There is no promise of backwards compatibility
when it comes to the node.js test server or the ``GuzzleHttp\Tests\Server``
class. If you are using the test server or ``Server`` class outside of
guzzlehttp/guzzle, then you will need to configure autoloading and
ensure the web server is started manually.
.. hint::
You almost never need to use this test web server. You should only ever
consider using it when developing HTTP handlers. The test web server
is not necessary for mocking requests. For that, please use the
Mock subcribers and History subscriber.
Guzzle ships with a node.js test server that receives requests and returns
responses from a queue. The test server exposes a simple API that is used to
enqueue responses and inspect the requests that it has received.
Any operation on the ``Server`` object will ensure that
the server is running and wait until it is able to receive requests before
returning.
.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Tests\Server;
// Start the server and queue a response
Server::enqueue("HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n");
$client = new Client(['base_url' => Server::$url]);
echo $client->get('/foo')->getStatusCode();
// 200
``GuzzleHttp\Tests\Server`` provides a static interface to the test server. You
can queue an HTTP response or an array of responses by calling
``Server::enqueue()``. This method accepts a string representing an HTTP
response message, a ``GuzzleHttp\Message\ResponseInterface``, or an array of
HTTP message strings / ``GuzzleHttp\Message\ResponseInterface`` objects.
.. code-block:: php
// Queue single response
Server::enqueue("HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n");
// Clear the queue and queue an array of responses
Server::enqueue([
"HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n",
"HTTP/1.1 404 Not Found\r\n\Content-Length: 0r\n\r\n"
]);
When a response is queued on the test server, the test server will remove any
previously queued responses. As the server receives requests, queued responses
are dequeued and returned to the request. When the queue is empty, the server
will return a 500 response.
You can inspect the requests that the server has retrieved by calling
``Server::received()``. This method accepts an optional ``$hydrate`` parameter
that specifies if you are retrieving an array of HTTP requests as strings or an
array of ``GuzzleHttp\Message\RequestInterface`` objects.
.. code-block:: php
foreach (Server::received() as $response) {
echo $response;
}
You can clear the list of received requests from the web server using the
``Server::flush()`` method.
.. code-block:: php
Server::flush();
echo count(Server::received());
// 0