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.
Related
I have a problem when I am trying to POST data to third party API. I'm getting an error
yii\base\ErrorException: Header may not contain more than a single header, new line detected in /www/wwwroot/xxx/vendor/yiisoft/yii2/web/Response.php:382
As far as I know yii manages headers by itself and I added additional headers for auth purposes.
My additional headers:
protected function getHeaders($data = [])
{
ksort($data);
reset($data);
$ts = microtime().rand(0, 10000);
return [
'login: '.$this->login,
'ts: '.$ts,
'sig: '.md5($ts.$this->apiKey),
];
}
Code works in pure php tests, but not inside yii app.
I already tried to log response and request headers, didn't find any duplicated headers.
Only something like this one:
'CONTENT_TYPE' => 'application/json; charset=utf-8'
But I don't know if this counts for multiple headers.
The problem was on the API provider's side. My requests were not passing authentication, and I was getting back gibberish with incorrect headers.
In my controller action, I have this:
$pdf = $this->Invoice->makePdf($invoice);
$this->response->charset('UTF-8');
$this->response->body($pdf);
$this->response->type(array('pdf' => 'application/x-pdf'));
$this->response->disableCache();
$this->response->send();
However, no matter what I do, CakePHP always sends the data as text/html; charset=utf-8. I have also tried
$this->response->header(array('Content-Type' => 'application/x-pdf'));
But it still sent it as text/html. How can I force the response to be sent using the content type above?
Doing $this->response->type(array('pdf' => 'application/x-pdf')); stores/replaces the content type for the associated key as mentioned in the api. Use $this->response->type('pdf'); to set the type.
Edit: Also don't call $this->response->send(); just return the response object return $this->response; and let the dispatcher handle the sending.
Symfony 2 is displaying cache headers, i was wondering how i could hide those
examples
HTTP/1.0 200 OK Cache-Control: no-cache Content-Type: text/html Date: Fri, 18 Jan 2013 19:07:08 GMT HTTP/1.0 200 OK Cache-Control: no-cache Date: Fri, 18 Jan 2013 19:07:08 GMT X-Debug-Token: 50f99d5cba4da
i am using this in my code
return new Response($this->renderView('Shout/view/default.html.twig'));
which gets called by
$httpKernel = $this->container->get('http_kernel');
$response = new Response;
$response->SetContent($httpKernel->forward('MyBundle:Module/'.$module.'/'.$module.':index'));
$response->headers->set('Content-Type', 'text/html');
return $response;
in a twig extension
Add ->getContent() to end.
http://api.symfony.com/2.0/Symfony/Component/HttpFoundation/Response.html
$response = $this->forward("MyBundle:Module:$module", array(
'customer_id' => $customer_id
))->getContent();
return $response;
Headers are part of the Response class inside HttpFoundation. You can manage them using the headers attribute, the same one you used in your code. That attribute is an instance of the ResponseHaderBag class, which has a remove function.
The header you want to remove is named 'Cache-Control', so if you write:
$response->headers->remove('Cache-Control');
It will remove that header. But if you check the source of Response, you will see that some of it's functionality depends on this header, so I'm not sure that removing this is really a good idea.
By default this header does nothing wrong, just returns 'no-cache', which means the browser won't cache your page. But you won't be able to cache a page without this header.
If your goal is to manually send the cache-control header yourself, consider using Symfony2's built in functionality instead.
For everyone that is looking for an answer, i continued on the above post and tried to use the render function from twig but with my custom module
this is was i got and it works fine :)
return $this->container->get('templating.helper.actions')->render('MyBundle:Module/'.$module.'/'.$module.':index', $attributes, $options);
Using PHP Zend Framework 2.0.2, I return JSON data after an AJAX call. Obviously, Internet Explorer 9 wants to download the data instead of returning it to the calling Javascript method.
Posts like this one and this one say to use Content-Type: text/plain instead of Content-Type: application/json, but how do I do this with ZF2's JsonModel? I'm new to it...
I imagine I have to set something in the setOptions() array, but what?
public function testJsonAction()
{
$jsonResponse = new JsonModel(array('success' => false));
$jsonResponse->setOptions(array(
// ** Should I put something here? What? **
));
return $jsonResponse;
}
I tried using these:
$this->getResponse()->getHeaders()->addHeaderLine('Content-Type', 'text/plain');
$this->getResponse()->getHeaders()->addHeaderLine('Content-Disposition', 'inline; filename="textdata.json"');
but it doesn't change the HTTP Content-Type in the response headers:
Key Value
Response HTTP/1.1 200 OK
Content-Type application/json
Server Microsoft-IIS/7.5
X-Powered-By PHP/5.3.13
Set-Cookie ZDEDebuggerPresent=php,phtml,php3; path=/
Content-Disposition inline; filename="textdata.json"
X-Powered-By ASP.NET
Date Wed, 10 Oct 2012 13:19:42 GMT
Content-Length 17
Thanks for your help!
Because when \Zend\Mvc\MvcEvent::EVENT_RENDER event happen, the JsonStrategy will change content-type again. Source code is in
Zend\View\Strategy\JsonStrategy->injectResponse();
So in order to replace content-type into yours, you need to use EventManager to inject your custom header after JsonStrategy injected.
try below codes in your controller:
$this->getServiceLocator()->get('Application')->getEventManager()->attach(\Zend\Mvc\MvcEvent::EVENT_RENDER, function($event){
$event->getResponse()->getHeaders()->addHeaderLine('Content-Type', 'text/plain');
}, -10000);
How to check whether a page has been updated without downloading the entire webpage in Php? Whether I need to look in at the header?
One possibility is to check the LastModified header. You can download just the headers by issuing a HEAD request. The server responds back with the HTTP headers only and you can inspect the last modified header and/or the content length header to detect changes.
Last-modified "Mon, 03 Jan 2011 13:02:54 GMT"
One thing to note is that the HTTP server does not need to send this header so this would not work in all cases. The PHP function get_headers will fetch these for you.
// By default get_headers uses a GET request to fetch the headers. If you
// want to send a HEAD request instead, you can do so using a stream context:
stream_context_set_default(
array(
'http' => array(
'method' => 'HEAD'
)
)
);
$headers = get_headers('http://example.com');
You can add a If-Modified-Since: <datetime> header to your request, and the server should return a 304 Not Modified if it hasn't changed since then. But if the document is generated dynamically (php, perl, etc.), the generator could be too lazy to check this header and always return the full document.