Closed roelleor closed 6 years ago
This should work as expected.
At first, you must uncomment the line prefix
. And do you load this controller somewhere else ?
Nope, not loading the controller somewhere else. Good that you're checking, but I used it uncommented :) My config:
fos_rest:
routing_loader:
default_format: json
format_listener:
enabled: true
versioning:
enabled: true
view:
view_response_listener: force
formats:
json: true
jsonp: false
xml: false
rss: false
to add: it does work well when using the version as a parameter
On 01 Jul 2016, at 13:16, Guilhem N notifications@github.com wrote:
This should works as expected. At first, you must uncomment the line prefix. Do you load this controller somewhere else ?
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/FriendsOfSymfony/FOSRestBundle/issues/1529#issuecomment-229922098, or mute the thread https://github.com/notifications/unsubscribe/AC-MigxR-7lA68BOZ2SwS9EUIRUMsL1Tks5qRPb2gaJpZM4JC-xX.
In fact, you don't need the versioning feature of this bundle if you only use a path parameter. What do you mean by not working ? You can't access your controller ?
it gives a "No route found” error Perhaps you are right that one doesn’t strictly need it. One could just hard code the prefix. It’s not that much work, I’ll just go for that route then. FYI, this approach of having {version} as a parameter in the path is in the documentation. However, not in combination with the ClassResourceInterface.
On 01 Jul 2016, at 14:04, Guilhem N notifications@github.com wrote:
In fact, you don't need the versioning feature of this bundle if you use a path parameter. What do you mean by not working ? You can't access your controller ?
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/FriendsOfSymfony/FOSRestBundle/issues/1529#issuecomment-229929837, or mute the thread https://github.com/notifications/unsubscribe/AC-MiuOvatI-4vVa0df_AtKKDW4ZtKH_ks5qRQJQgaJpZM4JC-xX.
Same issue here
# app/config/routing.yml
api:
resource: "@ApiBundle/Resources/config/routes.yml"
type: rest
prefix: /api/{version}
and then
# src/ApiBundle/Resources/config/routes.yml
products:
type: rest
resource: ApiBundle\Controller\ProductController
name_prefix: api_
shops:
type: rest
resource: ApiBundle\Controller\ShopController
name_prefix: api_
When trying to access /api/v1/shops
, a "no route found" exception is thrown. Note that this stopped working after I upgraded from 2.0.0-BETA
to 2.0.0
. Not to mention it's in the docs, like @roelleor said.
Bumping this issue, as it's happening to me aswell, same case as @tetele
Can you try finding the corresponding route with bin/console debug:router
?
@Ener-Getick
vagrant@mymachine:/vagrant$ app/console debug:router get_categories
+--------------+--------------------------------------------------------------------+
| Property | Value |
+--------------+--------------------------------------------------------------------+
| Route Name | get_categories |
| Path | /frontend/api/{tube}/{version}/categories |
| Path Regex | #^/frontend/api/(?P<tube>[^/]++)/(?P<version>[^/]++)/categories$#s |
| Host | ANY |
| Host Regex | |
| Scheme | ANY |
| Method | GET |
| Requirements | NO CUSTOM |
| Class | Symfony\Component\Routing\Route |
| Defaults | _controller: ApiBundle:Frontend\V1\Category:cget |
| | _format: json |
| Options | compiler_class: Symfony\Component\Routing\RouteCompiler |
+--------------+--------------------------------------------------------------------+
Should be noted aswell that in the profiler the symfony matcher complains about attributes.get('version')
not being equal to v1
(my version).
@Lumbendil What is the exact path that you are trying? What output do you get when using the router:match
command with that path?
@xabbuh answer from memory.
The path I tried was /frontend/api/something/v1/categories
, there was no match, and on symfony debug, when inspecting, it said something along "get_categories" route is a close match but version doesn't match the requirements (the route version was being overriden by the listener).
It should be noted that adding ?version=v1
did make the route match.
I am sorry to bump this issue, but was this ever resolved or a hotfix/bypass found? I'm currently running into this problem myself, well the prefix part at least.
Observation:
The reason this seems to go wrong because the Request given to match
-function of the RedirectableUrlMatcher
-class does not contain any attributes.
Reproduce:
I tested this by accessing a route like /api/{version}/emails
where {version}
is v1
and dumped the incoming request in appDevDebugProjectContainerUrlMatcher
. The request contained no attributes, request or query values, thus making the matching of a route with a prefix impossible.
Strange behaviour:
When the Request is passed to one of my controllers, $request->attributes->get('version')
does return v1
, which seems to suggest that the URL hasn't been fully parsed when it's given to the class extending RedirectableUrlMatcher
.
If someone of you could provide a small project that makes it possible to reproduce your issue, we could look into where the issue actually lies and try to solve it. That would be great. :)
@xabbuh I'll get a small example up and running after lunch. ;)
@xabbuh Here you go: https://github.com/hipio/FosRestBundleFoc
echo "Version: " . $request->attributes->get('version', 'null');
on line 109 in appDevDebugProjectContainerUrlMatcher
(once generated) shows that the Request object really is empty.#
from routing.yml
on line 5 you'll be able to see that the Request object that the controller receives does contain the version
parameter. 0 === strpos($pathinfo, '/api') && preg_match('#^/api/(?P
[^/]++)/test(?:\.(?P<_format>json|xml|html))?$#s', $pathinfo, $matches)
Seems to work fine so it really is in_array($request->attributes->get("version"), array(0 => "v1"))
that fails in appDevDebugProjectContainerUrlMatcher
. Which brings me back to my previous comment stating that somehow the URL isn't fully parsed (if that makes sense) when it's passed to appDevDebugProjectContainerUrlMatcher
.
I hope this helps a bit. When you find the issue, could you let me know?
The problem is linked with priority of kernel.request event listeners
$request->attributes->get("version")
in VersionListener (priority 33) will never take into account the value of {version} url placeholder, as this will be defined later in Symfony RouterListener (priority 32).request.attributes.get('version') in [...]
. These conditions are evaluated by Symfony RouterListener (priority 32), but at the time of evaluation, request.attributes.get('version') is still empty for url placeholders. The RequestMatcherInterface will throw a ResourceNotFoundException before the url placeholder value is stored in request attributes. This explain issue #1491To resolve all these problems at the same time, I think we need to:
I will propose a PR that fix issues #1491 and #1529
Are there any workarounds for URI versioning? It still seems not to work, only query and header versioning works
Yes, still not working URI versioning. Why it happens and how I can help to fix this (maybe, we need new resolver for this)?
You can simply add your own onKernelRequest
listener to work around the problem described by @juillerat.
namespace AppBundle\EventListener;
use FOS\RestBundle\View\ConfigurableViewHandlerInterface;
use FOS\RestBundle\View\ViewHandlerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class VersionListener
{
private $viewHandler;
public function __construct(ViewHandlerInterface $viewHandler)
{
$this->viewHandler = $viewHandler;
}
private function resolveVersion(Request $request)
{
$version = $request->attributes->get('version');
return is_scalar($version) ? $version : strval($version);
}
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
$version = str_replace('v', '', $this->resolveVersion($request));
$request->attributes->set('version', $version);
if ($this->viewHandler instanceof ConfigurableViewHandlerInterface) {
$this->viewHandler->setExclusionStrategyVersion($version);
}
}
}
app.version_listener:
class: Acme\AppBundle\EventListener\VersionListener
tags:
- { name: kernel.event_listener, event: kernel.request, priority: 30 }
+1
Was this problem ever resolved? I'm running into the same issue as @roelleor. I'm going to try the workaround but would like to configure it as documented.
+1
+1
+1
It doesn't seem possible to use uri versioning (/v1/users) with a controller implementing the ClassResourceInterface, is that correct? Or am I missing something? route: