liuggio / symfony2-rest-api-the-best-2013-way

Code for the article at:
http://welcometothebundle.com/symfony2-rest-api-the-best-2013-way/
MIT License
150 stars 46 forks source link

PUTting a resource always returns Content-Type "text/html" #12

Open rodrigorigotti opened 9 years ago

rodrigorigotti commented 9 years ago

Hello.

I'm trying to implement a new REST API in my project, but I'm getting the same errors I get when I test liuggio/symfony2-rest-api-the-best-2013-way: the PUT HTTP calls are always returned as text/html (instead of application/json), and fail in the assertJsonResponse assertion. The other methods always return application/json.

Did anyone have the same problem?

PHPUnit 3.7.38 by Sebastian Bergmann.

Configuration read from /Users/rodrigorigotti/Sites/liuggio/symfony2-rest-api-the-best-2013-way/app/phpunit.xml.dist

.....F.F......

Time: 4.93 seconds, Memory: 30.75Mb

There were 2 failures:

1) Acme\BlogBundle\Tests\Controller\PageControllerTest::testJsonPutPageActionShouldModify
Allow:         GET, PUT, PATCH
Cache-Control: no-cache
Date:          Fri, 24 Oct 2014 17:46:27 GMT
Location:      http://localhost/api/v1/pages/16.json
Set-Cookie: MOCKSESSID=5bde664cd92ea4a6054d789e41008cc175afd08a; path=/

Failed asserting that false is true.

/Users/rodrigorigotti/Sites/liuggio/symfony2-rest-api-the-best-2013-way/src/Acme/BlogBundle/Tests/Controller/PageControllerTest.php:199
/Users/rodrigorigotti/Sites/liuggio/symfony2-rest-api-the-best-2013-way/src/Acme/BlogBundle/Tests/Controller/PageControllerTest.php:126

2) Acme\BlogBundle\Tests\Controller\PageControllerTest::testJsonPatchPageAction
Allow:         GET, PUT, PATCH
Cache-Control: no-cache
Date:          Fri, 24 Oct 2014 17:46:27 GMT
Location:      http://localhost/api/v1/pages/18.json
Set-Cookie: MOCKSESSID=8c619cf2c11c32a72a303eb8cd68ba72fbd0becb; path=/

Failed asserting that false is true.

/Users/rodrigorigotti/Sites/liuggio/symfony2-rest-api-the-best-2013-way/src/Acme/BlogBundle/Tests/Controller/PageControllerTest.php:199
/Users/rodrigorigotti/Sites/liuggio/symfony2-rest-api-the-best-2013-way/src/Acme/BlogBundle/Tests/Controller/PageControllerTest.php:175

FAILURES!
Tests: 14, Assertions: 49, Failures: 2.
liuggio commented 9 years ago

I think yould see on the configuration of fosrest on the format type part https://github.com/FriendsOfSymfony/FOSRestBundle/blob/master/Resources/doc/configuration-reference.md because I think this project is not updated with the latest improvment...

daveharding commented 9 years ago

I'm having this same problem, did you find a solution?

bblue commented 8 years ago

This is an old topic, but I am getting the same errors. Did you find a solution?

bblue commented 8 years ago

Update: Tried returning a view object directly. It still gets converted to text/html even when I explicitly set headers to application/json. I have no idea what is going on...

I have never been using Symfony before and I am still experimenting, but I might have found the source of the issue, but no real solution yet.

By forcing redirects also for json I am getting the correct content type (but then the wrong status code).

# config.yml
fos_rest:
     view:
        force_redirects:
            json: true

This leads me to believe something bad happens when the redirect in the PageController does not redirect because we are requesting a json reply.

For instance:

# Pagecontroller::putPageAction()
(...)
return $this->routeRedirectView('api_1_get_page', $routeOptions, $statusCode);

This appears to be related: https://github.com/FriendsOfSymfony/FOSRestBundle/issues/500

bblue commented 8 years ago

A few hours into debugging now.. a little wiser.

It appears that the PUT request is correctly setting content headers as long as the http response code is anything but 204. This is caused by PHP or your web server, see the two links below for explanations.

See here: https://github.com/symfony/symfony/issues/12744 and here: https://github.com/symfony/symfony/pull/11244

I am still trying to figure out what response to return, but I will very probably do something along the lines of this:

      if ($this->get('fos_rest.view_handler')->isFormatTemplating($request->getRequestFormat())) {
            return $this->routeRedirectView('api_1_get_page', $routeOptions, $statusCode);
        } else {
            $uri = $this->get('router')->generate('api_1_get_page', $routeOptions);
            return $this->view()->setStatusCode($statusCode)->setFormat($request->get('_format'))->setLocation
            ($uri);
        }

Key here is that html is being rerouted, while any other format is provided with a response header with the address of the resource in the location header. What led me to this is mainly. http://stackoverflow.com/questions/13635181/is-http-303-acceptable-for-other-http-methods and http://stackoverflow.com/questions/2427518/which-http-redirect-status-code-is-best-for-this-rest-api-scenario , but no one seems to agree on the correct http status codes to return for these request types. I am now returning HTTP_CREATED as before, but I changed HTTP_NO_CONTENT to HTTP_SEE_OTHER