Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HTTP 111: Connection Refused #1947

Closed
wants to merge 1 commit into from

Conversation

skyzyx
Copy link

@skyzyx skyzyx commented Aug 6, 2016

Ran into this when attempting to connect to a turned-off Redis server using the Predis library through Slim. This was the HTTP error code that was returned, and Slim triggered the phpErrorHandler against its own code because this was missing from the list.

I had never heard of this error code before, and I could not find it in RFC 2616 or RFC 6585. But apparently it's quite common. Google: http error 111.


Here is the Exception that was logged. Cleaned-up for readability.

[06-Aug-2016 05:04:22 UTC] PHP Fatal error:  Uncaught InvalidArgumentException: ReasonPhrase must be supplied for this code in /vagrant/vendor/slim/slim/Slim/Http/Response.php:194

Stack trace:
#0 /vagrant/vendor/slim/slim/Slim/Http/Response.php(321): Slim\Http\Response->withStatus(111)
#1 /vagrant/src/Application/EventHandler/Error/ErrorHandler.php(49): Slim\Http\Response->withJson(Array, 111, 450)
#2 [internal function]: Application\EventHandler\Error\ErrorHandler->Application\EventHandler\Error\{closure}(Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Predis\Connection\ConnectionException))
#3 /vagrant/vendor/slim/slim/Slim/App.php(613): call_user_func_array(Object(Closure), Array)
#4 /vagrant/vendor/slim/slim/Slim/App.php(339): Slim\App->handleException(Object(Predis\Connection\ConnectionException), Object(Slim\Http\Request), Object(Slim\Http\Response))
#5 /vagrant/vendor/slim/slim/Slim/App.php(298): Slim\App->process(Object(Slim\Http\Request), Object(Slim\Http\Response))
#6 /vagrant/bootstrap.php(127): Slim\App->run()
#7 /vagrant/publi in /vagrant/vendor/slim/slim/Slim/Http/Response.php on line 194

Running on PHP 7.0.9. Slim Framework 3.5.0. Here is a snippet from composer.lock:

"name": "slim/slim",
"version": "3.5.0",
"source": {
    "type": "git",
    "url": "https://github.com/slimphp/Slim.git",
    "reference": "184352bc1913d7ba552ab4131d62f4730ddb0893"
},

@coveralls
Copy link

Coverage Status

Coverage remained the same at 97.176% when pulling c63ba65 on luckyrocketshipunderpants:3.x into a63b393 on slimphp:3.x.

@akrabat
Copy link
Member

akrabat commented Aug 14, 2016

@skyzyx: How can I reproduce this? I don't get the exception about a missing reason code that you report in my testing.

Using this code:

$app->get('/', function ($request, $response) {

    $client = new Predis\Client();
    $client->set('foo', 'bar');
    $value = $client->get('foo');

    $response->write("Value = $value");
    return $response;
});

I get either: Value = bar when redis is running or https://i.19ft.com/e2530193.png when it isn't.

I see in your stack trace that you have a Application/EventHandler/Error/ErrorHandler.php file. I don't seem to have this file. What does it do?

@akrabat akrabat self-assigned this Aug 14, 2016
@skyzyx
Copy link
Author

skyzyx commented Aug 15, 2016

Let me try to share in pieces. I'm building a JSON-only API, so I've overridden the handlers that default to sending HTML back.

bootstrap.php:

...
$config['errorHandler'] = new Application\EventHandler\Error\ErrorHandler($config);
...

Application/EventHandler/Error/ErrorHandler.php:

namespace Application\EventHandler\Error;

use Application\Dictionary\Http as HttpDict;
use Application\Util\Url;
use Throwable;
use GuzzleHttp\Psr7;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Container;

class ErrorHandler extends AbstractHandler
{
    public function __invoke(Container $c)
    {
        /**
         * @param \Psr\Http\Message\ServerRequestInterface $request   PSR7 request
         * @param \Psr\Http\Message\ResponseInterface      $response  PSR7 response
         * @param \Throwable                               $exception The exception thrown.
         *
         * @return \Psr\Http\Message\ResponseInterface
         */
        return function (Request $request, Response $response, Throwable $exception) use ($c)
        {
            $error_code = $exception->getCode() ?: 500;
            $error = HttpDict::getStatus($error_code);
            $error['message'] = $exception->getMessage();
            unset($error['standard_message']);

            $request_id = $request->getHeaderLine('X-Request-Id');

            // Clear the body.
            $response = $response->withBody(Psr7\stream_for(''));

            $response = $response->withJson([
                'error' => [
                    'errors' => array_merge($error, [
                        'resource' => Url::getCompleteUrl($request),
                    ]),
                    'code'   => $error_code,
                ]
            ], $error_code, $this->config['json_options'])
                ->withAddedHeader('X-Request-Id', $request_id);

            $this->logRequest($request);
            $this->logResponse($response);

            return $response;
        };
    }
}

In short, it happens when $exception->getCode() (error code 111) is passed as the second parameter to $response->withJson(). Slim goes to look it up, but it can't.


Application\Dictionary\Http is my own HTTP dictionary which includes pre-written messaging for various types of HTTP statuses, and isn't particularly relevant here.

Application\Util\Url is a set of utilities for messing with URLs, and is also not relevant here.

@akrabat
Copy link
Member

akrabat commented Aug 15, 2016

You should not set Redis' error code as an HTTP status code as it isn't one. You should set the response to a valid HTTP status code in the 5xx series and log the Redis code for your own diagnostics.

@skyzyx
Copy link
Author

skyzyx commented Aug 15, 2016

Nginx, Memcache, MySQL, cURL, and lots of other software return this code when a connection has been refused. But I cannot find a canonical source of information which suggests that this is an HTTP code, so I'll let this go. Perhaps it's simply an error code that all major web software implements.

sigh

Thanks for taking a look at this.

@skyzyx skyzyx closed this Aug 15, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants