2017 © Pedro Peláez
 

library fast-cgi-client

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

image

hollodotme/fast-cgi-client

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  • Sunday, January 28, 2018
  • by hollodotme
  • Repository
  • 18 Watchers
  • 233 Stars
  • 20,121 Installations
  • PHP
  • 1 Dependents
  • 0 Suggesters
  • 7 Forks
  • 1 Open issues
  • 21 Versions
  • 35 % Grown

The README.md

FastCGI Client CI PHP 7.1 - 8.1 Latest Stable Version Total Downloads, (*1)

Fast CGI Client

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM using the FastCGI Protocol., (*2)

This library is based on the work of Pierrick Charron's PHP-FastCGI-Client and was ported and modernized to latest PHP versions, extended with some features for handling multiple requests (in loops) and unit and integration tests as well., (*3)


This is the documentation of the latest release., (*4)

Please have a look at the backwards incompatible changes (BC breaks) in the changelog., (*5)

Please see the following links for earlier releases:, (*6)

Read more about the journey to and changes in v2.6.0 in this blog post., (*7)


You can find an experimental use-case in my related blog posts:, (*8)

You can also find slides of my talks about this project on speakerdeck.com., (*9)


Installation

composer require hollodotme/fast-cgi-client

Usage - connections

This library supports two types of connecting to a FastCGI server:, (*10)

  1. Via network socket
  2. Via unix domain socket

Create a network socket connection

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\SocketConnections\NetworkSocket;

$connection = new NetworkSocket(
    '127.0.0.1',    # Hostname
    9000,           # Port
    5000,           # Connect timeout in milliseconds (default: 5000)
    5000            # Read/write timeout in milliseconds (default: 5000)
);

Create a unix domain socket connection

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\SocketConnections\UnixDomainSocket;

$connection = new UnixDomainSocket(
    '/var/run/php/php7.3-fpm.sock',     # Socket path
    5000,                               # Connect timeout in milliseconds (default: 5000)
    5000                                # Read/write timeout in milliseconds (default: 5000)
);

Usage - single request

The following examples assume that the content of /path/to/target/script.php looks like this:, (*11)

<?php declare(strict_types=1);

sleep((int)($_REQUEST['sleep'] ?? 0));
echo $_REQUEST['key'] ?? '';

Send request synchronously

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\Client;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;

$client     = new Client();
$connection = new NetworkSocket('127.0.0.1', 9000);
$content    = http_build_query(['key' => 'value']);
$request    = new PostRequest('/path/to/target/script.php', $content);

$response = $client->sendRequest($connection, $request);

echo $response->getBody();
# prints
value

Send request asynchronously (Fire and forget)

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\Client;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;

$client     = new Client();
$connection = new NetworkSocket('127.0.0.1', 9000);
$content    = http_build_query(['key' => 'value']);
$request    = new PostRequest('/path/to/target/script.php', $content);

$socketId = $client->sendAsyncRequest($connection, $request);

echo "Request sent, got ID: {$socketId}";

Read the response, after sending the async request

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\Client;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;

$client     = new Client();
$connection = new NetworkSocket('127.0.0.1', 9000);
$content    = http_build_query(['key' => 'value']);
$request    = new PostRequest('/path/to/target/script.php', $content);

$socketId = $client->sendAsyncRequest($connection, $request);

echo "Request sent, got ID: {$socketId}";

# Do something else here in the meanwhile

# Blocking call until response is received or read timed out
$response = $client->readResponse( 
    $socketId,     # The socket ID 
    3000            # Optional timeout to wait for response,
                    # defaults to read/write timeout in milliseconds set in connection
);

echo $response->getBody();
# prints
value

Notify a callback when async request responded

You can register response and failure callbacks for each request. In order to notify the callbacks when a response was received instead of returning it, you need to use the waitForResponse(int $socketId, ?int $timeoutMs = null) method., (*12)

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\Client;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\Interfaces\ProvidesResponseData;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;
use Throwable;

$client     = new Client();
$connection = new NetworkSocket('127.0.0.1', 9000);
$content    = http_build_query(['key' => 'value']);
$request    = new PostRequest('/path/to/target/script.php', $content);

# Register a response callback, expects a `ProvidesResponseData` instance as the only parameter
$request->addResponseCallbacks(
    static function( ProvidesResponseData $response )
    {
        echo $response->getBody();  
    }
);

# Register a failure callback, expects a `\Throwable` instance as the only parameter
$request->addFailureCallbacks(
    static function ( Throwable $throwable )
    {
        echo $throwable->getMessage();  
    }
);

$socketId = $client->sendAsyncRequest($connection, $request);

echo "Request sent, got ID: {$socketId}";

# Do something else here in the meanwhile

# Blocking call until response is received or read timed out
# If response was received all registered response callbacks will be notified
$client->waitForResponse( 
    $socketId,     # The socket ID 
    3000            # Optional timeout to wait for response,
                    # defaults to read/write timeout in milliseconds set in connection
);

# ... is the same as

while(true)
{
    if ($client->hasResponse($socketId))
    {
        $client->handleResponse($socketId, 3000);
        break;
    }
}
# prints
value

Usage - multiple requests

Sending multiple requests and reading their responses (order preserved)

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\Client;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;

$client     = new Client();
$connection = new NetworkSocket('127.0.0.1', 9000);

$request1 = new PostRequest('/path/to/target/script.php', http_build_query(['key' => '1']));
$request2 = new PostRequest('/path/to/target/script.php', http_build_query(['key' => '2']));
$request3 = new PostRequest('/path/to/target/script.php', http_build_query(['key' => '3']));

$socketIds = [];

$socketIds[] = $client->sendAsyncRequest($connection, $request1);
$socketIds[] = $client->sendAsyncRequest($connection, $request2);
$socketIds[] = $client->sendAsyncRequest($connection, $request3);

echo 'Sent requests with IDs: ' . implode( ', ', $socketIds ) . "\n";

# Do something else here in the meanwhile

# Blocking call until all responses are received or read timed out
# Responses are read in same order the requests were sent
foreach ($client->readResponses(3000, ...$socketIds) as $response)
{
    echo $response->getBody() . "\n";   
}
# prints
1
2
3

Sending multiple requests and reading their responses (reactive)

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\Client;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;

$client     = new Client();
$connection = new NetworkSocket('127.0.0.1', 9000);

$request1 = new PostRequest('/path/to/target/script.php', http_build_query(['key' => '1', 'sleep' => 3]));
$request2 = new PostRequest('/path/to/target/script.php', http_build_query(['key' => '2', 'sleep' => 2]));
$request3 = new PostRequest('/path/to/target/script.php', http_build_query(['key' => '3', 'sleep' => 1]));

$socketIds = [];

$socketIds[] = $client->sendAsyncRequest($connection, $request1);
$socketIds[] = $client->sendAsyncRequest($connection, $request2);
$socketIds[] = $client->sendAsyncRequest($connection, $request3);

echo 'Sent requests with IDs: ' . implode( ', ', $socketIds ) . "\n";

# Do something else here in the meanwhile

# Loop until all responses were received
while ( $client->hasUnhandledResponses() )
{
    # read all ready responses
    foreach ( $client->readReadyResponses( 3000 ) as $response )
    {
        echo $response->getBody() . "\n";
    }

    echo '.';
}

# ... is the same as

while ( $client->hasUnhandledResponses() )
{
    $readySocketIds = $client->getSocketIdsHavingResponse();

    # read all ready responses
    foreach ( $client->readResponses( 3000, ...$readySocketIds ) as $response )
    {
        echo $response->getBody() . "\n";
    }

    echo '.';
}

# ... is the same as

while ( $client->hasUnhandledResponses() )
{
    $readySocketIds = $client->getSocketIdsHavingResponse();

    # read all ready responses
    foreach ($readySocketIds as $socketId)
    {
        $response = $client->readResponse($socketId, 3000);
        echo $response->getBody() . "\n";
    }

    echo '.';
}
# prints
...............................................3
...............................................2
...............................................1

Sending multiple requests and notifying callbacks (reactive)

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\Client;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\Interfaces\ProvidesResponseData;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;
use Throwable;

$client     = new Client();
$connection = new NetworkSocket('127.0.0.1', 9000);

$responseCallback = static function( ProvidesResponseData $response )
{
    echo $response->getBody();  
};

$failureCallback = static function ( Throwable $throwable )
{
    echo $throwable->getMessage();  
};

$request1 = new PostRequest('/path/to/target/script.php', http_build_query(['key' => '1', 'sleep' => 3]));
$request2 = new PostRequest('/path/to/target/script.php', http_build_query(['key' => '2', 'sleep' => 2]));
$request3 = new PostRequest('/path/to/target/script.php', http_build_query(['key' => '3', 'sleep' => 1]));

$request1->addResponseCallbacks($responseCallback);
$request1->addFailureCallbacks($failureCallback);

$request2->addResponseCallbacks($responseCallback);
$request2->addFailureCallbacks($failureCallback);

$request3->addResponseCallbacks($responseCallback);
$request3->addFailureCallbacks($failureCallback);

$socketIds = [];

$socketIds[] = $client->sendAsyncRequest($connection, $request1);
$socketIds[] = $client->sendAsyncRequest($connection, $request2);
$socketIds[] = $client->sendAsyncRequest($connection, $request3);

echo 'Sent requests with IDs: ' . implode( ', ', $socketIds ) . "\n";

# Do something else here in the meanwhile

# Blocking call until all responses were received and all callbacks notified
$client->waitForResponses(3000);

# ... is the same as

while ( $client->hasUnhandledResponses() )
{
    $client->handleReadyResponses(3000);
}

# ... is the same as

while ( $client->hasUnhandledResponses() )
{
    $readySocketIds = $client->getSocketIdsHavingResponse();

    # read all ready responses
    foreach ($readySocketIds as $socketId)
    {
        $client->handleResponse($socketId, 3000);
    }
}
# prints
3
2
1

Reading output buffer from worker script using pass through callbacks

It may be useful to see the progression of a requested script by having access to the flushed output of that script. The php.ini default output buffering for php-fpm is 4096 bytes and is (hard-coded) disabled for CLI mode. (See documentation) Calling ob_implicit_flush() causes every call to echo or print to immediately be flushed., (*13)

The callee script could look like this:, (*14)

<?php declare(strict_types=1);

ob_implicit_flush();

function show( string $string )
{
    echo $string . str_repeat( "\r", 4096 - strlen( $string ) ) . "\n";
    sleep( 1 );
}

show( 'One' );
show( 'Two' );
show( 'Three' );

error_log("Oh oh!\n");

echo 'End';

The caller than could look like this:, (*15)

<?php declare(strict_types=1);

namespace YourVendor\YourProject;

use hollodotme\FastCGI\Client;
use hollodotme\FastCGI\Requests\GetRequest;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;

$client     = new Client();
$connection = new NetworkSocket('127.0.0.1', 9000);

$passThroughCallback = static function( string $outputBuffer, string $errorBuffer )
{
    echo 'Output: ' . $outputBuffer;
    echo 'Error: ' . $errorBuffer;
};

$request = new GetRequest('/path/to/target/script.php', '');
$request->addPassThroughCallbacks( $passThroughCallback );

$client->sendAsyncRequest($connection, $request);
$client->waitForResponses();
# prints immediately
Buffer: Content-type: text/html; charset=UTF-8

Output: One
# sleeps 1 sec
Output: Two
# sleeps 1 sec
Output: Three
# sleeps 1 sec
Error: Oh oh!
Output: End

Requests

Requests are defined by the following interface:, (*16)

<?php declare(strict_types=1);

namespace hollodotme\FastCGI\Interfaces;

interface ProvidesRequestData
{
    public function getGatewayInterface() : string;

    public function getRequestMethod() : string;

    public function getScriptFilename() : string;

    public function getServerSoftware() : string;

    public function getRemoteAddress() : string;

    public function getRemotePort() : int;

    public function getServerAddress() : string;

    public function getServerPort() : int;

    public function getServerName() : string;

    public function getServerProtocol() : string;

    public function getContentType() : string;

    public function getContentLength() : int;

    public function getContent() : string;

    public function getCustomVars() : array;

    public function getParams() : array;

    public function getRequestUri() : string;
}

Alongside with this interface, this package provides an abstract request class, containing default values to make the API more handy for you and 5 request method implementations of this abstract class:, (*17)

  • hollodotme\FastCGI\Requests\GetRequest
  • hollodotme\FastCGI\Requests\PostRequest
  • hollodotme\FastCGI\Requests\PutRequest
  • hollodotme\FastCGI\Requests\PatchRequest
  • hollodotme\FastCGI\Requests\DeleteRequest

So you can either implement the interface, inherit from the abstract class or simply use one of the 5 implementations., (*18)

Default values

The abstract request class defines several default values which you can optionally overwrite:, (*19)

Key Default value Comment
GATEWAY_INTERFACE FastCGI/1.0 Cannot be overwritten, because this is the only supported version of the client.
SERVER_SOFTWARE hollodotme/fast-cgi-client
REMOTE_ADDR 192.168.0.1
REMOTE_PORT 9985
SERVER_ADDR 127.0.0.1
SERVER_PORT 80
SERVER_NAME localhost
SERVER_PROTOCOL HTTP/1.1 You can use the public class constants in hollodotme\FastCGI\Constants\ServerProtocol
CONTENT_TYPE application/x-www-form-urlencoded
REQUEST_URI
CUSTOM_VARS empty array You can use the methods setCustomVar, addCustomVars to add own key-value pairs

Request contents

In order to make the composition of different request content types easier there are classes covering the typical content types:, (*20)

You can create your own request content type composer by implementing the following interface:, (*21)

ComposesRequestContent, (*22)

interface ComposesRequestContent
{
    public function getContentType() : string;

    public function getContent() : string;
}
Request content example: URL encoded form data (application/x-www-form-urlencoded)
<?php declare(strict_types=1);

use hollodotme\FastCGI\RequestContents\UrlEncodedFormData;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\Client;

$client = new Client();
$connection = new NetworkSocket( '127.0.0.1', 9000 );

$urlEncodedContent = new UrlEncodedFormData(
    [
        'nested' => [
            'one',
            'two'   => 'value2',
            'three' => [
                'value3',
            ],
        ],
    ]
);

$postRequest = PostRequest::newWithRequestContent( '/path/to/target/script.php', $urlEncodedContent );

$response = $client->sendRequest( $connection, $postRequest );

This example produces the following $_POST array at the target script:, (*23)

Array
(
    [nested] => Array
        (
            [0] => one
            [two] => value2
            [three] => Array
                (
                    [0] => value3
                )

        )
)
Request content example: multipart form data (multipart/form-data)

Multipart form-data can be used to transfer any binary data as files to the target script just like a file upload in a browser does., (*24)

PLEASE NOTE: Multipart form-data content type works with POST requests only., (*25)

<?php declare(strict_types=1);

use hollodotme\FastCGI\RequestContents\MultipartFormData;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\Client;

$client = new Client();
$connection = new NetworkSocket( '127.0.0.1', 9000 );

$multipartContent = new MultipartFormData(
    # POST data
    [
        'simple'          => 'value',
        'nested[]'        => 'one',
        'nested[two]'     => 'value2',
        'nested[three][]' => 'value3',
    ],
    # FILES
    [
        'file1'        => __FILE__,
        'files[1]'     => __FILE__,
        'files[three]' => __FILE__,
    ]
);

$postRequest = PostRequest::newWithRequestContent( '/path/to/target/script.php', $multipartContent );

$response = $client->sendRequest( $connection, $postRequest );

This example produces the following $_POST and $_FILES array at the target script:, (*26)

# $_POST
Array
(
    [simple] => value
    [nested] => Array
        (
            [0] => one
            [two] => value2
            [three] => Array
                (
                    [0] => value3
                )

        )

)

# $_FILES
Array
(
    [file1] => Array
        (
            [name] => multipart.php
            [type] => application/octet-stream
            [tmp_name] => /tmp/phpiIdCNM
            [error] => 0
            [size] => 1086
        )

    [files] => Array
        (
            [name] => Array
                (
                    [1] => multipart.php
                    [three] => multipart.php
                )

            [type] => Array
                (
                    [1] => application/octet-stream
                    [three] => application/octet-stream
                )

            [tmp_name] => Array
                (
                    [1] => /tmp/phpAjHINL
                    [three] => /tmp/phpicAmjN
                )

            [error] => Array
                (
                    [1] => 0
                    [three] => 0
                )

            [size] => Array
                (
                    [1] => 1086
                    [three] => 1086
                )

        )

)
Request content example: JSON encoded data (application/json)
<?php declare(strict_types=1);

use hollodotme\FastCGI\RequestContents\JsonData;
use hollodotme\FastCGI\SocketConnections\NetworkSocket;
use hollodotme\FastCGI\Requests\PostRequest;
use hollodotme\FastCGI\Client;

$client = new Client();
$connection = new NetworkSocket( '127.0.0.1', 9000 );

$jsonContent = new JsonData(
    [
        'nested' => [
            'one',
            'two'   => 'value2',
            'three' => [
                'value3',
            ],
        ],
    ]
);

$postRequest = PostRequest::newWithRequestContent( '/path/to/target/script.php', $jsonContent );

$response = $client->sendRequest( $connection, $postRequest );

This example produces the following content for php://input at the target script:, (*27)

{
  "nested": {
    "0": "one",
    "two": "value2",
    "three": [
      "value3"
    ]
  }
}

Responses

Responses are defined by the following interface:, (*28)

<?php declare(strict_types=1);

namespace hollodotme\FastCGI\Interfaces;

interface ProvidesResponseData
{
    public function getHeaders() : array;

    public function getHeader( string $headerKey ) : array;

    public function getHeaderLine( string $headerKey ) : string;

    public function getBody() : string;

    public function getOutput() : string;

    public function getError() : string;

    public function getDuration() : float;
}

Assuming /path/to/target/script.php has the following content:, (*29)

<?php declare(strict_types=1);

echo 'Hello World';
error_log('Some error');

The raw response would look like this:, (*30)

Content-type: text/html; charset=UTF-8

Hello World

Please note:, (*31)

  • All headers sent by your script will precede the response body
  • There won't be any HTTP specific headers like HTTP/1.1 200 OK, because there is no webserver involved.

Custom headers will also be part of the response:, (*32)

<?php declare(strict_types=1);

header('X-Custom: Header');
header('Set-Cookie: yummy_cookie=choco');
header('Set-Cookie: tasty_cookie=strawberry');

echo 'Hello World';
error_log('Some error');

The raw response would look like this:, (*33)

X-Custom: Header
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
Content-type: text/html; charset=UTF-8

Hello World

You can retrieve all of the response data separately from the response object:, (*34)

# Get all values of a single response header
$response->getHeader('Set-Cookie'); 
// ['yummy_cookie=choco', 'tasty_cookie=strawberry']

# Get all values of a single response header as comma separated string
$response->getHeaderLine('Set-Cookie');
// 'yummy_cookie=choco, tasty_cookie=strawberry'

# Get all headers as grouped array
$response->getHeaders();
// [
//   'X-Custom' => [
//      'Header',
//   ],
//   'Set-Cookie' => [
//      'yummy_cookie=choco',
//      'tasty_cookie=strawberry',
//   ],
//   'Content-type' => [
//      'text/html; charset=UTF-8',
//   ],
// ]

# Get the body
$response->getBody(); 
// 'Hello World'

# Get the raw response output from STDOUT stream
$response->getOutput();
// 'X-Custom: Header
// Set-Cookie: yummy_cookie=choco
// Set-Cookie: tasty_cookie=strawberry
// Content-type: text/html; charset=UTF-8
// 
// Hello World'

# Get the raw response from SFTERR stream
$response->getError();
// Some error

# Get the duration
$response->getDuration(); 
// e.g. 0.0016319751739502

Trouble shooting

"File not found." response (php-fpm)

This response is generated by php-fpm for the preceding error Primary script unknown in case the requested script does not exists or there are path traversals in its path like /var/www/../run/script.php., (*35)

Although the given path may exist and would resolve to an absolute path in the file system, php-fpm does not do any path resolution and accepts only absolute paths to the script you want to execute., (*36)

Programatically you can handle this error like this:, (*37)

if (preg_match("#^Primary script unknown\n?$#", $response->getError()))
{
    throw new Exception('Could not find or resolve path to script for execution.');
}

# OR

if ('404 Not Found' === $response->getHeaderLine('Status'))
{
    throw new Exception('Could not find or resolve path to script for execution.');
}

# OR

if ('File not found.' === trim($response->getBody()))
{
    throw new Exception('Could not find or resolve path to script for execution.');
}

Prepare local development environment

This requires docker and docker-compose installed on your machine., (*38)

make update

Run examples

make examples

Run all tests

make tests

Command line tool (for local debugging only)

Please note: bin/fcgiget is not included and linked to vendor/bin via composer anymore since version v3.1.2for security reasons. Read more., (*39)

Run a call through a network socket:, (*40)

docker-compose exec php74 php bin/fcgiget localhost:9001/status

Run a call through a Unix Domain Socket, (*41)

docker-compose exec php74 php bin/fcgiget unix:///var/run/php-uds.sock/status

This shows the response of the php-fpm status page., (*42)

The Versions

28/01 2018

dev-master

9999999-dev

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

28/01 2018

dev-development

dev-development

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

28/01 2018

dev-1.x-dev

dev-1.x-dev

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

28/01 2018

dev-1.x-stable

dev-1.x-stable

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

28/01 2018

v1.4.2

1.4.2.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

28/01 2018

v2.4.2

2.4.2.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

19/11 2017

v2.4.1

2.4.1.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

19/11 2017

v1.4.1

1.4.1.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

28/09 2017

v2.4.0

2.4.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

28/09 2017

v1.4.0

1.4.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

15/06 2017

v2.3.0

2.3.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

15/06 2017

v1.3.0

1.3.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

27/05 2017

v1.2.0

1.2.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

15/04 2017

v2.2.0

2.2.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

15/04 2017

dev-feature/reactive-loop

dev-feature/reactive-loop

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

07/03 2017

v2.1.0

2.1.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

07/03 2017

v1.1.0

1.1.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

23/02 2017

v2.0.1

2.0.1.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket

23/02 2017

v1.0.1

1.0.1.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

03/01 2017

v1.0.0

1.0.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

php-fpm fastcgi socket

03/01 2017

v2.0.0

2.0.0.0

A PHP fast CGI client to send requests (a)synchronously to PHP-FPM.

  Sources   Download

MIT

The Requires

  • php >=7.1

 

The Development Requires

php-fpm fastcgi socket