Zend framework 2 : not able to send desired status code in response
Asked Answered
T

2

5

I am building REST API on Zend Framework 2. I want to send certain status code in response whenever any error has occurred.

I tried below in my controller :

$statusCode = 401;
$this->response->setStatusCode($statusCode);
return new JsonModel(array("error message" => "error description"));

Echoing status code prints 401, but client-side application gets status code 200 every time.

How can I set status code to particular value?

Module.php :

class Module 
{
    public function getAutoloaderConfig()
    {
        return array(
                     'Zend\Loader\ClassMapAutoloader' => array(
                                                               __DIR__ . '/autoload_classmap.php',
                                                               ),
                     'Zend\Loader\StandardAutoloader' => array(
                                                               'namespaces' => array(
                                                                                     __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                                                                                     ),
                                                               ),
                     );
    }

    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }

}

EDIT : Below is how the response looks : enter image description here

Trichinize answered 10/1, 2014 at 10:49 Comment(13)
This code works for me.Padron
@Padron I still get 200 as status code. Please see the edit.Trichinize
I get HTTP/1.0 401 Unauthorized.Padron
I advice checking your web-server setup. There might be some redirection configured or http-code is forced. Also, have you tried using other status codes?Lawabiding
And try using $this->getResponse() instead of $this->response.Lawabiding
@Lawabiding I have not set up any redirection. I am not aware of any already set redirection(by framework) though. I tried getResponse(), too.Trichinize
Could you post full code of your controller? What class does your controller extend?Lawabiding
@Lawabiding I am simply placing 3 lines of code(which is posted in question) in my controller. I have created an abstract controller myController, which extends AbstractRestfulController. All controllers then extend myController.Trichinize
@Trichinize Is it possible, that there is output start somewhere before your controller code is executed? I assume, that status code should be sent before any response text, with other http-headers. Is it possible, that you missed a line-break at start of some file, or there is a notice missed? I would also try changing response status code with another parent controller. And, at last, debugging must show, when status code is changed to 200 in response object.Lawabiding
Actually, first thing i would do, is find all "setStatusCode()" usages in project and Zend, set a debug-break on everyone, and run debug. :)Lawabiding
What is the name of your controller method? Maybe it correlates with some Zend's magical calls?Lawabiding
@Lawabiding Controller method name is get(), which is inherited from AbstractRESTfulController.Trichinize
let us continue this discussion in chatTrichinize
P
8

I've just tested this with a simple example project at https://github.com/akrabat/zf2-api-response-code

In a controller that extends AbstractRestfulController, you can certainly use

<?php
namespace Application\Controller;

use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;

class IndexController extends AbstractRestfulController
{
    public function create($data)
    {
        $this->response->setStatusCode(401);
        return new JsonModel(array("message" => "Please authenticate!"));
    }
}

Testing via curl, I get this:

$ curl -v -X POST http://zf2-api-example.localhost/
* Adding handle: conn: 0x7f880b003a00
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f880b003a00) send_pipe: 1, recv_pipe: 0
* About to connect() to zf2-api-example.localhost port 80 (#0)
*   Trying 127.0.0.1...
* Connected to zf2-api-example.localhost (127.0.0.1) port 80 (#0)
> POST / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: zf2-api-example.localhost
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Date: Fri, 17 Jan 2014 10:02:47 GMT
* Server Apache is not blacklisted
< Server: Apache
< Content-Length: 34
< Content-Type: application/json; charset=utf-8
<
* Connection #0 to host zf2-api-example.localhost left intact
{"message":"Please authenticate!"}

As you can see, the response code set is 401. If you're not getting this with your application, please check my example on github and see if that one works with your server.

Procurator answered 17/1, 2014 at 10:6 Comment(0)
W
0

Try this:

$statusCode = 401;
$response = $this->response;
$response->setStatusCode($statusCode);
$response->setContent(new JsonModel(array("error message" => "error description")));
return $response;

If this does not work, there might be an onDispatch event handler which overwrites the status code again. Check your Module.php's.

Weevil answered 10/1, 2014 at 12:23 Comment(4)
I use the same code. I don't have onDispatch event handler in Module.php file. I have added its code to my question. I don't know why, but it worked yesterday for some times and then after some point it gives 200 only.Trichinize
Is it related to the thing that response is object of class \Zend\Http\PhpEnvironment\Response or \Zend\Http\Response? Doing var_dump($this->response) says that it is \Zend\Http\PhpEnvironment\Response object.Trichinize
No, I don't think so. You sure setStatusCode never gets called after your setting it to 401?Weevil
Actually I return the response just after setting the status code. So I can say that there is not code overriding status code value. I am new to zend so if there is something happening behind the screen then I have very less idea about it.Trichinize

© 2022 - 2024 — McMap. All rights reserved.