slimphp / Slim

Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
http://slimframework.com
MIT License
11.98k stars 1.95k forks source link

[v3.3.0] Return response withJson status not working #1827

Closed Loic-Rameau closed 8 years ago

Loic-Rameau commented 8 years ago

I guys, i've came accros difficulty with routing.

Here some code that works for me :

/**
 * @var Slim\App $app
 */
$this->get('/{slug:[a-zA-Z0-9_-]+}/agencies[/dpts/{dpts:\d+}]', function (Request $request, Response $response, $args) use ($database, $slug, $app) {
        $entity = Entity::getItem([
            [
                'column'=>$slug,
                'operator'=>'=',
                'value'=>$args['slug']
            ]
        ]);
        if($entity === false){
            $app->respond($response->withJson([
                'error'=>'Unknown Entity',
                'code'=>404
            ], 400));
            exit();
        }

        $response->getBody()->write(Agency::getItemsJson(
            $where, 'cp'
        ));
        return $response;
});

Here some that don't :

/**
 * @var Slim\App $app
 */
$this->get('/{slug:[a-zA-Z0-9_-]+}/agencies[/dpts/{dpts:\d+}]', function (Request $request, Response $response, $args) use ($database, $slug, $app) {
        $entity = Entity::getItem([
            [
                'column'=>$slug,
                'operator'=>'=',
                'value'=>$args['slug']
            ]
        ]);
        if($entity === false){
            return $response->withJson([
                'error'=>'Unknown Entity',
                'code'=>404
            ], 400);
        }

        $response->getBody()->write(Agency::getItemsJson(
            $where, 'cp'
        ));
        return $response;
});

And i can't figure why the second one doesn't work. It returns the given json :

{
 "error": "Unknown Entity",
 "code": 404
}

But with a HTTP code of 200 and not 400 as given in parameter.

The fact is that if i do :

/**
 * @var Slim\App $app
 */
$this->get('/{slug:[a-zA-Z0-9_-]+}/agencies[/dpts/{dpts:\d+}]', function (Request $request, Response $response, $args) use ($database, $slug, $app) {
        $entity = Entity::getItem([
            [
                'column'=>$slug,
                'operator'=>'=',
                'value'=>$args['slug']
            ]
        ]);
        if($entity === false){
           $newResponse = $response->withStatus(400)->withJson([
                'error'=>'Unknown Entity',
                'code'=>404
            ]);
           return $newResponse;
        }

        $response->getBody()->write(Agency::getItemsJson(
            $where, 'cp'
        ));
        return $response;
});

This as the same effect. The Json is correctly send but with a wrong HTTP code 200 instead of 400. I almost lost a day figuring why my code wouldn't work, and i find annoying to pass $app in every callback.

ppetermann commented 8 years ago

not sure why, but whoever added the method build it so it accepts a $status as second parameter. Have you tried:

       $newResponse = $response->withJson([
            'error'=>'Unknown Entity',
            'code'=>404
        ], 400);
Loic-Rameau commented 8 years ago

I did as i say earlier.


/**
 * @var Slim\App $app
 */
$this->get('/{slug:[a-zA-Z0-9_-]+}/agencies[/dpts/{dpts:\d+}]', function (Request $request, Response $response, $args) use ($database, $slug, $app) {
        $entity = Entity::getItem([
            [
                'column'=>$slug,
                'operator'=>'=',
                'value'=>$args['slug']
            ]
        ]);
        if($entity === false){
            return $response->withJson([
                'error'=>'Unknown Entity',
                'code'=>404
            ], 400);
        }

        $response->getBody()->write(Agency::getItemsJson(
            $where, 'cp'
        ));
        return $response;
});

The responses have the good data but not the status.

akrabat commented 8 years ago

Which version of Slim 3 are you using? This was fixed in version 3.20 (https://github.com/slimphp/Slim/pull/1737).

Loic-Rameau commented 8 years ago
{
            "name": "slim/slim",
            "version": "3.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/slimphp/Slim.git",
                "reference": "939f2e85d57508de9cff241d10091cd972f221c3"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/slimphp/Slim/zipball/939f2e85d57508de9cff241d10091cd972f221c3",
                "reference": "939f2e85d57508de9cff241d10091cd972f221c3",
                "shasum": ""
            },
            "require": {
                "container-interop/container-interop": "^1.1",
                "nikic/fast-route": "^0.6",
                "php": ">=5.5.0",
                "pimple/pimple": "^3.0",
                "psr/http-message": "^1.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^4.0",
                "squizlabs/php_codesniffer": "^2.5"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Slim\\": "Slim"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Rob Allen",
                    "email": "rob@akrabat.com",
                    "homepage": "http://akrabat.com"
                },
                {
                    "name": "Josh Lockhart",
                    "email": "hello@joshlockhart.com",
                    "homepage": "https://joshlockhart.com"
                },
                {
                    "name": "Gabriel Manricks",
                    "email": "gmanricks@me.com",
                    "homepage": "http://gabrielmanricks.com"
                },
                {
                    "name": "Andrew Smith",
                    "email": "a.smith@silentworks.co.uk",
                    "homepage": "http://silentworks.co.uk"
                }
            ],
            "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
            "homepage": "http://slimframework.com",
            "keywords": [
                "api",
                "framework",
                "micro",
                "router"
            ],
            "time": "2016-03-10 21:37:40"
        }
akrabat commented 8 years ago

This works:

$app->get('/jsontest', function ($request, $response, $args) {
    $response = $response->withStatus(201);
    $response = $response->withJson(['foo' => 'bar']);
    return $response;
});
$ curl -v http://develop-testbed.slim3.dev/jsontest
*   Trying 127.0.0.1...
* Connected to develop-testbed.slim3.dev (127.0.0.1) port 80 (#0)
> GET /jsontest HTTP/1.1
> Host: develop-testbed.slim3.dev
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 201 Created
< Date: Tue, 29 Mar 2016 09:30:29 GMT
< Server: Apache/2.4.18 (Unix) PHP/7.0.4
< X-Powered-By: PHP/7.0.4
< Content-Length: 13
< Content-Type: application/json;charset=utf-8
< 
* Connection #0 to host develop-testbed.slim3.dev left intact
{"foo":"bar"}
akrabat commented 8 years ago

This also works:

$app->get('/jsontest2', function ($request, $response, $args) {
    return $response->withJson(['foo' => 'bar'], 400);
});
$ curl -v http://develop-testbed.slim3.dev/jsontest2
*   Trying 127.0.0.1...
* Connected to develop-testbed.slim3.dev (127.0.0.1) port 80 (#0)
> GET /jsontest2 HTTP/1.1
> Host: develop-testbed.slim3.dev
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
< Date: Tue, 29 Mar 2016 09:32:21 GMT
< Server: Apache/2.4.18 (Unix) PHP/7.0.4
< X-Powered-By: PHP/7.0.4
< Content-Length: 13
< Connection: close
< Content-Type: application/json;charset=utf-8
< 
* Closing connection 0
{"foo":"bar"}

Can you create a tiny, standalone example that doesn't work please?

akrabat commented 8 years ago

OOI, do you have have any middleware in the chain that sets the status after calling $next()?

Loic-Rameau commented 8 years ago

OOH ! I didn't tough of that. I found the guilty one !

$app->add(function (Request $request,Response $response_,callable $next) {
    $response = $response_->withHeader('Cache-Control','no-cache, must-revalidate');
    $next($request, $response);
    return $response;
});

Thank you for the help, and sorry for the bother.

akrabat commented 8 years ago

I'm glad that you found the problem :)