2011-02-27 22:32:13 -06:00
|
|
|
<?php
|
|
|
|
|
2014-02-16 21:02:54 -08:00
|
|
|
namespace GuzzleHttp\Tests;
|
2011-02-27 22:32:13 -06:00
|
|
|
|
2014-02-16 20:10:19 -08:00
|
|
|
use GuzzleHttp\Message\MessageFactory;
|
|
|
|
use GuzzleHttp\Message\Response;
|
|
|
|
use GuzzleHttp\Client;
|
2011-02-27 22:32:13 -06:00
|
|
|
|
|
|
|
/**
|
2011-03-11 09:08:02 -06:00
|
|
|
* The Server class is used to control a scripted webserver using node.js that
|
|
|
|
* will respond to HTTP requests with queued responses.
|
2012-03-26 20:09:18 -05:00
|
|
|
*
|
2011-03-11 09:08:02 -06:00
|
|
|
* Queued responses will be served to requests using a FIFO order. All requests
|
2012-06-14 09:49:05 -07:00
|
|
|
* received by the server are stored on the node.js server and can be retrieved
|
2014-03-22 22:05:45 -07:00
|
|
|
* by calling {@see Server::received()}.
|
2012-03-26 20:09:18 -05:00
|
|
|
*
|
2011-03-11 09:08:02 -06:00
|
|
|
* Mock responses that don't require data to be transmitted over HTTP a great
|
2012-06-14 09:49:05 -07:00
|
|
|
* for testing. Mock response, however, cannot test the actual sending of an
|
2011-03-11 09:08:02 -06:00
|
|
|
* HTTP request using cURL. This test server allows the simulation of any
|
|
|
|
* number of HTTP request response transactions to test the actual sending of
|
|
|
|
* requests over the wire without having to leave an internal network.
|
2011-02-27 22:32:13 -06:00
|
|
|
*/
|
2011-03-10 22:29:13 -06:00
|
|
|
class Server
|
2011-02-27 22:32:13 -06:00
|
|
|
{
|
2011-03-11 09:08:02 -06:00
|
|
|
const REQUEST_DELIMITER = "\n----[request]\n";
|
2011-02-27 22:32:13 -06:00
|
|
|
|
2013-05-29 22:53:59 -07:00
|
|
|
/** @var Client */
|
2014-03-22 22:05:45 -07:00
|
|
|
private static $client;
|
2012-01-14 13:57:05 -06:00
|
|
|
|
2014-03-22 22:05:45 -07:00
|
|
|
public static $started;
|
|
|
|
public static $url = 'http://127.0.0.1:8124/';
|
|
|
|
public static $port = 8124;
|
2011-02-27 22:32:13 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Flush the received requests from the server
|
2013-09-22 20:55:24 -07:00
|
|
|
* @throws \RuntimeException
|
2011-02-27 22:32:13 -06:00
|
|
|
*/
|
2014-03-22 22:05:45 -07:00
|
|
|
public static function flush()
|
2011-02-27 22:32:13 -06:00
|
|
|
{
|
2014-03-22 22:05:45 -07:00
|
|
|
self::$started && self::$client->delete('guzzle-server/requests');
|
2011-02-27 22:32:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-03-11 09:08:02 -06:00
|
|
|
* Queue an array of responses or a single response on the server.
|
|
|
|
*
|
|
|
|
* Any currently queued responses will be overwritten. Subsequent requests
|
|
|
|
* on the server will return queued responses in FIFO order.
|
2011-02-27 22:32:13 -06:00
|
|
|
*
|
2011-03-03 12:24:51 -06:00
|
|
|
* @param array|Response $responses A single or array of Responses to queue
|
2014-03-22 22:05:45 -07:00
|
|
|
* @throws \Exception
|
2011-02-27 22:32:13 -06:00
|
|
|
*/
|
2014-03-22 22:05:45 -07:00
|
|
|
public static function enqueue($responses)
|
2011-02-27 22:32:13 -06:00
|
|
|
{
|
2014-03-22 22:05:45 -07:00
|
|
|
static $factory;
|
|
|
|
if (!$factory) {
|
|
|
|
$factory = new MessageFactory();
|
|
|
|
}
|
|
|
|
|
|
|
|
self::start();
|
|
|
|
|
2013-10-13 17:19:11 -07:00
|
|
|
$data = [];
|
2011-02-27 22:32:13 -06:00
|
|
|
foreach ((array) $responses as $response) {
|
|
|
|
|
|
|
|
// Create the response object from a string
|
|
|
|
if (is_string($response)) {
|
2014-03-22 22:05:45 -07:00
|
|
|
$response = $factory->fromMessage($response);
|
2012-05-11 21:04:42 -07:00
|
|
|
} elseif (!($response instanceof Response)) {
|
2014-03-22 22:05:45 -07:00
|
|
|
throw new \Exception('Responses must be strings or Responses');
|
2011-02-27 22:32:13 -06:00
|
|
|
}
|
|
|
|
|
2014-03-22 22:05:45 -07:00
|
|
|
$headers = array_map(function ($h) {
|
|
|
|
return implode(' ,', $h);
|
|
|
|
}, $response->getHeaders());
|
|
|
|
|
2013-10-13 17:19:11 -07:00
|
|
|
$data[] = [
|
2012-04-21 00:23:07 -07:00
|
|
|
'statusCode' => $response->getStatusCode(),
|
2011-02-27 22:32:13 -06:00
|
|
|
'reasonPhrase' => $response->getReasonPhrase(),
|
2014-03-22 22:05:45 -07:00
|
|
|
'headers' => $headers,
|
2013-10-13 17:19:11 -07:00
|
|
|
'body' => (string) $response->getBody()
|
|
|
|
];
|
2011-02-27 22:32:13 -06:00
|
|
|
}
|
|
|
|
|
2014-03-22 22:05:45 -07:00
|
|
|
self::getClient()->put('guzzle-server/responses', [
|
|
|
|
'body' => json_encode($data)
|
|
|
|
]);
|
2011-02-27 22:32:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all of the received requests
|
|
|
|
*
|
2012-05-16 00:55:45 -07:00
|
|
|
* @param bool $hydrate Set to TRUE to turn the messages into
|
2011-03-11 09:08:02 -06:00
|
|
|
* actual {@see RequestInterface} objects. If $hydrate is FALSE,
|
|
|
|
* requests will be returned as strings.
|
2011-02-27 22:32:13 -06:00
|
|
|
*
|
|
|
|
* @return array
|
2013-09-22 20:55:24 -07:00
|
|
|
* @throws \RuntimeException
|
2011-02-27 22:32:13 -06:00
|
|
|
*/
|
2014-03-22 22:05:45 -07:00
|
|
|
public static function received($hydrate = false)
|
2011-02-27 22:32:13 -06:00
|
|
|
{
|
2014-03-22 22:05:45 -07:00
|
|
|
if (!self::$started) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
$response = self::getClient()->get('guzzle-server/requests');
|
2013-09-22 20:55:24 -07:00
|
|
|
$data = array_filter(explode(self::REQUEST_DELIMITER, (string) $response->getBody()));
|
2013-07-16 14:15:25 -07:00
|
|
|
if ($hydrate) {
|
2014-03-22 22:05:45 -07:00
|
|
|
$factory = new MessageFactory();
|
2013-09-22 20:55:24 -07:00
|
|
|
$data = array_map(function($message) use ($factory) {
|
|
|
|
return $factory->fromMessage($message);
|
2013-07-16 14:15:25 -07:00
|
|
|
}, $data);
|
2011-02-27 22:32:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-03-22 22:05:45 -07:00
|
|
|
* Stop running the node.js server
|
2011-02-27 22:32:13 -06:00
|
|
|
*/
|
2014-03-22 22:05:45 -07:00
|
|
|
public static function stop()
|
2011-02-27 22:32:13 -06:00
|
|
|
{
|
2014-03-22 22:05:45 -07:00
|
|
|
if (self::$started) {
|
|
|
|
self::getClient()->delete('guzzle-server');
|
|
|
|
}
|
|
|
|
|
|
|
|
self::$started = false;
|
|
|
|
}
|
|
|
|
|
2014-03-23 10:53:34 -07:00
|
|
|
public static function wait($maxTries = 3)
|
|
|
|
{
|
|
|
|
$tries = 0;
|
|
|
|
while (!self::isListening() && ++$tries < $maxTries) {
|
|
|
|
usleep(100000);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!self::isListening()) {
|
|
|
|
throw new \RuntimeException('Unable to contact node.js server');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-22 22:05:45 -07:00
|
|
|
private static function start()
|
|
|
|
{
|
|
|
|
if (self::$started){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!self::isListening()) {
|
|
|
|
exec('node ' . __DIR__ . \DIRECTORY_SEPARATOR . 'server.js '
|
|
|
|
. self::$port . ' >> /tmp/server.log 2>&1 &');
|
2014-03-23 10:53:34 -07:00
|
|
|
self::wait();
|
2011-02-27 22:32:13 -06:00
|
|
|
}
|
2014-03-22 22:05:45 -07:00
|
|
|
|
|
|
|
self::$started = true;
|
2011-02-27 22:32:13 -06:00
|
|
|
}
|
|
|
|
|
2014-03-22 22:05:45 -07:00
|
|
|
private static function isListening()
|
2011-02-27 22:32:13 -06:00
|
|
|
{
|
2014-03-22 22:05:45 -07:00
|
|
|
try {
|
|
|
|
self::getClient()->get('guzzle-server/perf', [
|
|
|
|
'connect_timeout' => 5,
|
|
|
|
'timeout' => 5
|
|
|
|
]);
|
|
|
|
return true;
|
|
|
|
} catch (\Exception $e) {
|
2011-02-27 22:32:13 -06:00
|
|
|
return false;
|
|
|
|
}
|
2014-03-22 22:05:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private static function getClient()
|
|
|
|
{
|
|
|
|
if (!self::$client) {
|
|
|
|
self::$client = new Client(['base_url' => self::$url]);
|
|
|
|
}
|
2011-02-27 22:32:13 -06:00
|
|
|
|
2014-03-22 22:05:45 -07:00
|
|
|
return self::$client;
|
2011-02-27 22:32:13 -06:00
|
|
|
}
|
2012-04-21 00:23:07 -07:00
|
|
|
}
|