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

Geek
  • 8,280
  • 17
  • 73
  • 137
  • This code works for me. – akond Jan 10 '14 at 11:51
  • @akond I still get 200 as status code. Please see the edit. – Geek Jan 10 '14 at 12:06
  • I get `HTTP/1.0 401 Unauthorized`. – akond Jan 10 '14 at 12:17
  • 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? – Xardas Jan 16 '14 at 09:03
  • And try using $this->getResponse() instead of $this->response. – Xardas Jan 16 '14 at 09:06
  • @Xardas I have not set up any redirection. I am not aware of any already set redirection(by framework) though. I tried `getResponse()`, too. – Geek Jan 16 '14 at 09:08
  • Could you post full code of your controller? What class does your controller extend? – Xardas Jan 16 '14 at 09:35
  • @Xardas 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`. – Geek Jan 16 '14 at 10:18
  • @Geek 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. – Xardas Jan 16 '14 at 11:09
  • Actually, first thing i would do, is find all "setStatusCode()" usages in project and Zend, set a debug-break on everyone, and run debug. :) – Xardas Jan 16 '14 at 11:11
  • What is the name of your controller method? Maybe it correlates with some Zend's magical calls? – Xardas Jan 16 '14 at 11:12
  • @Xardas Controller method name is `get()`, which is inherited from `AbstractRESTfulController`. – Geek Jan 16 '14 at 12:59
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/45374/discussion-between-geek-and-xardas) – Geek Jan 16 '14 at 13:23

2 Answers2

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.

Rob Allen
  • 12,643
  • 1
  • 40
  • 49
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.

sroes
  • 14,663
  • 1
  • 53
  • 72
  • 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. – Geek Jan 10 '14 at 13:27
  • 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. – Geek Jan 13 '14 at 12:32
  • No, I don't think so. You sure `setStatusCode` never gets called after your setting it to 401? – sroes Jan 13 '14 at 12:35
  • 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. – Geek Jan 13 '14 at 13:17