symfony-cmf / Routing

Routing component building on the Symfony Routing component
Other
288 stars 69 forks source link

No matching accepted Response format could be determined error #106

Closed asiragusa closed 10 years ago

asiragusa commented 10 years ago

Hi guys, this is the setup I have:

My route:

        $type = new Route;
        $type->setPosition($parent, 'type');
        $type->setContent($page);
        $type->setVariablePattern('.{_format}');
        $type->setDefault('_format', 'html');
        $type->setDefault('type', 'default_type');
        $dm->persist($type);        

and my controller action:

    public function typeAction($contentDocument, $_format)
    {
        if (!$contentDocument) {
            throw new NotFoundHttpException('Content not found');
        }
    $params = array(
        'cmfMainContent' => $contentDocument
    );

        return $this->renderResponse('MyBundle:Default:index.html.twig', $params);
}

If I use the URL http://mysite.com/type.json and http://mysite.com/type.html everything works fine, but http://mysite.com/type throws the following error:

No matching accepted Response format could be determined, while handling: Format '' not supported, handler must be implemented

Digging into the code I found this:

In FOS\RestBundle\View\ViewHandler:

    public function handle(View $view, Request $request = null)
    {
        if (null === $request) {
            $request = $this->container->get('request');
        }

        $format = $view->getFormat() ?: $request->getRequestFormat();

        if (!$this->supports($format)) {
            $msg = "Format '$format' not supported, handler must be implemented";
            throw new UnsupportedMediaTypeHttpException($msg);
        }
...

And $request->getRequestFormat() here should return html, as:

public function getRequestFormat($default ='html')
{
if (null === $this->format) {
$this->format = $this->get('_format', $default);
}

but instead of the default 'html' value null is returned. Am I doing something wrong or there is a bug somewhere in the router?

Thanks

dbu commented 10 years ago

i think at least the phpcr route document found in the RoutingBundle has a special option to control whether the format should be appended. see http://symfony.com/doc/master/cmf/bundles/routing/dynamic.html#the-phpcr-odm-route-document and https://github.com/symfony-cmf/RoutingBundle/blob/master/Model/Route.php#L69-L71 (you can also call setOption defined by the symfony Route class the cmf route class is extending)

could it be your route ended up not looking exactly like you expected? you could try to debug what the pattern looks like in https://github.com/symfony-cmf/Routing/blob/master/NestedMatcher/NestedMatcher.php#L141

asiragusa commented 10 years ago

I tried using the add_format_pattern option and now it works for /type and for /type.html, but not for /type.json, as expected: https://github.com/symfony-cmf/RoutingBundle/blob/master/Model/Route.php#L83

        $type = new Route(array(
            'add_format_pattern' => true
        ));
        $type->setPosition($parent, 'type');
        $type->setContent($page);
        $type->setDefault('type', 'default_type');
        $dm->persist($type);

How can I make it work with json too?

asiragusa commented 10 years ago

Well my question was finally dumb :)

        $type = new Route(array(
            'add_format_pattern' => true
        ));
        $type->setPosition($parent, 'type');
        $type->setContent($page);
        $type->setDefault('type', 'default_type');
        $type->setRequirement('_format', 'html|json');

By the way it would be nice to be able to express this like:

        $type = new Route(array(
            'add_format_pattern' => ('html', 'json')
        ));
//OR
        $type = new Route(array(
            'add_format_pattern' => ('html' => true, 'json' => true)
        ));

Anyway thanks a lot for your help

dbu commented 10 years ago

glad you could solve it.

indeed, your proposal would be nice. if you want to do a PR, feel free. i would extract the pattern right in the constructor and overwrite the setOption to handle this case, and clean the stored value to become true, setting the format requirement automatically. and you could update the documentation over at symfony-cmf-docs to mention the possibility (i think right now we don't really explain the add_format_pattern with any example, but i might be wrong)

asiragusa commented 10 years ago

Yep, it's not documented, otherwise I wouldn't have struggled ;)

At the moment I am really busy finishing the Symfony porting of my CMS, I will do the PR once I will have some free time