简体   繁体   中英

Response::json() sending html instead of json

Using Laravel 4, return Response::json(array('foo' => 'bar')) used in one controller will return actual application/json , whereas in another controller, for another action, it will return text/html . Both actions are called via Ajax.

In the faulty controller , I tried to force the content-type with this snippet:

[...]

$response = Response::json($data);
$response->header('Content-Type', 'application/json');
$response->header('Content-Foo', 'Bar'); // test if additional headers are really set
Log::info($response);
return $response;

... while working controller returns correct Json response with:

return Response::json($data);

In both, $data is an array (tested).

Logged response from the faulty controller is:

HTTP/1.0 200 OK
Cache-Control: no-cache
Content-Foo:   Bar
Content-Type:  application/json
Date:          Wed, 17 Sep 2014 10:55:03 GMT

But received response (in Firebug / DevTools) is:

Connection  Keep-Alive
Content-Type    text/html
Date    Wed, 17 Sep 2014 10:55:03 GMT
Keep-Alive  timeout=5, max=93
Server  Apache/2.2.25 (Unix) mod_ssl/2.2.25 OpenSSL/0.9.8y DAV/2 PHP/5.5.3
Transfer-Encoding   chunked
X-Powered-By    PHP/5.5.3

I tried to directly return Response::json(array('foo' => 'bar')) at the beginning of the faulty controller action but it still sends the response as text/html .

I would like to know why would the content-type switch from application/json to text/html for no reason? And why the mock header isn't in the received response?

-- EDIT --

The problem seems to be located around the validator.

public function faultyAction()
{
    if(!Request::ajax()) App::abort(405);

    $validator = Validator::make(
        array('trackfile' => Input::file('trackfile')),
        array('trackfile' => 'required|audio')); // audio is a custom validator

    if($validator->fails())
    {
        Log::info('validation failed!');
        return Response::json(array('code' => 1, 'message' => 'File validation has failed.'));
    } 
    else
    {
        Log::info('validation passed!');
        return Response::json(array('code' => 0, 'filename' => 'test'));
    }
}

... returns text/html response while validation passed .

public function faultyAction()
{
    if(!Request::ajax()) App::abort(405);

    $validator = Validator::make(
        array('trackfile' => Input::file('trackfile')),
        array('trackfile' => 'required|audio')); // audio is a custom validator

    return Response::json(array('code' => 0, 'filename' => 'test'));
}

... returns application/json .

How comes the same response is returned with different content-type depending on where it is called in the code?

May it come from $validator->fails() (even if nothing seems to alter the headers or to print something in the Laravel's Validator.php code)?

Hi basically using Response::json() with an array of data as parameter is enough. Defining again the Content-type header is useless, Response::json is supposed to set it right by default.

I'm creating json responses on my project right now and so far it went fine. Just to be clear the faulty controller returns the good value with a wrong content-type header, right ? Can you try again using just Response::json and can you tell which exact laravel version are you using ?

Hi again i'm editing my first answer based on your replies : you should test something like this :

$json = json_encode($yourArray);

// first check the $json variable with var_dump() oro Log::info() to see if you have the space problem. Then you can create the response.

$response = Response::make($json, 200);

$response->header('Content-Type', 'application/json');

return $response;

Hope it helps...

It may not be the case for OP, but this is a best search result for json response sent as text/html . I just spent considerable amount of time debugging this issue in Laravel 9 with php 8.2

One possible reason for wrong content type is hidden somewhere in php magic goo. In another words, how it handles sending response headers.

If you have whitespace anywhere before or after php opening or closing tag, respectively, the headers will be sent and you cant modify them anymore. This is why it is recommended to not use php closing tag in multi file applications, but this does not help for whitespace before opening tag:


 <?php

Now if your framework, like Laravel, checks with headers_sent() , before modifying headers for you, the result is, drumm roll: text/html, with no errors anywhere.

To identify the problem, try setting headers yourself, with header() , somewhere at the end of call stack. It should then fail and tell you in which file the headers are already sent. For me the culprit was hidden in one of the lang files.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM