Slim 3.6.0 release -

The Response’s withJson() fix is NOT working now, it return an empty response with status 200 OK ( on POST request).
( I’m using the same code i used with 3.5.0, and it was OK):

return $response->withJson($resp, 200);

  • $resp is an Array…

Is there something new we need to use?

Thanks.
Malik Eran

I have the same problem but only when using multiple Middlewares.

A -> B -> C -> B -> A

If I try to use “return $response->withJson($result, 200);” from B or C the response body will be empty.

My code works fine against Slim v3.5 and breaks at v3.6

Might it be because of this?

Ensure withJson returns a new Response #1975

I’ve just wanted to update from 3.5.0 to 3.7.0 and am experiencing the same behaviour (also with 3.6.0). Going back to 3.5.0 everything works fine again.

@tflight As no one got back here, could you please give a little explenation. I am not that code savvy. By the way I use php7.1.1 if that matters.

@panic, @ChristianDube

Can you give a minimal example? I can’t reproduce getting an empty response using withJson.

Hi @llvdl,

don’t know where to begin. Here is a code example and the middlewares:

use PDO;
use Psr\Log\LoggerInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

class getItems {
	protected $logger;
	protected $db;
	protected $csrf;

	//Constructor
	public function __construct($csrf, PDO $db, LoggerInterface $logger) {
		$this->db = $db;
		$this->logger = $logger;
		$this->csrf = $csrf;
	}

	/**
	 * Returns all items from the database.
	 */
	public function index(Request $request, Response $response, $args) {
		$result = $this->db->query('SELECT * FROM items')->fetchAll(PDO::FETCH_ASSOC);
		$response->withJson($result, 200);
	}

Middleware:

class Middleware
{
    protected $container;

    public function __construct($container)
    {
        $this->container = $container;
    }
}

AuthMiddleware:

use Dflydev\FigCookies\FigResponseCookies;

class AuthMiddleware extends Middleware
{
    public function __invoke($request, $response, $next)
    {
        if (!$this->container->auth->isValid()) {
            $this->container->flash->addMessage('error', 'Please sign in before doing that.');

            $settings = $this->container->get('settings');
            $domain = $settings['jwt']['domain'];
            // Expire cookie
            $response = FigResponseCookies::expire($response, 'token', $domain, '/');
            return $response->withRedirect($this->container->router->pathFor('auth.login'));
        }

        $response = $next($request, $response);
        return $response;
    }
}

CsrfMiddleware:

class CsrfViewMiddleware extends Middleware
{
    public function __invoke($request, $response, $next)
    {
        $this->container->view->getEnvironment()->addGlobal('csrf', [
            'field' => '
                <input type="hidden" name="' . $this->container->csrf->getTokenNameKey() . '" value="' . $this->container->csrf->getTokenName() . '">
                <input type="hidden" name="' . $this->container->csrf->getTokenValueKey() . '" value="' . $this->container->csrf->getTokenValue() . '">
            ',
        ]);

        $response = $next($request, $response);
        return $response;
    }
}

GuestMiddleware:

class GuestMiddleware extends Middleware
{
    public function __invoke($request, $response, $next)
    {
        if ($this->container->auth->isValid()) {
            return $response->withRedirect($this->container->router->pathFor('home'));
        }

        $response = $next($request, $response);
        return $response;
    }
}

I’ve also noticed the response has a content type of “text/html; charset=UTF-8” instead of json.
With 3.5 I’ve also have a content type of text/html but it works…

This happens when you don’t return the $response that you created via withJson.

i.e.

$app->get('/users', function ($request, $response) {
    $response->withJson(['user1'. 'user2']);
});

Will not return the JSON:

$ curl -i http:/localhost:8888/users
HTTP/1.1 200 OK
Host: localhost:8888
Connection: close
X-Powered-By: PHP/7.0.15
Content-Type: text/html; charset=UTF-8


$

However:

$app->get('/users', function ($request, $response) {
    return $response->withJson(['user1'. 'user2']);
});

will work:

$ curl -i http:/localhost:8888/users
HTTP/1.1 200 OK
Host: localhost:8888
Connection: close
X-Powered-By: PHP/7.0.15
Content-Type: application/json;charset=utf-8

["user1","user2"]

This is because PSR-7 is immutable and you get back a new Response object. As @tflight noted, there was a bug in earlier versions of Slim3 where it happened to work by accident if you didn’t return the $response object as we just modified the underlying stream.

The problem is here:

	public function index(Request $request, Response $response, $args) {
		$result = $this->db->query('SELECT * FROM items')->fetchAll(PDO::FETCH_ASSOC);
		$response->withJson($result, 200);
	}

You do not return the newly created Response that has the JSON in it.

Change to:

	public function index(Request $request, Response $response, $args) {
		$result = $this->db->query('SELECT * FROM items')->fetchAll(PDO::FETCH_ASSOC);
		return $response->withJson($result, 200);
	}
1 Like

Oh boy… Thank you @akrabat!