withJson and Content-Type

Hello,

I try to convert my development project from Slim v2 to Slim v3 and I have a behavior which i can’t explain the reason why.
It’s written in the documentation (http://www.slimframework.com/docs/objects/response.html) that “The Content-Type of the Response is automatically set to application/json;charset=utf-8.” when we use withJson.

But I have a problem because when i get the response “Content-type” is “text/html; charset=UTF-8”

My code is very simple.

The route :

$app->get("/{memberRole:public|member|moderator|admin|superuser}/members[/{id:[0-9]+}]", '\LPDP\Controllers\membersController:getMembers' )->setName("getMembers");

The method

public function get(Request $req, Response $res, $args, $table)
    {
        /**
         * get response error code
         */
        $result = $this->conf->get('errors.REST_RESPONSE_OK');
        $sqlStatement = "SELECT * FROM $table";
        $this->db->exec("SET NAMES utf8");
        $sdata = $this->db->prepare($sqlStatement);
        $sdata->execute();
        $data = $sdata->fetchAll(PDO::FETCH_CLASS);

        /**
         * add debug information in response
         */
        $data["debug"] = "get$table";

        /**
         * return response
         */
        return $res->withJson($data, $result["httpStatus"]);
    }

The response property :

HTTP/1.1 200 OK
Server: xxxxxxxx
Date: Sat, 07 May 2016 14:04:35 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.5.35
X-Cache: HIT from Backend

Have you any idea why I don’t get the correct Content-Type ?

Thanks for your help.

Hey,

You sure it’s copy of your code - because I just tested your code and it returns normal content-type header.

Hi,

Thanks for your answer. I have two middlewares

/**
 * define JWT middleware
 */
$app->add(new Slim\Middleware\JwtAuthentication([
    "secure" => false,
    "secret" => "key",
    "rules" => [
        new \Slim\Middleware\JwtAuthentication\RequestPathRule([
            "path" => "/",
            "passthrough" => ["/public"]
        ]),
        new \Slim\Middleware\JwtAuthentication\RequestMethodRule([
            "passthrough" => ["OPTIONS"]
        ])
    ],
    "callback" => function (Request $request, Response $response, $arguments) use ($container) {
        $container["jwt"] = $arguments["decoded"];
    },
    "error" => function (Request $request, Response $response, $arguments) use ($container) {
        //TODO: complete response
        $conf = $container->get('apiConfig');
        $data = $conf->get('errors.REST_RESPONSE_UNAUTHORIZED');
        $data["debug"] = "error-jwt";
        return $response->withJson($data, $data["httpStatus"]);
    }
]));

/**
 * add Authentication Session middleware
 */
$app->add(new \LPDP\Middleware\AuthenticateSession());

The AuthenticateSession class is empty (just the invoke function for now without any action).

class AuthenticateSession
{
   public function __invoke(ServerRequestInterface $req, ResponseInterface $res, $next)
    {
        $res = $next($req, $res);

        return $res;
    }
}

It’s strange… I use the version 3.3.0 (with composer). You are in the same version ?

Thanks you

You copied the right code? Because the mapping refers to a method named getMembers and the method you posted is named get.

Hello

I’ve a class membersController that inherit from a class controller. That’s the reason why you don’t retrieve the good name for the method :wink:

class membersController extends controller
{

    private $table = "members";

    public function getMembers(Request $req, Response $res, $args)
    {
        parent::get($req, $res, $args, $this->table);
    }

I just try to modify my code of membersController :

public function getMembers(Request $req, Response $res, $args)
{
    return $res->withJson(parent::get($req, $res, $args, $this->table));
} 

It’s same result :confused: :

HTTP/1.1 200 OK
Server: xxx
Date: Sun, 08 May 2016 13:25:44 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.5.35
X-Cache: HIT from Backend

You don’t return the response here, you just call the parent. You should put return before parent.

hi,
I tried this but same issue. I will try to rewrite my code step by step to identify the root cause and I will give you the results.

I am very busy on other things this week . I will do this weekend

thank you

Hello,
I think have the same problem; or my problem can be described exactly with this discussion title :slight_smile:

Here’s my minimal working example:

<?php

require ‘vendor/autoload.php’;

// Create and configure Slim app
$app = new \Slim\App;

$app->get(‘/’, function($request, $response, $args) {
$new_response = $response->withJson([‘test’, ‘test2’]);
$content_type = $new_response->getHeader(‘Content-Type’);
echo “\n” . $content_type[0];
return $new_response;
});

$app->run();

$content_type = $app->getContainer()->get(‘response’)->getHeader(‘Content-Type’);
echo “\n” . $content_type[0];

The output after execution is this:
["test","test2"]
application/json;charset=utf-8
text/html; charset=UTF-8

I’ve even tried adding a $app->add( function( ServerRequestInterface $request, ResponseInterface $response, callable $next ) { ... } )); and check the header values before and after the $next($request, $response); call.
The headers are only correct when accessing inside the specific route which was executed. Outside of it, the Content-Type is always the default text/html.

Edit: I’ve installed the framework with the suggested composer require slim/slim "^3.0" command. As of today morning, no updates are available, so I presume I’m at the current version: 3.4-0

Edit 2: One more thing worth mentioning: the browser correctly receives the Content-Type JSON header; and replacing the echos with IFs have no impact, the Content-Type is still text/html. (tested it in case somehow the echoing changes the Content-Type back to text/html)

@zeroxx1986 You dont have a problem. The behaviour is exacly as expected. Your response in the application has the right content type. Outside the application you get a new response object from the container, which has the default content type.

Ah, okay, thank you for clarifying.

I don’t understand why… But i try once again your suggestion

 public function getMembers(Request $req, Response $res, $args)
{
    return parent::get($req, $res, $args, $this->table);
}

It’s works now. May be, i make a mistake during the update on the server. It’s works fine now. May be, it’s because i did update Slim to the 3.4.1 version yesterday. I don’t know

Thanks